From bda7d0e7ee75b5ee729bca4f565cc598f7c04b6d Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Thu, 5 Dec 2024 11:23:24 +0100 Subject: [PATCH 01/12] notes are rendered as HTML --- CHANGELOG | 4 +++- .../Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx | 6 +++++- .../Drawer/ReactionDrawer/ReactionDrawer.component.tsx | 9 ++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 164d4397..a0285e6e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,10 @@ minerva-front (18.0.5) stable; urgency=medium * Bug fix: anchor overlays were disappearing after clicking on anchor and outside of the anchor (#319) + * Bug fix: bioEntity HTML notes in the left panel were not rendered as html + (#323) - -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 27 Nov 2024 13:00:00 +0200 + -- Piotr Gawron <piotr.gawron@uni.lu> Thu, 05 Dec 2024 13:00:00 +0200 minerva-front (18.0.4) stable; urgency=medium * Bug fix: link to search result from overview image caused map not to diff --git a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx index 14fc5449..1e54091e 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx @@ -14,6 +14,7 @@ import { DrawerHeading } from '@/shared/DrawerHeading'; import { ElementSearchResultType } from '@/types/models'; import { CommentItem } from '@/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component'; import { ModificationResidueItem } from '@/components/Map/Drawer/BioEntityDrawer/ModificationResidueItem'; +import React from 'react'; import { CollapsibleSection } from '../ExportDrawer/CollapsibleSection'; import { AnnotationItem } from './AnnotationItem'; import { AssociatedSubmap } from './AssociatedSubmap'; @@ -73,7 +74,10 @@ export const BioEntityDrawer = (): React.ReactNode => { {bioEntityData.notes && ( <span> <hr className="border-b border-b-divide" /> - <div className="text-sm font-normal">{bioEntityData.notes}</div> + <div + className="text-sm font-normal" + dangerouslySetInnerHTML={{ __html: bioEntityData.notes }} + /> </span> )} {isModificationAvailable && ( diff --git a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx index 1423ef7d..f772343e 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx @@ -8,6 +8,7 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { currentDrawerReactionCommentsSelector } from '@/redux/bioEntity/bioEntity.selectors'; import { CommentItem } from '@/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component'; import { ZERO } from '@/constants/common'; +import React from 'react'; import { ReferenceGroup } from './ReferenceGroup'; import { ConnectedBioEntitiesList } from './ConnectedBioEntitiesList'; @@ -37,7 +38,13 @@ export const ReactionDrawer = (): React.ReactNode => { Type: <b className="font-semibold">{reaction.type}</b> </div> <hr className="border-b border-b-divide" /> - {reaction.notes && <div className="text-sm font-normal">{reaction.notes}</div>} + {reaction.notes && ( + <div + className="text-sm font-normal" + dangerouslySetInnerHTML={{ __html: reaction.notes }} + /> + )} + <h3 className="font-semibold">Annotations:</h3> {referencesGrouped.map(group => ( <ReferenceGroup key={group.source} group={group} /> -- GitLab From 44c9e0010363d6d24179e1540d80f16df3c794fd Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Fri, 6 Dec 2024 10:39:08 +0100 Subject: [PATCH 02/12] Update CHANGELOG --- CHANGELOG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index a0285e6e..37a544e7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +minerva-front (18.0.6) stable; urgency=medium + + * No changes in frontend + +-- Piotr Gawron <piotr.gawron@uni.lu> Fri, 06 Dec 2024 13:00:00 +0200 + minerva-front (18.0.5) stable; urgency=medium * Bug fix: anchor overlays were disappearing after clicking on anchor and outside of the anchor (#319) -- GitLab From 5faa81bfee166317bffc7b94f522de83c6fb3f14 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Wed, 11 Dec 2024 08:44:57 +0100 Subject: [PATCH 03/12] export to image should include overlays --- CHANGELOG | 5 +++++ .../ExportCompound/ExportCompound.component.tsx | 3 +++ .../ExportCompound/utils/getGraphicsDownloadUrl.test.ts | 6 +++++- .../ExportCompound/utils/getGraphicsDownloadUrl.ts | 6 +++++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 37a544e7..25728623 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +minerva-front (18.0.7) stable; urgency=medium + * Bug fix: export to image did not include overlays (#326) + +-- Piotr Gawron <piotr.gawron@uni.lu> Wed, 11 Dec 2024 13:00:00 +0200 + minerva-front (18.0.6) stable; urgency=medium * No changes in frontend diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx index f5803c10..e33a99ed 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx @@ -5,6 +5,7 @@ import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { modelsDataSelector, modelsIdsSelector } from '@/redux/models/models.selectors'; import { ReactNode, useCallback, useMemo, useState } from 'react'; +import { activeOverlaysIdSelector } from '@/redux/overlayBioEntity/overlayBioEntity.selector'; import { CheckboxItem } from '../CheckboxFilter/CheckboxFilter.types'; import { Annotations } from './Annotations'; import { DownloadElements } from './DownloadElements/DownloadElements'; @@ -33,6 +34,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { const modelIds = useAppSelector(modelsIdsSelector); const currentModels = useAppSelector(modelsDataSelector); const currentBackground = useAppSelector(currentBackgroundSelector); + const overlays = useAppSelector(activeOverlaysIdSelector); const [annotations, setAnnotations] = useState<CheckboxItem[]>([]); const [includedCompartmentPathways, setIncludedCompartmentPathways] = useState<CheckboxItem[]>( [], @@ -76,6 +78,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { modelId: models?.[FIRST_ARRAY_ELEMENT]?.id, handler: imageFormats?.[FIRST_ARRAY_ELEMENT]?.id, zoom: getModelExportZoom(imageSize.width, model), + overlayIds: overlays.map(overlayId => `${overlayId}`), }); if (url) { diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.test.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.test.ts index 2e6c4db9..e621890a 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.test.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.test.ts @@ -3,10 +3,11 @@ import { GetGraphicsDownloadUrlProps, getGraphicsDownloadUrl } from './getGraphi describe('getGraphicsDownloadUrl - util', () => { const cases: [GetGraphicsDownloadUrlProps, string | undefined][] = [ - [{}, undefined], + [{ overlayIds: [] }, undefined], [ { backgroundId: 50, + overlayIds: [], }, undefined, ], @@ -14,6 +15,7 @@ describe('getGraphicsDownloadUrl - util', () => { { backgroundId: 50, modelId: '30', + overlayIds: [], }, undefined, ], @@ -22,6 +24,7 @@ describe('getGraphicsDownloadUrl - util', () => { backgroundId: 50, modelId: '30', handler: 'any.handler.image', + overlayIds: [], }, undefined, ], @@ -31,6 +34,7 @@ describe('getGraphicsDownloadUrl - util', () => { modelId: '30', handler: 'any.handler.image', zoom: 7, + overlayIds: [], }, `${BASE_API_URL}/projects/${PROJECT_ID}/models/30:downloadImage?backgroundOverlayId=50&handlerClass=any.handler.image&zoomLevel=7`, ], diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.ts index c4020e98..169265ea 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.ts @@ -5,6 +5,7 @@ export interface GetGraphicsDownloadUrlProps { modelId?: string; handler?: string; zoom?: number; + overlayIds: string[]; } export const getGraphicsDownloadUrl = ({ @@ -12,6 +13,7 @@ export const getGraphicsDownloadUrl = ({ modelId, handler, zoom, + overlayIds, }: GetGraphicsDownloadUrlProps): string | undefined => { const isAllElementsTruthy = [backgroundId, modelId, handler, zoom].reduce( (a, b) => Boolean(a) && Boolean(b), @@ -22,5 +24,7 @@ export const getGraphicsDownloadUrl = ({ return undefined; } - return `${BASE_API_URL}/projects/${PROJECT_ID}/models/${modelId}:downloadImage?backgroundOverlayId=${backgroundId}&handlerClass=${handler}&zoomLevel=${zoom}`; + const overlays = overlayIds.join(','); + + return `${BASE_API_URL}/projects/${PROJECT_ID}/models/${modelId}:downloadImage?backgroundOverlayId=${backgroundId}&handlerClass=${handler}&zoomLevel=${zoom}&overlayIds=${overlays}`; }; -- GitLab From 972c905e555e46bb097a0ed58e39985c777723b3 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Wed, 11 Dec 2024 08:59:33 +0100 Subject: [PATCH 04/12] fix tests --- .../ExportCompound/utils/getGraphicsDownloadUrl.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.test.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.test.ts index e621890a..a4e4c59d 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.test.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.test.ts @@ -34,9 +34,9 @@ describe('getGraphicsDownloadUrl - util', () => { modelId: '30', handler: 'any.handler.image', zoom: 7, - overlayIds: [], + overlayIds: ['107'], }, - `${BASE_API_URL}/projects/${PROJECT_ID}/models/30:downloadImage?backgroundOverlayId=50&handlerClass=any.handler.image&zoomLevel=7`, + `${BASE_API_URL}/projects/${PROJECT_ID}/models/30:downloadImage?backgroundOverlayId=50&handlerClass=any.handler.image&zoomLevel=7&overlayIds=107`, ], ]; -- GitLab From eb710e2815ce2301509cf5e0feff78a3cd548eb5 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Wed, 11 Dec 2024 10:20:53 +0100 Subject: [PATCH 05/12] bump tailwind dependency --- package-lock.json | 22 +++++++++++----------- package.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 095755a0..95f24b71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "react-redux": "8.1.3", "sonner": "1.4.3", "tailwind-merge": "1.14.0", - "tailwindcss": "3.3.3", + "tailwindcss": "3.4.13", "ts-deepmerge": "6.2.0", "use-debounce": "9.0.4", "uuid": "9.0.1", @@ -13020,19 +13020,19 @@ } }, "node_modules/tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.18.2", + "jiti": "^1.21.0", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", @@ -23497,19 +23497,19 @@ "integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==" }, "tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", "requires": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.18.2", + "jiti": "^1.21.0", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", diff --git a/package.json b/package.json index 01cbb2f8..9255d88b 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "react-redux": "8.1.3", "sonner": "1.4.3", "tailwind-merge": "1.14.0", - "tailwindcss": "3.3.3", + "tailwindcss": "3.4.13", "ts-deepmerge": "6.2.0", "use-debounce": "9.0.4", "uuid": "9.0.1", -- GitLab From 138c591cf8450db7e93d60d7a7e0076f3dc8083e Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Wed, 11 Dec 2024 10:22:34 +0100 Subject: [PATCH 06/12] configurable logos were not loaded --- CHANGELOG | 1 + src/components/Map/Map.component.tsx | 4 +- .../MapAdditionalLogos.component.tsx | 51 +++++++++++++++++++ .../Map/MapAdditionalLogos/index.ts | 1 + .../configuration/configuration.constants.ts | 6 +++ .../configuration/configuration.selectors.ts | 32 ++++++++++++ 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/components/Map/MapAdditionalLogos/MapAdditionalLogos.component.tsx create mode 100644 src/components/Map/MapAdditionalLogos/index.ts diff --git a/CHANGELOG b/CHANGELOG index 25728623..52071d51 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ minerva-front (18.0.7) stable; urgency=medium * Bug fix: export to image did not include overlays (#326) + * Bug fix: missing logos added (#329) -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 11 Dec 2024 13:00:00 +0200 diff --git a/src/components/Map/Map.component.tsx b/src/components/Map/Map.component.tsx index 72d18ebf..033ebd2f 100644 --- a/src/components/Map/Map.component.tsx +++ b/src/components/Map/Map.component.tsx @@ -1,8 +1,9 @@ import { Drawer } from '@/components/Map/Drawer'; import { Legend } from '@/components/Map/Legend'; +import { MapAdditionalLogos } from '@/components/Map/MapAdditionalLogos'; +import { MapViewer } from '@/components/Map/MapViewer'; import { MapAdditionalActions } from './MapAdditionalActions'; import { MapAdditionalOptions } from './MapAdditionalOptions'; -import { MapViewer } from './MapViewer/MapViewer.component'; import { PluginsDrawer } from './PluginsDrawer'; export const Map = (): JSX.Element => ( @@ -16,5 +17,6 @@ export const Map = (): JSX.Element => ( <MapViewer /> <Legend /> <MapAdditionalActions /> + <MapAdditionalLogos /> </div> ); diff --git a/src/components/Map/MapAdditionalLogos/MapAdditionalLogos.component.tsx b/src/components/Map/MapAdditionalLogos/MapAdditionalLogos.component.tsx new file mode 100644 index 00000000..51b29d2d --- /dev/null +++ b/src/components/Map/MapAdditionalLogos/MapAdditionalLogos.component.tsx @@ -0,0 +1,51 @@ +/* eslint-disable @next/next/no-img-element */ +import { twMerge } from 'tailwind-merge'; +import { + leftLogoImgValSelector, + leftLogoLinkValSelector, + leftLogoTextValSelector, + rightLogoImgValSelector, + rightLogoLinkValSelector, + rightLogoTextValSelector, +} from '@/redux/configuration/configuration.selectors'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { LinkButton } from '@/shared/LinkButton'; + +export const MapAdditionalLogos = (): JSX.Element => { + const leftLink = useAppSelector(leftLogoLinkValSelector); + const leftText = useAppSelector(leftLogoTextValSelector); + const leftImage = useAppSelector(leftLogoImgValSelector); + + const rightLink = useAppSelector(rightLogoLinkValSelector); + const rightText = useAppSelector(rightLogoTextValSelector); + const rightImage = useAppSelector(rightLogoImgValSelector); + + return ( + <div className={twMerge('absolute bottom-6 left-[102px] grid grid-cols-2 gap-4')}> + {leftLink && ( + <LinkButton + type="button" + className="flex h-auto max-h-20 w-auto max-w-20 cursor-pointer items-center justify-center border-0 bg-gray-200 bg-opacity-20 hover:bg-gray-300 hover:bg-opacity-30" + data-testid="location-button" + title={leftText} + href={leftLink} + target="_blank" + > + <img alt={leftText} src={leftImage} /> + </LinkButton> + )} + {rightLink && ( + <LinkButton + type="button" + className="flex h-auto max-h-20 w-auto max-w-20 cursor-pointer items-center justify-center border-0 bg-gray-200 bg-opacity-20 hover:bg-gray-300 hover:bg-opacity-30" + data-testid="location-button" + title={rightText} + href={rightLink} + target="_blank" + > + <img alt={rightText} src={rightImage} /> + </LinkButton> + )} + </div> + ); +}; diff --git a/src/components/Map/MapAdditionalLogos/index.ts b/src/components/Map/MapAdditionalLogos/index.ts new file mode 100644 index 00000000..6ea9ee31 --- /dev/null +++ b/src/components/Map/MapAdditionalLogos/index.ts @@ -0,0 +1 @@ +export { MapAdditionalLogos } from './MapAdditionalLogos.component'; diff --git a/src/redux/configuration/configuration.constants.ts b/src/redux/configuration/configuration.constants.ts index 032c5e0b..25ff1216 100644 --- a/src/redux/configuration/configuration.constants.ts +++ b/src/redux/configuration/configuration.constants.ts @@ -7,6 +7,12 @@ export const SEARCH_DISTANCE_NAME_ID = 'SEARCH_DISTANCE'; export const REQUEST_ACCOUNT_EMAIL = 'REQUEST_ACCOUNT_EMAIL'; export const TERMS_OF_SERVICE_ID = 'TERMS_OF_USE'; export const COOKIE_POLICY_URL = 'COOKIE_POLICY_URL'; +export const LEFT_LOGO_IMG = 'LEFT_LOGO_IMG'; +export const LEFT_LOGO_LINK = 'LEFT_LOGO_LINK'; +export const LEFT_LOGO_TEXT = 'LEFT_LOGO_TEXT'; +export const RIGHT_LOGO_IMG = 'RIGHT_LOGO_IMG'; +export const RIGHT_LOGO_LINK = 'RIGHT_LOGO_LINK'; +export const RIGHT_LOGO_TEXT = 'RIGHT_LOGO_TEXT'; export const LEGEND_FILE_NAMES_IDS = [ 'LEGEND_FILE_1', diff --git a/src/redux/configuration/configuration.selectors.ts b/src/redux/configuration/configuration.selectors.ts index 01a9eb4c..8677cadb 100644 --- a/src/redux/configuration/configuration.selectors.ts +++ b/src/redux/configuration/configuration.selectors.ts @@ -20,6 +20,12 @@ import { REQUEST_ACCOUNT_EMAIL, TERMS_OF_SERVICE_ID, COOKIE_POLICY_URL, + LEFT_LOGO_IMG, + LEFT_LOGO_LINK, + LEFT_LOGO_TEXT, + RIGHT_LOGO_IMG, + RIGHT_LOGO_LINK, + RIGHT_LOGO_TEXT, } from './configuration.constants'; import { ConfigurationHandlersIds, ConfigurationImageHandlersIds } from './configuration.types'; @@ -151,3 +157,29 @@ export const loadingConfigurationMainSelector = createSelector( configurationSelector, state => state?.main?.loading, ); + +export const leftLogoImgValSelector = createSelector( + configurationOptionsSelector, + state => configurationAdapterSelectors.selectById(state, LEFT_LOGO_IMG)?.value, +); +export const leftLogoLinkValSelector = createSelector( + configurationOptionsSelector, + state => configurationAdapterSelectors.selectById(state, LEFT_LOGO_LINK)?.value, +); +export const leftLogoTextValSelector = createSelector( + configurationOptionsSelector, + state => configurationAdapterSelectors.selectById(state, LEFT_LOGO_TEXT)?.value, +); + +export const rightLogoImgValSelector = createSelector( + configurationOptionsSelector, + state => configurationAdapterSelectors.selectById(state, RIGHT_LOGO_IMG)?.value, +); +export const rightLogoLinkValSelector = createSelector( + configurationOptionsSelector, + state => configurationAdapterSelectors.selectById(state, RIGHT_LOGO_LINK)?.value, +); +export const rightLogoTextValSelector = createSelector( + configurationOptionsSelector, + state => configurationAdapterSelectors.selectById(state, RIGHT_LOGO_TEXT)?.value, +); -- GitLab From 38f51e0f83c6b6faf765ab3b693250b451f1b430 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Wed, 11 Dec 2024 12:11:05 +0100 Subject: [PATCH 07/12] provide info about entries when returning list of visible data overlays --- CHANGELOG | 2 + .../map/overlays/getVisibleDataOverlays.ts | 40 ++++++++++++++++- .../map/overlays/types/DataOverlay.ts | 44 +++++++++++++++++++ .../map/overlays/types/DataOverlayEntry.ts | 27 ++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/services/pluginsManager/map/overlays/types/DataOverlay.ts create mode 100644 src/services/pluginsManager/map/overlays/types/DataOverlayEntry.ts diff --git a/CHANGELOG b/CHANGELOG index 52071d51..a58b1598 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ minerva-front (18.0.7) stable; urgency=medium * Bug fix: export to image did not include overlays (#326) * Bug fix: missing logos added (#329) + * Bug fix: plugin API did not provide overlay entries when returning list of + visible overlays (#332) -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 11 Dec 2024 13:00:00 +0200 diff --git a/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.ts b/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.ts index 6224d3ff..5f570436 100644 --- a/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.ts +++ b/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.ts @@ -1,9 +1,47 @@ -import { activeOverlaysSelector } from '@/redux/overlayBioEntity/overlayBioEntity.selector'; +import { + activeOverlaysSelector, + overlayBioEntityDataSelector, +} from '@/redux/overlayBioEntity/overlayBioEntity.selector'; import { store } from '@/redux/store'; import { MapOverlay } from '@/types/models'; +import { DataOverlay } from '@/services/pluginsManager/map/overlays/types/DataOverlay'; +import { modelsDataSelector } from '@/redux/models/models.selectors'; +import { DataOverlayEntry } from '@/services/pluginsManager/map/overlays/types/DataOverlayEntry'; export const getVisibleDataOverlays = (): MapOverlay[] => { const activeOverlays = activeOverlaysSelector(store.getState()); + const overlayData = overlayBioEntityDataSelector(store.getState()); + + const models = modelsDataSelector(store.getState()); + + const dataOverlays = activeOverlays.map(mapOverlay => new DataOverlay(mapOverlay)); + + dataOverlays.forEach(dataOverlay => { + const mapOverlayData = overlayData[dataOverlay.id]; + if (mapOverlayData) { + models.forEach(model => { + const entries = mapOverlayData[model.idObject]; + if (entries) { + entries.forEach(dataEntry => { + if (dataEntry.type === 'submap-link') { + dataOverlay.addEntry( + new DataOverlayEntry( + Number(dataEntry.id), + 'ALIAS', + dataEntry.modelId, + dataEntry.color, + dataEntry.value, + ), + ); + } else { + // eslint-disable-next-line no-console + console.log(`${dataEntry.type} not supported`); + } + }); + } + }); + } + }); return activeOverlays; }; diff --git a/src/services/pluginsManager/map/overlays/types/DataOverlay.ts b/src/services/pluginsManager/map/overlays/types/DataOverlay.ts new file mode 100644 index 00000000..e79d88ba --- /dev/null +++ b/src/services/pluginsManager/map/overlays/types/DataOverlay.ts @@ -0,0 +1,44 @@ +import { MapOverlay } from '@/types/models'; +import { DataOverlayEntry } from '@/services/pluginsManager/map/overlays/types/DataOverlayEntry'; + +export class DataOverlay { + id: number; + + idObject: number; + + name: string; + + order: number; + + creator: string; + + description: string; + + genomeType: string | null; + + genomeVersion: string | null; + + publicOverlay: boolean; + + type: string; + + entries: DataOverlayEntry[]; + + constructor(mapOverlay: MapOverlay) { + this.id = mapOverlay.idObject; + this.idObject = mapOverlay.idObject; + this.name = mapOverlay.name; + this.order = mapOverlay.order; + this.creator = mapOverlay.creator; + this.description = mapOverlay.description; + this.genomeType = mapOverlay.genomeType; + this.genomeVersion = mapOverlay.genomeVersion; + this.publicOverlay = mapOverlay.publicOverlay; + this.type = mapOverlay.type; + this.entries = []; + } + + public addEntry(entry: DataOverlayEntry): void { + this.entries.push(entry); + } +} diff --git a/src/services/pluginsManager/map/overlays/types/DataOverlayEntry.ts b/src/services/pluginsManager/map/overlays/types/DataOverlayEntry.ts new file mode 100644 index 00000000..2627887c --- /dev/null +++ b/src/services/pluginsManager/map/overlays/types/DataOverlayEntry.ts @@ -0,0 +1,27 @@ +import { Color } from '@/types/models'; + +export class DataOverlayEntry { + bioEntityId: number; + + bioEntityType: string; + + bioEntityModelId: number; + + color: Color | null; + + value: number | null; + + constructor( + bioEntityId: number, + bioEntityType: string, + bioEntityModelId: number, + color: Color | null, + value: number | null, + ) { + this.bioEntityId = bioEntityId; + this.color = color; + this.value = value; + this.bioEntityType = bioEntityType; + this.bioEntityModelId = bioEntityModelId; + } +} -- GitLab From 671676199d1103df8c61c819689ba082907f5b93 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Wed, 11 Dec 2024 12:58:29 +0100 Subject: [PATCH 08/12] provide data overlay entries for plugins in new interface --- .../map/overlays/getVisibleDataOverlays.test.ts | 5 ++++- .../pluginsManager/map/overlays/getVisibleDataOverlays.ts | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.test.ts b/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.test.ts index 036a668b..c0f486b9 100644 --- a/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.test.ts +++ b/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.test.ts @@ -3,6 +3,7 @@ import { overlaysFixture } from '@/models/fixtures/overlaysFixture'; import { OVERLAYS_INITIAL_STATE_MOCK } from '@/redux/overlays/overlays.mock'; import { RootState, store } from '@/redux/store'; import { OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK } from '@/redux/overlayBioEntity/overlayBioEntity.mock'; +import { DataOverlay } from '@/services/pluginsManager/map/overlays/types/DataOverlay'; import { getVisibleDataOverlays } from './getVisibleDataOverlays'; const ACTIVE_OVERLAYS_IDS = overlaysFixture.map(overlay => overlay.idObject); @@ -34,7 +35,9 @@ describe('getVisibleDataOverlays', () => { }) as RootState, ); - expect(getVisibleDataOverlays()).toEqual(overlaysFixture); + expect(getVisibleDataOverlays()).toEqual( + overlaysFixture.map(overlay => new DataOverlay(overlay)), + ); }); it('should return empty array if no active overlays', () => { diff --git a/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.ts b/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.ts index 5f570436..14a69d51 100644 --- a/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.ts +++ b/src/services/pluginsManager/map/overlays/getVisibleDataOverlays.ts @@ -3,12 +3,11 @@ import { overlayBioEntityDataSelector, } from '@/redux/overlayBioEntity/overlayBioEntity.selector'; import { store } from '@/redux/store'; -import { MapOverlay } from '@/types/models'; import { DataOverlay } from '@/services/pluginsManager/map/overlays/types/DataOverlay'; import { modelsDataSelector } from '@/redux/models/models.selectors'; import { DataOverlayEntry } from '@/services/pluginsManager/map/overlays/types/DataOverlayEntry'; -export const getVisibleDataOverlays = (): MapOverlay[] => { +export const getVisibleDataOverlays = (): DataOverlay[] => { const activeOverlays = activeOverlaysSelector(store.getState()); const overlayData = overlayBioEntityDataSelector(store.getState()); @@ -43,5 +42,5 @@ export const getVisibleDataOverlays = (): MapOverlay[] => { } }); - return activeOverlays; + return dataOverlays; }; -- GitLab From a4ba3e5e819d5189e1e90b9836a87c776471d638 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Thu, 12 Dec 2024 12:01:10 +0100 Subject: [PATCH 09/12] current view is changing properly image size --- .../CurrentView/CurrentView.component.tsx | 24 ++++++++++ .../CurrentView/CurrentView.constants.ts | 5 ++ .../CurrentView/CurrentView.types.ts | 3 ++ .../ExportCompound/CurrentView/index.ts | 1 + .../ExportCompound.component.tsx | 8 ++++ .../ExportCompound/ExportCompound.constant.ts | 3 ++ .../ExportCompound/ExportCompound.types.ts | 3 ++ .../ImageSize/utils/useImageSize.ts | 33 +++++++++---- .../ImageSize/utils/useScreenAspectRatios.ts | 48 +++++++++++++++++++ .../Graphics/Graphics.component.tsx | 1 + 10 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.component.tsx create mode 100644 src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.constants.ts create mode 100644 src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.types.ts create mode 100644 src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/index.ts create mode 100644 src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios.ts diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.component.tsx new file mode 100644 index 00000000..cad075a0 --- /dev/null +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.component.tsx @@ -0,0 +1,24 @@ +import { useContext } from 'react'; +import { ExportContext } from '@/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.context'; + +export const CurrentView = (): React.ReactNode => { + const { setCurrentView, data } = useContext(ExportContext); + + return ( + <div className="flex flex-col gap-4 border-b"> + <label className="flex h-9 items-center gap-4"> + <span>Current view: </span> + <input + className="rounded-[64px] border border-transparent bg-cultured px-4 py-2.5 text-xs font-medium text-font-400 outline-none hover:border-greyscale-600 focus:border-greyscale-600" + name="width" + checked={data.currentView.value} + type="checkbox" + aria-label="export graphics width input" + onChange={(e): void => { + setCurrentView({ value: e.target.checked }); + }} + /> + </label> + </div> + ); +}; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.constants.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.constants.ts new file mode 100644 index 00000000..f512b6d7 --- /dev/null +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.constants.ts @@ -0,0 +1,5 @@ +import { CurrentView } from './CurrentView.types'; + +export const DEFAULT_CURRENT_VIEW: CurrentView = { + value: false, +}; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.types.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.types.ts new file mode 100644 index 00000000..dc5bc917 --- /dev/null +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.types.ts @@ -0,0 +1,3 @@ +export interface CurrentView { + value: boolean; +} diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/index.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/index.ts new file mode 100644 index 00000000..883104d6 --- /dev/null +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/index.ts @@ -0,0 +1 @@ +export { CurrentView } from './CurrentView.component'; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx index e33a99ed..1b7d192b 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx @@ -6,6 +6,8 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { modelsDataSelector, modelsIdsSelector } from '@/redux/models/models.selectors'; import { ReactNode, useCallback, useMemo, useState } from 'react'; import { activeOverlaysIdSelector } from '@/redux/overlayBioEntity/overlayBioEntity.selector'; +import { CurrentView } from '@/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView'; +import { DEFAULT_CURRENT_VIEW } from '@/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.constants'; import { CheckboxItem } from '../CheckboxFilter/CheckboxFilter.types'; import { Annotations } from './Annotations'; import { DownloadElements } from './DownloadElements/DownloadElements'; @@ -18,6 +20,7 @@ import { ImageFormat } from './ImageFormat'; import { ImageSize } from './ImageSize'; import { DEFAULT_IMAGE_SIZE } from './ImageSize/ImageSize.constants'; import { ImageSize as ImageSizeType } from './ImageSize/ImageSize.types'; +import { CurrentView as CurrentViewType } from './CurrentView/CurrentView.types'; import { IncludedCompartmentPathways } from './IncludedCompartmentPathways '; import { Submap } from './Submap'; import { getDownloadElementsBodyRequest } from './utils/getDownloadElementsBodyRequest'; @@ -45,6 +48,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { const [models, setModels] = useState<CheckboxItem[]>([]); const [imageSize, setImageSize] = useState<ImageSizeType>(DEFAULT_IMAGE_SIZE); const [imageFormats, setImageFormats] = useState<CheckboxItem[]>([]); + const [currentView, setCurrentView] = useState<CurrentViewType>(DEFAULT_CURRENT_VIEW); const handleDownloadElements = useCallback(async () => { const body = getDownloadElementsBodyRequest({ @@ -94,6 +98,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { models, imageSize, imageFormats, + currentView, }), [ annotations, @@ -102,6 +107,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { models, imageSize, imageFormats, + currentView, ], ); @@ -113,6 +119,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { setModels, setImageSize, setImageFormats, + setCurrentView, handleDownloadElements, handleDownloadNetwork, handleDownloadGraphics, @@ -133,3 +140,4 @@ Export.ImageSize = ImageSize; Export.ImageFormat = ImageFormat; Export.DownloadNetwork = DownloadNetwork; Export.DownloadGraphics = DownloadGraphics; +Export.CurrentView = CurrentView; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.constant.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.constant.ts index 5a7e4f08..5381e784 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.constant.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.constant.ts @@ -1,3 +1,4 @@ +import { DEFAULT_CURRENT_VIEW } from '@/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.constants'; import { ExportContextType } from './ExportCompound.types'; import { DEFAULT_IMAGE_SIZE } from './ImageSize/ImageSize.constants'; @@ -54,6 +55,7 @@ export const EXPORT_CONTEXT_DEFAULT_VALUE: ExportContextType = { setModels: () => {}, setImageSize: () => {}, setImageFormats: () => {}, + setCurrentView: () => {}, handleDownloadElements: () => Promise.resolve(), handleDownloadNetwork: () => Promise.resolve(), handleDownloadGraphics: () => {}, @@ -64,5 +66,6 @@ export const EXPORT_CONTEXT_DEFAULT_VALUE: ExportContextType = { models: [], imageFormats: [], imageSize: DEFAULT_IMAGE_SIZE, + currentView: DEFAULT_CURRENT_VIEW, }, }; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.types.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.types.ts index 02c87101..b57cc6e0 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.types.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.types.ts @@ -1,3 +1,4 @@ +import { CurrentView } from '@/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.types'; import { CheckboxItem } from '../CheckboxFilter/CheckboxFilter.types'; import { ImageSize } from './ImageSize/ImageSize.types'; @@ -6,6 +7,7 @@ export type ExportContextType = { setIncludedCompartmentPathways: React.Dispatch<React.SetStateAction<CheckboxItem[]>>; setExcludedCompartmentPathways: React.Dispatch<React.SetStateAction<CheckboxItem[]>>; setModels: React.Dispatch<React.SetStateAction<CheckboxItem[]>>; + setCurrentView: React.Dispatch<React.SetStateAction<CurrentView>>; setImageSize: React.Dispatch<React.SetStateAction<ImageSize>>; setImageFormats: React.Dispatch<React.SetStateAction<CheckboxItem[]>>; handleDownloadElements: () => Promise<void>; @@ -16,6 +18,7 @@ export type ExportContextType = { includedCompartmentPathways: CheckboxItem[]; excludedCompartmentPathways: CheckboxItem[]; models: CheckboxItem[]; + currentView: CurrentView; imageSize: ImageSize; imageFormats: CheckboxItem[]; }; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useImageSize.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useImageSize.ts index f36afdd3..d4869197 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useImageSize.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useImageSize.ts @@ -1,9 +1,13 @@ import { MapModel } from '@/types/models'; import { numberToSafeInt } from '@/utils/number/numberToInt'; import { useCallback, useContext, useEffect } from 'react'; +import { + getScreenAspectRatios, + getScreenDimension, +} from '@/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios'; import { ExportContext } from '../../ExportCompound.context'; import { DEFAULT_IMAGE_HEIGHT, DEFAULT_IMAGE_WIDTH } from '../ImageSize.constants'; -import { ImageSize } from '../ImageSize.types'; +import { ImageSize, ModelAspectRatios } from '../ImageSize.types'; import { useExportGraphicsSelectedModel } from './useExportGraphicsSelectedModel'; import { getModelAspectRatios } from './useModelAspectRatios'; @@ -16,9 +20,15 @@ interface UseImageSizeResults { export const useImageSize = (): UseImageSizeResults => { const selectedModel = useExportGraphicsSelectedModel(); - const aspectRatios = getModelAspectRatios(selectedModel); - const { data, setImageSize } = useContext(ExportContext); - const { imageSize } = data; + const { data, setImageSize, setCurrentView } = useContext(ExportContext); + const { imageSize, currentView } = data; + let aspectRatios: ModelAspectRatios; + if (currentView.value) { + aspectRatios = getScreenAspectRatios(); + } else { + aspectRatios = getModelAspectRatios(selectedModel); + } + const maxWidth = selectedModel?.width || DEFAULT_IMAGE_WIDTH; const maxHeight = selectedModel?.height || DEFAULT_IMAGE_HEIGHT; @@ -27,8 +37,8 @@ export const useImageSize = (): UseImageSizeResults => { const newWidth = newImageSize.width; const newHeight = newImageSize.height; - const widthMinMax = Math.min(maxWidth, newWidth); - const heightMinMax = Math.min(maxHeight, newHeight); + const widthMinMax = currentView.value ? newWidth : Math.min(maxWidth, newWidth); + const heightMinMax = currentView.value ? newHeight : Math.min(maxHeight, newHeight); const widthInt = numberToSafeInt(widthMinMax); const heightInt = numberToSafeInt(heightMinMax); @@ -43,14 +53,17 @@ export const useImageSize = (): UseImageSizeResults => { const setDefaultModelImageSize = useCallback( (model: MapModel): void => { + const screenDimension = getScreenDimension(); + const width = currentView.value ? screenDimension.width : model.width; + const height = currentView.value ? screenDimension.height : model.height; const newImageSize = getNormalizedImageSize({ - width: model.width, - height: model.height, + width, + height, }); setImageSize(newImageSize); }, - [getNormalizedImageSize, setImageSize], + [getNormalizedImageSize, setImageSize, setCurrentView, currentView], ); const handleChangeWidth = (width: number): void => { @@ -77,7 +90,7 @@ export const useImageSize = (): UseImageSizeResults => { } setDefaultModelImageSize(selectedModel); - }, [setDefaultModelImageSize, selectedModel]); + }, [setDefaultModelImageSize, selectedModel, setCurrentView, currentView]); return { handleChangeWidth, diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios.ts new file mode 100644 index 00000000..e586afcb --- /dev/null +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios.ts @@ -0,0 +1,48 @@ +import { getBounds } from '@/services/pluginsManager/map/data/getBounds'; +import { ZERO } from '@/constants/common'; +import { DEFAULT_IMAGE_SIZE, DEFAULT_MODEL_ASPECT_RATIOS } from '../ImageSize.constants'; +import { ImageSize, ModelAspectRatios } from '../ImageSize.types'; + +export const getScreenAspectRatios = (): ModelAspectRatios => { + const bounds = getBounds(); + if (!bounds) { + return DEFAULT_MODEL_ASPECT_RATIOS; + } + let { x1, y1 } = bounds; + const { x2, y2 } = bounds; + if (x1 > x2) { + x1 = ZERO; + } + if (y1 > y2) { + y1 = ZERO; + } + const width = x2 - x1; + const height = y2 - y1; + + return { + vertical: height / width, + horizontal: width / height, + }; +}; + +export const getScreenDimension = (): ImageSize => { + const bounds = getBounds(); + if (!bounds) { + return DEFAULT_IMAGE_SIZE; + } + let { x1, y1 } = bounds; + const { x2, y2 } = bounds; + if (x1 > x2) { + x1 = ZERO; + } + if (y1 > y2) { + y1 = ZERO; + } + const width = x2 - x1; + const height = y2 - y1; + + return { + width, + height, + }; +}; diff --git a/src/components/Map/Drawer/ExportDrawer/Graphics/Graphics.component.tsx b/src/components/Map/Drawer/ExportDrawer/Graphics/Graphics.component.tsx index 547c2c14..aafe37a2 100644 --- a/src/components/Map/Drawer/ExportDrawer/Graphics/Graphics.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/Graphics/Graphics.component.tsx @@ -4,6 +4,7 @@ export const Graphics = (): React.ReactNode => { return ( <div data-testid="graphics-tab"> <Export> + <Export.CurrentView /> <Export.Submap /> <Export.ImageSize /> <Export.ImageFormat /> -- GitLab From ded1605d652fe5a31ef8808d340a70921b1c7d7c Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Thu, 12 Dec 2024 12:23:51 +0100 Subject: [PATCH 10/12] download image considering bounds when current view is selected --- .../ExportCompound.component.tsx | 1 + .../ImageSize/utils/useScreenAspectRatios.ts | 19 ++----------------- .../utils/getGraphicsDownloadUrl.ts | 14 +++++++++++++- .../pluginsManager/map/data/getBounds.ts | 5 +++-- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx index 1b7d192b..1c7da289 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx @@ -83,6 +83,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { handler: imageFormats?.[FIRST_ARRAY_ELEMENT]?.id, zoom: getModelExportZoom(imageSize.width, model), overlayIds: overlays.map(overlayId => `${overlayId}`), + currentView: currentView.value, }); if (url) { diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios.ts index e586afcb..ee1bec83 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ImageSize/utils/useScreenAspectRatios.ts @@ -1,5 +1,4 @@ import { getBounds } from '@/services/pluginsManager/map/data/getBounds'; -import { ZERO } from '@/constants/common'; import { DEFAULT_IMAGE_SIZE, DEFAULT_MODEL_ASPECT_RATIOS } from '../ImageSize.constants'; import { ImageSize, ModelAspectRatios } from '../ImageSize.types'; @@ -8,14 +7,7 @@ export const getScreenAspectRatios = (): ModelAspectRatios => { if (!bounds) { return DEFAULT_MODEL_ASPECT_RATIOS; } - let { x1, y1 } = bounds; - const { x2, y2 } = bounds; - if (x1 > x2) { - x1 = ZERO; - } - if (y1 > y2) { - y1 = ZERO; - } + const { x1, x2, y1, y2 } = bounds; const width = x2 - x1; const height = y2 - y1; @@ -30,14 +22,7 @@ export const getScreenDimension = (): ImageSize => { if (!bounds) { return DEFAULT_IMAGE_SIZE; } - let { x1, y1 } = bounds; - const { x2, y2 } = bounds; - if (x1 > x2) { - x1 = ZERO; - } - if (y1 > y2) { - y1 = ZERO; - } + const { x1, x2, y1, y2 } = bounds; const width = x2 - x1; const height = y2 - y1; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.ts index 169265ea..28448995 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getGraphicsDownloadUrl.ts @@ -1,4 +1,5 @@ import { BASE_API_URL, PROJECT_ID } from '@/constants'; +import { getBounds } from '@/services/pluginsManager/map/data/getBounds'; export interface GetGraphicsDownloadUrlProps { backgroundId?: number; @@ -6,6 +7,7 @@ export interface GetGraphicsDownloadUrlProps { handler?: string; zoom?: number; overlayIds: string[]; + currentView?: boolean; } export const getGraphicsDownloadUrl = ({ @@ -14,6 +16,7 @@ export const getGraphicsDownloadUrl = ({ handler, zoom, overlayIds, + currentView, }: GetGraphicsDownloadUrlProps): string | undefined => { const isAllElementsTruthy = [backgroundId, modelId, handler, zoom].reduce( (a, b) => Boolean(a) && Boolean(b), @@ -26,5 +29,14 @@ export const getGraphicsDownloadUrl = ({ const overlays = overlayIds.join(','); - return `${BASE_API_URL}/projects/${PROJECT_ID}/models/${modelId}:downloadImage?backgroundOverlayId=${backgroundId}&handlerClass=${handler}&zoomLevel=${zoom}&overlayIds=${overlays}`; + let polygonSuffix = ''; + if (currentView) { + const bounds = getBounds(); + if (bounds) { + const { x1, y1, x2, y2 } = bounds; + polygonSuffix = `&polygonString=${x1},${y1};${x1},${y2};${x2},${y2};${x2},${y1}`; + } + } + + return `${BASE_API_URL}/projects/${PROJECT_ID}/models/${modelId}:downloadImage?backgroundOverlayId=${backgroundId}&handlerClass=${handler}&zoomLevel=${zoom}&overlayIds=${overlays}${polygonSuffix}`; }; diff --git a/src/services/pluginsManager/map/data/getBounds.ts b/src/services/pluginsManager/map/data/getBounds.ts index 626e13f7..a905228e 100644 --- a/src/services/pluginsManager/map/data/getBounds.ts +++ b/src/services/pluginsManager/map/data/getBounds.ts @@ -2,6 +2,7 @@ import { mapDataSizeSelector } from '@/redux/map/map.selectors'; import { store } from '@/redux/store'; import { latLngToPoint } from '@/utils/map/latLngToPoint'; import { toLonLat } from 'ol/proj'; +import { ZERO } from '@/constants/common'; import { MapManager } from '../mapManager'; type GetBoundsReturnType = @@ -29,8 +30,8 @@ export const getBounds = (): GetBoundsReturnType => { const { x: x2, y: y2 } = latLngToPoint([latY2, lngX2], mapSize, { rounded: true }); return { - x1, - y1, + x1: x1 > x2 ? ZERO : x1, // handle lat,lng overflow + y1: y1 > y2 ? ZERO : y1, // handle lat,lng overflow x2, y2, }; -- GitLab From a976ff3d96dc03e4d8ac23acfd9194532a386d17 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Thu, 12 Dec 2024 12:49:05 +0100 Subject: [PATCH 11/12] when selecting current view set proper model in the list --- .../CurrentView/CurrentView.component.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.component.tsx index cad075a0..cb7e611d 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/CurrentView/CurrentView.component.tsx @@ -1,8 +1,13 @@ import { useContext } from 'react'; import { ExportContext } from '@/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.context'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { currentModelIdSelector, currentModelNameSelector } from '@/redux/models/models.selectors'; export const CurrentView = (): React.ReactNode => { - const { setCurrentView, data } = useContext(ExportContext); + const { setCurrentView, data, setModels } = useContext(ExportContext); + + const currentMapModelId = useAppSelector(currentModelIdSelector); + const currentMapModelName = useAppSelector(currentModelNameSelector); return ( <div className="flex flex-col gap-4 border-b"> @@ -16,6 +21,14 @@ export const CurrentView = (): React.ReactNode => { aria-label="export graphics width input" onChange={(e): void => { setCurrentView({ value: e.target.checked }); + if (e.target.checked) { + setModels([ + { + id: `${currentMapModelId}`, + label: currentMapModelName, + }, + ]); + } }} /> </label> -- GitLab From 8fbfcf0ea1d9e783b391b1cd607162ad946f522e Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Thu, 12 Dec 2024 13:13:38 +0100 Subject: [PATCH 12/12] rename Submap to Dialog --- CHANGELOG | 1 + .../ExportCompound/Submap/Submap.component.test.tsx | 8 ++++---- .../ExportCompound/Submap/Submap.component.tsx | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0992fd8c..ead072d8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ minerva-front (19.0.0~alpha.0) stable; urgency=medium * Feature: allow plugin to access info about opened panel (#309) * Feature: allow plugin to hide opened panel (#309) * Feature: allow plugin to open left panel (#309) + * Feature: allow to export current view for graphics export (#327) -- Piotr Gawron <piotr.gawron@uni.lu> Fri, 18 Oct 2024 13:00:00 +0200 diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/Submap/Submap.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/Submap/Submap.component.test.tsx index 6ee9cb42..f3b874e3 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/Submap/Submap.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/Submap/Submap.component.test.tsx @@ -45,7 +45,7 @@ describe('Submap - component', () => { navigationButton.click(); }); - expect(screen.getByText('Submap')).toBeInTheDocument(); + expect(screen.getByText('Diagram')).toBeInTheDocument(); await waitFor(() => { expect(screen.getByTestId('checkbox-filter')).toBeInTheDocument(); @@ -64,7 +64,7 @@ describe('Submap - component', () => { }, }, }); - expect(screen.getByText('Submap')).toBeInTheDocument(); + expect(screen.getByText('Diagram')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { navigationButton.click(); @@ -83,7 +83,7 @@ describe('Submap - component', () => { }, }, }); - expect(screen.getByText('Submap')).toBeInTheDocument(); + expect(screen.getByText('Diagram')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { navigationButton.click(); @@ -103,7 +103,7 @@ describe('Submap - component', () => { }, }, }); - expect(screen.getByText('Submap')).toBeInTheDocument(); + expect(screen.getByText('Diagram')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { navigationButton.click(); diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/Submap/Submap.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/Submap/Submap.component.tsx index 422c4b73..21e1048d 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/Submap/Submap.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/Submap/Submap.component.tsx @@ -30,7 +30,7 @@ export const Submap = (): React.ReactNode => { } return ( - <CollapsibleSection title="Submap" dangerouslySetExpanded> + <CollapsibleSection title="Diagram" dangerouslySetExpanded> {isPending && <p>Loading...</p>} {!isPending && mappedElementAnnotations && mappedElementAnnotations.length > ZERO && ( <CheckboxFilter -- GitLab