diff --git a/applications/virtual-fly-brain/frontend/src/components/TermInfo/TerminfoSlider.jsx b/applications/virtual-fly-brain/frontend/src/components/TermInfo/TerminfoSlider.jsx index 418b94df..41e1d2f0 100644 --- a/applications/virtual-fly-brain/frontend/src/components/TermInfo/TerminfoSlider.jsx +++ b/applications/virtual-fly-brain/frontend/src/components/TermInfo/TerminfoSlider.jsx @@ -7,7 +7,7 @@ import { useSelector } from 'react-redux'; import { Slide } from 'react-slideshow-image'; import { ChevronLeft, FullScreen } from '../../icons'; import { Box, Button, Typography } from '@mui/material'; -import { getInstanceByID } from '../../reducers/actions/instances'; +import { getInstanceByID, clearUrlLoadingState } from '../../reducers/actions/instances'; import Modal from '../../shared/modal/Modal'; import 'react-slideshow-image/dist/styles.css' @@ -115,12 +115,16 @@ const TerminfoSlider = (props) => { }); const [isLoading, setIsLoading] = useState(false); const reduxState = useSelector(state => state); + const misalignedTemplate = useSelector(state => state.globalInfo.misalignedTemplate) + const alignedTemplates = useSelector(state => state.globalInfo.alignedTemplates) + const misalignedIDs = useSelector(state => state.globalInfo.misalignedIDs) const handleConfirmLoad = async () => { if (!confirmationModal.example) return; setIsLoading(true); try { + clearUrlLoadingState() window.open( window.location.origin + '/?id=' + confirmationModal.example.template + '&i=' + confirmationModal.example.id, '_blank' @@ -159,6 +163,20 @@ const TerminfoSlider = (props) => { } } + + useEffect(() => { + const misalignedIdKeys = Object.keys(misalignedIDs || {}); + const activeMisalignedId = misalignedIdKeys[misalignedIdKeys.length - 1]; + if (misalignedTemplate && !alignedTemplates && activeMisalignedId) { + setConfirmationModal({ + open: true, + example: { id: activeMisalignedId, template: misalignedTemplate }, + message: `The image you requested is aligned to another template. Click Load Template to open it in a new tab or Cancel to just view the image metadata.` + }); + } + }, [misalignedTemplate, misalignedIDs, alignedTemplates]) + + useEffect( () => { if(props?.examples) { const images = []; diff --git a/applications/virtual-fly-brain/frontend/src/reducers/GlobalReducer.js b/applications/virtual-fly-brain/frontend/src/reducers/GlobalReducer.js index 0209cf17..e8889bd5 100644 --- a/applications/virtual-fly-brain/frontend/src/reducers/GlobalReducer.js +++ b/applications/virtual-fly-brain/frontend/src/reducers/GlobalReducer.js @@ -36,11 +36,12 @@ const GlobalReducer = (state = initialStateGlobalReducer, response) => { }) case getGlobalTypes.ALIGN_TEMPLATES:{ const aligned = response.payload.aligned; - const id = response.payload.templateID + const templateID = response.payload.templateID + const id = response.payload.id return Object.assign({}, state, { alignedTemplates: aligned, - misalignedTemplate : id, - misalignedIDs : {...state.misalignedIDs, [id] : id } + misalignedTemplate : templateID, + misalignedIDs : id ? {...state.misalignedIDs, [id] : id } : state.misalignedIDs }) } case getGlobalTypes.OPEN_QUERY_COMPONENT: diff --git a/applications/virtual-fly-brain/frontend/src/reducers/InstancesReducer.js b/applications/virtual-fly-brain/frontend/src/reducers/InstancesReducer.js index 5a46876a..087d4176 100644 --- a/applications/virtual-fly-brain/frontend/src/reducers/InstancesReducer.js +++ b/applications/virtual-fly-brain/frontend/src/reducers/InstancesReducer.js @@ -762,6 +762,7 @@ const InstancesReducer = (state = initialStateInstancesReducer, response) => { case getInstancesTypes.CLEAR_URL_LOADING_STATE: { return Object.assign({}, state, { isLoadingFromUrl: false, + isLoading: false, }); } default: diff --git a/applications/virtual-fly-brain/frontend/src/reducers/actions/globals.js b/applications/virtual-fly-brain/frontend/src/reducers/actions/globals.js index 6256f121..2d96be83 100644 --- a/applications/virtual-fly-brain/frontend/src/reducers/actions/globals.js +++ b/applications/virtual-fly-brain/frontend/src/reducers/actions/globals.js @@ -36,9 +36,9 @@ export const setFirstIDLoaded = () => ({ payload : {} }) -export const setAlignTemplates = (aligned, templateID) => ({ +export const setAlignTemplates = (aligned, id, templateID) => ({ type: getGlobalTypes.ALIGN_TEMPLATES, - payload : { aligned, templateID } + payload : { aligned, id, templateID } }) export const setTemplateID = (id) => ({ diff --git a/applications/virtual-fly-brain/frontend/src/reducers/actions/instances.js b/applications/virtual-fly-brain/frontend/src/reducers/actions/instances.js index 70a5e118..80097c3a 100644 --- a/applications/virtual-fly-brain/frontend/src/reducers/actions/instances.js +++ b/applications/virtual-fly-brain/frontend/src/reducers/actions/instances.js @@ -175,9 +175,10 @@ export const setBulkLoadingCount = (count, isFromUrl = false) => ({ payload: { count, isFromUrl } }); -export const clearUrlLoadingState = () => ({ - type: getInstancesTypes.CLEAR_URL_LOADING_STATE -}); +export const clearUrlLoadingState = () => { + store.dispatch({type: getInstancesTypes.CLEAR_URL_LOADING_STATE}); + return; +}; export const resetBulkLoading = () => ({ type: getInstancesTypes.RESET_BULK_LOADING diff --git a/applications/virtual-fly-brain/frontend/src/reducers/middleware/urlUpdaterMiddleware.js b/applications/virtual-fly-brain/frontend/src/reducers/middleware/urlUpdaterMiddleware.js index d99b21dd..a2677272 100644 --- a/applications/virtual-fly-brain/frontend/src/reducers/middleware/urlUpdaterMiddleware.js +++ b/applications/virtual-fly-brain/frontend/src/reducers/middleware/urlUpdaterMiddleware.js @@ -182,14 +182,14 @@ export const urlUpdaterMiddleware = store => next => (action) => { await focusInstance(pendingFocusId); await selectInstance(pendingFocusId); // Clear URL loading state after async operations complete - store.dispatch(clearUrlLoadingState()); + clearUrlLoadingState(); // Clear the initial focus ID after a longer delay to allow all pending template operations to complete setTimeout(() => { initialUrlFocusId = null; }, 1000); })(); } else { - store.dispatch(clearUrlLoadingState()); + clearUrlLoadingState(); } } @@ -224,7 +224,7 @@ export const urlUpdaterMiddleware = store => next => (action) => { return; } else if (IsTemplate && launchTemplate?.metadata?.Id !== action.payload.Id) { // If it's a template and the launchTemplate is defined, we need to show the widget to open this template in a new tab - store.dispatch(setAlignTemplates(false, action.payload.Id)); + store.dispatch(setAlignTemplates(false, action.payload.Id, action.payload.Id)); return; } @@ -272,7 +272,7 @@ export const urlUpdaterMiddleware = store => next => (action) => { return; } // If the individual is not aligned with the current template, we need to show the misalignment dialog - store.dispatch(setAlignTemplates(false, action.payload.Id)); + store.dispatch(setAlignTemplates(false, action.payload.Id, Object.keys(action.payload?.Images)|| Object.keys(action.payload?.Examples || {}))); return; } }