diff --git a/CHANGELOG.md b/CHANGELOG.md index d5a2806ee0..b771b11b47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,8 @@ and this project adheres to ### Fixed +- 500 error when navigating from collaborative editor to full history page + [#3941](https://github.com/OpenFn/lightning/pull/3941) - Duplicate `isReadOnly` declaration in TriggerForm that was blocking asset builds [#3976](https://github.com/OpenFn/lightning/issues/3976) - Run duration and status alignment drift in history view diff --git a/assets/js/collaborative-editor/components/diagram/CollaborativeWorkflowDiagram.tsx b/assets/js/collaborative-editor/components/diagram/CollaborativeWorkflowDiagram.tsx index 7fc8bc94b5..ced33d7cfe 100644 --- a/assets/js/collaborative-editor/components/diagram/CollaborativeWorkflowDiagram.tsx +++ b/assets/js/collaborative-editor/components/diagram/CollaborativeWorkflowDiagram.tsx @@ -18,10 +18,13 @@ import { useRunSteps, } from '../../hooks/useHistory'; import { useIsNewWorkflow } from '../../hooks/useSessionContext'; +import { useVersionMismatch } from '../../hooks/useVersionMismatch'; +import { useVersionSelect } from '../../hooks/useVersionSelect'; import { useNodeSelection } from '../../hooks/useWorkflow'; import type { Run } from '../../types/history'; import MiniHistory from './MiniHistory'; +import { VersionMismatchBanner } from './VersionMismatchBanner'; import CollaborativeWorkflowDiagramImpl from './WorkflowDiagram'; interface CollaborativeWorkflowDiagramProps { @@ -72,14 +75,31 @@ export function CollaborativeWorkflowDiagram({ // Use hook to get run steps with automatic subscription management const currentRunSteps = useRunSteps(selectedRunId); - // Update URL when run selection changes - const handleRunSelect = useCallback((run: Run) => { - setSelectedRunId(run.id); + // Detect version mismatch for warning banner + const versionMismatch = useVersionMismatch(selectedRunId); - const url = new URL(window.location.href); - url.searchParams.set('run', run.id); - window.history.pushState({}, '', url.toString()); - }, []); + // Get version selection handler + const handleVersionSelect = useVersionSelect(); + + // Update URL when run selection changes + const handleRunSelect = useCallback( + (run: Run) => { + setSelectedRunId(run.id); + + // Find the workorder that contains this run + const workorder = history.find(wo => wo.runs.some(r => r.id === run.id)); + + // Switch to the version this run was executed on + if (workorder) { + handleVersionSelect(workorder.version); + } + + const url = new URL(window.location.href); + url.searchParams.set('run', run.id); + window.history.pushState({}, '', url.toString()); + }, + [history, handleVersionSelect] + ); // Clear URL parameter when deselecting run const handleDeselectRun = useCallback(() => { @@ -133,6 +153,15 @@ export function CollaborativeWorkflowDiagram({ return (
+ {/* Version mismatch warning when viewing latest but run used older version */} + {versionMismatch && ( + + )} + state.workflow); + // Clear expanded work order when panel collapses React.useEffect(() => { if (collapsed) { @@ -131,49 +142,30 @@ export default function MiniHistory({ const gotoHistory = (e: React.MouseEvent | React.KeyboardEvent) => { e.preventDefault(); e.stopPropagation(); - const currentUrl = new URL(window.location.href); - const nextUrl = new URL(currentUrl); - const paths = nextUrl.pathname.split('/'); - const wIdx = paths.indexOf('w'); - const workflowPaths = paths.splice(wIdx, paths.length - wIdx); - nextUrl.pathname = paths.join('/') + `/history`; - nextUrl.search = `?filters[workflow_id]=${ - workflowPaths[workflowPaths.length - 1] - }`; - window.location.assign(nextUrl.toString()); + + if (project?.id && workflow?.id) { + navigateToWorkflowHistory(project.id, workflow.id); + } }; - const navigateToWorkorderHistory = ( + const handleNavigateToWorkorderHistory = ( e: React.MouseEvent, workorderId: string ) => { e.preventDefault(); e.stopPropagation(); - const currentUrl = new URL(window.location.href); - const nextUrl = new URL(currentUrl); - const paths = nextUrl.pathname.split('/'); - const projectIndex = paths.indexOf('projects'); - const projectId = projectIndex !== -1 ? paths[projectIndex + 1] : null; - if (projectId) { - nextUrl.pathname = `/projects/${projectId}/history`; - nextUrl.search = `?filters[workorder_id]=${workorderId}`; - window.location.assign(nextUrl.toString()); + if (project?.id) { + navigateToWorkOrderHistory(project.id, workorderId); } }; - const navigateToRunView = (e: React.MouseEvent, runId: string) => { + const handleNavigateToRunView = (e: React.MouseEvent, runId: string) => { e.preventDefault(); e.stopPropagation(); - const currentUrl = new URL(window.location.href); - const nextUrl = new URL(currentUrl); - const paths = nextUrl.pathname.split('/'); - const projectIndex = paths.indexOf('projects'); - const projectId = projectIndex !== -1 ? paths[projectIndex + 1] : null; - if (projectId) { - nextUrl.pathname = `/projects/${projectId}/runs/${runId}`; - window.location.assign(nextUrl.toString()); + if (project?.id) { + navigateToRun(project.id, runId); } }; @@ -342,7 +334,7 @@ export default function MiniHistory({