diff --git a/frontend/common/hooks/__tests__/useLastEnv.test.ts b/frontend/common/hooks/__tests__/useLastEnv.test.ts new file mode 100644 index 000000000000..4d65658a5cf3 --- /dev/null +++ b/frontend/common/hooks/__tests__/useLastEnv.test.ts @@ -0,0 +1,16 @@ +import { parseLastEnv } from 'common/hooks/useLastEnv' + +describe('parseLastEnv', () => { + it('reads what usePageTracking wrote', () => { + const raw = JSON.stringify({ environmentId: 'abc', orgId: 1, projectId: 2 }) + expect(parseLastEnv(raw)).toEqual({ + environmentId: 'abc', + orgId: 1, + projectId: 2, + }) + }) + + it.each([null, '', 'not json', '{'])('survives %p', (raw) => { + expect(parseLastEnv(raw)).toBeNull() + }) +}) diff --git a/frontend/common/hooks/useLastEnv.ts b/frontend/common/hooks/useLastEnv.ts new file mode 100644 index 000000000000..c6455a057047 --- /dev/null +++ b/frontend/common/hooks/useLastEnv.ts @@ -0,0 +1,31 @@ +import { useEffect, useState } from 'react' + +// `lastEnv` is written by usePageTracking as you browse, and read by App and Nav +// to restore where you were. environmentId is the api_key, since routes use it. +export type LastEnv = { + orgId?: number | string + projectId?: number | string + environmentId?: string +} + +export const parseLastEnv = (raw: string | null): LastEnv | null => { + if (!raw) return null + try { + return JSON.parse(raw) + } catch { + return null + } +} + +export const useLastEnv = (): LastEnv | null => { + const [lastEnv, setLastEnv] = useState(null) + + useEffect(() => { + if (typeof AsyncStorage === 'undefined') return + Promise.resolve(AsyncStorage.getItem('lastEnv')).then((raw) => + setLastEnv(parseLastEnv(raw)), + ) + }, []) + + return lastEnv +} diff --git a/frontend/web/components/navigation/navbars/TopNavbar.tsx b/frontend/web/components/navigation/navbars/TopNavbar.tsx index 060b22bf5e32..b9ec039caccb 100644 --- a/frontend/web/components/navigation/navbars/TopNavbar.tsx +++ b/frontend/web/components/navigation/navbars/TopNavbar.tsx @@ -8,6 +8,7 @@ import Headway from 'components/Headway' import { Project } from 'common/types/responses' import AccountDropdown from 'components/navigation/AccountDropdown' import ThemeToggle from 'components/ThemeToggle' +import { useLastEnv } from 'common/hooks/useLastEnv' type TopNavType = { activeProject: Project | undefined @@ -15,6 +16,14 @@ type TopNavType = { } const TopNavbar: FC = ({ activeProject, projectId }) => { + // Name the project the tour should run against: the one you're in, else the + // one you were last in. Without it the page falls back to the org's first. + const lastEnv = useLastEnv() + const onboardingProjectId = projectId ?? lastEnv?.projectId + const gettingStartedTo = onboardingProjectId + ? `/getting-started?project=${onboardingProjectId}` + : '/getting-started' + return (