Skip to content

Commit

Permalink
Fix: Some urls causing loading loop
Browse files Browse the repository at this point in the history
  • Loading branch information
reglim committed Mar 27, 2023
1 parent 7a1e606 commit 791abea
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 19 deletions.
67 changes: 48 additions & 19 deletions web/src/pages/Docs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ import styles from './../style/pages/Docs.module.css'
import LoadingPage from './LoadingPage'
import NotFound from './NotFound'

const trimSlash = (str: string): string => {
str = str.trim()

while (str.charAt(0) === '/') {
str = str.substring(1)
}

while (str.charAt(str.length - 1) === '/') {
str = str.substring(0, str.length - 1)
}

return str
}

export default function Docs (): JSX.Element {
const projectParam = useParams().project ?? ''
const versionParam = useParams().version ?? 'latest'
Expand All @@ -23,7 +37,7 @@ export default function Docs (): JSX.Element {

const [project] = useState<string>(projectParam)
const [version, setVersion] = useState<string>(versionParam)
const [page, setPage] = useState<string>(pageParam)
const [page, setPage] = useState<string>(trimSlash(pageParam))
const [hideUi, setHideUi] = useState<boolean>(hideUiParam)
const [versions, setVersions] = useState<ProjectDetails[]>([])
const [loadingFailed, setLoadingFailed] = useState<boolean>(false)
Expand All @@ -40,19 +54,7 @@ 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
Expand All @@ -70,11 +72,25 @@ export default function Docs (): JSX.Element {

// 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`)) {
if (window.location.hash.includes(`${project}/latest`)) {
navigate(url, { replace: true })
return
}

const oldUrl = window.location.hash.substring(1)
const oldProject = oldUrl.split('/')[1]
const oldVersion = oldUrl.split('/')[2]
const oldPage = oldUrl.split('/')[3].split('?')[0]
const oldHideUi = oldUrl.includes('hide-ui=true')

const isSameUrl = oldProject === project && oldVersion === version && oldPage === page && oldHideUi === hideUi

console.log('update url', url, oldUrl, oldProject, oldVersion, oldPage, project, version, page, oldHideUi, hideUi, isSameUrl)

if (isSameUrl) {
return
}

navigate(url)
}, [project, version, page, hideUi])

Expand All @@ -88,26 +104,30 @@ export default function Docs (): JSX.Element {
return
}

// remove query params
newPage = newPage.split('?')[0]
newPage = trimSlash(newPage)

if (newPage === page) {
return
}

console.log('update page', newPage, page)

setPage(newPage)
}, [location])

useEffect(() => {
void (async (): Promise<void> => {
try {
let allVersions = await ProjectRepository.getVersions(project)
allVersions = allVersions.sort((a, b) => ProjectRepository.compareVersions(a, b))

if (allVersions.length === 0) {
setLoadingFailed(true)
return
}

allVersions = allVersions.sort((a, b) => ProjectRepository.compareVersions(a, b))
const versionToUse = getVersionToUse(allVersions)

if (versionToUse === '') {
Expand Down Expand Up @@ -147,13 +167,22 @@ export default function Docs (): JSX.Element {
// 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
const page = path.split(`${version}/`)[1]
let newPage = path.split(`${version}/`)[1]

if (newPage == null) {
return
}

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

if (page == null || page.trim().length < 1) {
if (newPage.length < 1 || newPage === page) {
return
}

setPage(page)
console.log('update page', newPage, page, path)

setPage(newPage)

// make all links in iframe open in new tab
// @ts-expect-error - ts does not find the document on the 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 791abea

Please sign in to comment.