Skip to content

Commit

Permalink
Fix: Back button not working.
Browse files Browse the repository at this point in the history
It's not perfect, but the back button should now work.

fixes: #476
  • Loading branch information
reglim committed Mar 28, 2023
1 parent e36a820 commit eab1201
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 25 deletions.
55 changes: 30 additions & 25 deletions web/src/pages/Docs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
and we need to use some of it's members, which is unsafe
*/

import { uniqueId } from 'lodash'
import React, { useEffect, useRef, useState } from 'react'
import { useParams, useSearchParams } from 'react-router-dom'
import { useParams, useSearchParams, useNavigate, useLocation } from 'react-router-dom'
import DocumentControlButtons from '../components/DocumentControlButtons'
import ProjectDetails from '../models/ProjectDetails'
import ProjectRepository from '../repositories/ProjectRepository'
Expand All @@ -28,6 +29,8 @@ export default function Docs (): JSX.Element {
const [loadingFailed, setLoadingFailed] = useState<boolean>(false)

const iFrameRef = useRef(null)
const navigate = useNavigate()
const location = useLocation()

document.title = `${project} | docat`

Expand All @@ -37,42 +40,44 @@ export default function Docs (): JSX.Element {

const getVersionToUse = (allVersions: ProjectDetails[]): string => {
if (version === 'latest') {
// latest version -> check if there is a latest tag
const versionWithLatestTag = allVersions.find((v) =>
(v.tags ?? []).includes('latest')
)

// if there is a latest tag, use it,
// otherwise use the latest version by sorting
const latestVersion =
versionWithLatestTag != null
? versionWithLatestTag.name
: allVersions[allVersions.length - 1].name

return latestVersion
return ProjectRepository.getLatestVersion(allVersions).name
}

// custom version -> check if it exists
const versionsAndTags = allVersions.map((v) => [v.name, ...v.tags]).flat()

if (!versionsAndTags.includes(version)) {
return ''
}

return version
return versionsAndTags.includes(version) ? version : ''
}

useEffect(() => {
const url = `/#/${project}/${version}/${page}${hideUi ? '?hide-ui=true' : ''}`
const url = `/${project}/${version}/${page}${hideUi ? '?hide-ui=true' : ''}`

// skip updating the route if the new state is the same as the current one
if (window.location.hash === url.substring(1)) {
// replace if the state is the same or the url contained latest
// this makes sure it is possible to go back to the overview page
if (window.location.hash.substring(1) === url || window.location.hash.includes(`${project}/latest`)) {
navigate(url, { replace: true })
return
}

window.history.pushState({}, '', url)
navigate(url)
}, [project, version, page, hideUi])

/**
* This makes sure, that the iframe is reloaded when the version changes,
* for example through clicking the back button in the browser.
*/
useEffect(() => {
let newPage = window.location.pathname.split('/')[3]
if (newPage == null) {
return
}

newPage = newPage.split('?')[0]

if (newPage !== page) {
setPage(newPage)
}
}, [location])

useEffect(() => {
void (async (): Promise<void> => {
try {
Expand Down Expand Up @@ -119,7 +124,6 @@ export default function Docs (): JSX.Element {
if (iFrameRef?.current == null) {
return
}

// update the path in the url
// @ts-expect-error - ts does not find the location on the iframe
const path: string = iFrameRef.current.contentWindow.location.href as string
Expand Down Expand Up @@ -155,6 +159,7 @@ export default function Docs (): JSX.Element {
<iframe
title="docs"
ref={iFrameRef}
key={uniqueId()}
src={ProjectRepository.getProjectDocsURL(project, version, page)}
onLoad={onIframeLocationChanged}
className={styles['docs-iframe']}
Expand Down
23 changes: 23 additions & 0 deletions web/src/repositories/ProjectRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ async function getVersions (projectName: string): Promise<ProjectDetails[]> {
return json.versions
}

/**
* Returns the latest version of a project.
* Order of precedence: latest, latest tag, latest version
* @param versions all versions of a project
*/
function getLatestVersion (versions: ProjectDetails[]): ProjectDetails {
const latest = versions.find((v) => v.name.includes('latest'))
if (latest != null) {
return latest
}

const latestTag = versions.find((v) => v.tags.includes('latest'))
if (latestTag != null) {
return latestTag
}

const sortedVersions = versions
.sort((a, b) => compareVersions(a, b))

return sortedVersions[sortedVersions.length - 1]
}

/**
* Returns a SearchResult object containing all projects and versions that contain the search query in their name or tag
* @param {Project[]} projects List of all projects
Expand Down Expand Up @@ -239,6 +261,7 @@ function setFavorite (projectName: string, shouldBeFavorite: boolean): void {

const exp = {
getVersions,
getLatestVersion,
filterHiddenVersions,
search,
getProjectLogoURL,
Expand Down
72 changes: 72 additions & 0 deletions web/src/tests/repositories/ProjectRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,3 +460,75 @@ describe('filterHiddenVersions', () => {
expect(result).toStrictEqual([])
})
})

describe('getLatestVersion', () => {
test('should return latest version by name', () => {
const versions: ProjectDetails[] = [
{
name: '1.0.0',
hidden: false,
tags: []
},
{
name: '2.0.0',
hidden: false,
tags: []
}
]

const latestVersion = ProjectRepository.getLatestVersion(versions)
expect(latestVersion).toStrictEqual(versions[1])
})

test('should return version with latest in name', () => {
const versions: ProjectDetails[] = [
{
name: '1.0.0',
hidden: false,
tags: []
},
{
name: 'latest',
hidden: false,
tags: []
}]

const latestVersion = ProjectRepository.getLatestVersion(versions)
expect(latestVersion).toStrictEqual(versions[1])
})

test('should return version with latest tag', () => {
const versions: ProjectDetails[] = [
{
name: '1.0.0',
hidden: false,
tags: ['latest']
},
{
name: '2.0.0',
hidden: false,
tags: []
}]

const latestVersion = ProjectRepository.getLatestVersion(versions)
expect(latestVersion).toStrictEqual(versions[0])
})

test('should prefer version with latest in name over latest tag', () => {
const versions: ProjectDetails[] = [
{
name: 'latest',
hidden: false,
tags: []
},
{
name: '1.0.0',
hidden: false,
tags: ['latest']
}
]

const latestVersion = ProjectRepository.getLatestVersion(versions)
expect(latestVersion).toStrictEqual(versions[0])
})
})

0 comments on commit eab1201

Please sign in to comment.