Skip to content
Snippets Groups Projects
Commit 0fc0b439 authored by Mark Kane's avatar Mark Kane
Browse files

refactor async version fetching code to react hook

optimize to reduce number of required request
upgrade JSONSchema to also use useVersion hook and support query string
(planning#679)
parent 0ed2d277
No related branches found
No related tags found
1 merge request!304add version query param to ApiSpec
import axios from "axios"; import axios from "axios";
import semver from "semver"; import semver from "semver";
export default async function ({siteVersion, projectId, includePrerelease = false}) { export default async function ({ siteVersion, projectId, includePrerelease = false, versions = null }) {
const filterResult = (data) => {
const versionRange = `~${siteVersion}`
const suitableVersions = data
.filter(({name}) => semver.satisfies(name, versionRange, {includePrerelease}))
.map(({name}) => name)
.sort()
const result_version = semver.maxSatisfying(suitableVersions, versionRange, {includePrerelease})
console.log('Get version for project: %s, requested version: %s, includePrerelease: %s, available versions: %s, selected version: %s', projectId, siteVersion, includePrerelease, suitableVersions, result_version)
return result_version
}
if (siteVersion === 'latest') { if (siteVersion === 'latest') {
return 'latest' return 'latest'
} else if (versions) {
return filterResult(versions.map((name) => {
return {name}
}))
} else { } else {
return axios.get(`https://git.fitko.de/api/v4/projects/${projectId}/repository/tags`) return axios.get(`https://git.fitko.de/api/v4/projects/${projectId}/repository/tags`)
.catch((error) => { .catch((error) => {
throw `Fetching of latest tags failed with ${error.response.status}` throw `Fetching of latest tags failed with ${error.response.status}`
}) })
.then(async ({data}) => { .then(async ({data}) => {
const versionRange = `~${siteVersion}` return filterResult(await data)
const suitableVersions = await data
.filter(({name}) => semver.satisfies(name, versionRange, {includePrerelease}))
.map(({name}) => name)
.sort()
const result_version = semver.maxSatisfying(suitableVersions, versionRange, {includePrerelease})
// console.log('Get version for project: %s, requested version: %s, includePrerelease: %s, available versions: %s, selected version: %s', projectId, siteVersion, includePrerelease, suitableVersions, result_version)
return result_version
}) })
} }
} }
...@@ -2,6 +2,7 @@ import axios from "axios"; ...@@ -2,6 +2,7 @@ import axios from "axios";
import semver from "semver"; import semver from "semver";
export default async function ({projectId, includePrerelease = false}) { export default async function ({projectId, includePrerelease = false}) {
console.log('projectId, includePrerelease: ', projectId, includePrerelease);
return axios.get(`https://git.fitko.de/api/v4/projects/${projectId}/repository/tags`) return axios.get(`https://git.fitko.de/api/v4/projects/${projectId}/repository/tags`)
.catch((error) => { .catch((error) => {
throw `Fetching of tags failed with ${error.response.status}` throw `Fetching of tags failed with ${error.response.status}`
......
import { useEffect, useState } from 'react'
import useAsync from '@hooks/useAsync'
import semver from 'semver'
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'
import getLatestVersion from '@lib/utils/getLatestVersion'
import getVersionList from '@lib/utils/getVersionList'
function useVersion(version, queryVersion, gitlabProjectId, includePrerelease, includePrereleaseVersion) {
const [selectedVersion, setSelectedVersion] = useState(version);
const isInBrowser = ExecutionEnvironment.canUseDOM
const {execute: executeList, status: statusList, value: versions} = useAsync(getVersionList, {
projectId: gitlabProjectId,
includePrerelease,
}, false)
const getLatestVersionOptions = {
siteVersion: version === undefined ? '*' : version,
projectId: gitlabProjectId,
includePrerelease: !!includePrereleaseVersion,
versions: versions,
}
const {execute, status, value: latestVersion} = useAsync(() => getLatestVersion(getLatestVersionOptions), {}, false)
if (isInBrowser) {
useEffect(() => {
executeList()
}, [])
useEffect(async () => {
if (statusList === 'success') {
getLatestVersionOptions.versions = versions
execute()
}
}, [statusList])
useEffect(async () => {
if (status === 'success' || latestVersion) {
if (semver.valid(queryVersion) && versions.includes(queryVersion)) {
setSelectedVersion(queryVersion)
} else {
setSelectedVersion(version && !version.includes('*') ? version : latestVersion)
}
}
}, [status])
}
return [versions, selectedVersion, setSelectedVersion];
}
export default useVersion;
import React, {useEffect, useState} from 'react' import React, {useEffect, useState} from 'react'
import semver from 'semver'
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'
import BrowserOnly from '@docusaurus/BrowserOnly' import BrowserOnly from '@docusaurus/BrowserOnly'
import { useLocation } from '@docusaurus/router' import { useLocation } from '@docusaurus/router'
import useAsync from '@hooks/useAsync'
import getLatestVersion from '@lib/utils/getLatestVersion'
import getVersionList from '@lib/utils/getVersionList'
import DownloadLabel from '@components/DownloadLabel' import DownloadLabel from '@components/DownloadLabel'
import VersionSelect from '@components/VersionSelect' import VersionSelect from '@components/VersionSelect'
import useVersion from '@lib/utils/useVersion'
const SCHEMA_BASE_URL = 'https://schema.fitko.de/fit-connect' const SCHEMA_BASE_URL = 'https://schema.fitko.de/fit-connect'
...@@ -18,42 +13,8 @@ export default function ApiSpec(props) { ...@@ -18,42 +13,8 @@ export default function ApiSpec(props) {
let { version } = props let { version } = props
const search = useLocation().search; const search = useLocation().search;
const queryVersion = new URLSearchParams(search).get('version'); const queryVersion = new URLSearchParams(search).get('version');
const [selectedVersion, setSelectedVersion] = useState('') const [versionList, selectedVersion, setSelectedVersion] =
useVersion(version, queryVersion, gitlabProjectId, includePrerelease, includePrereleaseVersion)
const isInBrowser = ExecutionEnvironment.canUseDOM
const {execute: executeList, status: statusList, value: versions} = useAsync(getVersionList, {
projectId: gitlabProjectId,
includePrerelease,
}, false)
const {execute, status, value: latestVersion} = useAsync(getLatestVersion, {
siteVersion: version === undefined ? '*' : version,
projectId: gitlabProjectId,
includePrerelease: !!includePrereleaseVersion
}, false)
if (isInBrowser) {
useEffect(() => {
executeList()
}, [])
useEffect(async () => {
if (statusList === 'success') {
execute()
}
}, [statusList])
useEffect(async () => {
if (status === 'success') {
if (semver.valid(queryVersion) && versions.includes(queryVersion)) {
setSelectedVersion(queryVersion)
} else {
setSelectedVersion(version && version !== '*' ? version : latestVersion)
}
}
}, [status])
}
return ( return (
<BrowserOnly fallback={<div>Lädt...</div>}> <BrowserOnly fallback={<div>Lädt...</div>}>
...@@ -66,8 +27,8 @@ export default function ApiSpec(props) { ...@@ -66,8 +27,8 @@ export default function ApiSpec(props) {
<DownloadLabel baseURL={`${SCHEMA_BASE_URL}/${path}`} version={selectedVersion} artifact={artifact} label="OpenAPI"/>}. <DownloadLabel baseURL={`${SCHEMA_BASE_URL}/${path}`} version={selectedVersion} artifact={artifact} label="OpenAPI"/>}.
</p> </p>
{statusList === 'success' && selectedVersion && <VersionSelect {selectedVersion && <VersionSelect
versions={versions} versions={versionList}
version={selectedVersion} version={selectedVersion}
setVersion={setSelectedVersion} setVersion={setSelectedVersion}
gitlabId={gitlabProjectId} gitlabId={gitlabProjectId}
...@@ -75,7 +36,7 @@ export default function ApiSpec(props) { ...@@ -75,7 +36,7 @@ export default function ApiSpec(props) {
/>} />}
<br /> <br />
{status === 'success' && selectedVersion && <rapi-doc {!selectedVersion.includes('*') && <rapi-doc
render-style="view" render-style="view"
layout="column" layout="column"
spec-url={`${SCHEMA_BASE_URL}/${path}/${selectedVersion}/${artifact}`} spec-url={`${SCHEMA_BASE_URL}/${path}/${selectedVersion}/${artifact}`}
......
...@@ -2,15 +2,12 @@ import React, {useEffect, useState} from 'react' ...@@ -2,15 +2,12 @@ import React, {useEffect, useState} from 'react'
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment' import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'
import BrowserOnly from '@docusaurus/BrowserOnly' import BrowserOnly from '@docusaurus/BrowserOnly'
import axios from 'axios' import axios from 'axios'
import { JsonSchemaViewer } from "@stoplight/json-schema-viewer" import { useLocation } from '@docusaurus/router'
import { JsonSchemaViewer } from '@stoplight/json-schema-viewer'
import {useActivePlugin, useActiveVersion,} from '@docusaurus/plugin-content-docs/client' import useVersion from '@lib/utils/useVersion'
import DownloadLabel from '@components/DownloadLabel'
import useAsync from '@hooks/useAsync' import VersionSelect from '@components/VersionSelect'
import getLatestVersion from "@lib/utils/getLatestVersion";
import getVersionList from '@lib/utils/getVersionList'
import DownloadLabel from "@components/DownloadLabel";
import VersionSelect from "@components/VersionSelect";
const SCHEMA_BASE_URL = 'https://schema.fitko.de/fit-connect/metadata' const SCHEMA_BASE_URL = 'https://schema.fitko.de/fit-connect/metadata'
const SCHEMA_FILE_NAME = 'metadata.schema.json' const SCHEMA_FILE_NAME = 'metadata.schema.json'
...@@ -35,63 +32,37 @@ const loadSchema = async (version, name) => { ...@@ -35,63 +32,37 @@ const loadSchema = async (version, name) => {
export default function JSONSchema(props) { export default function JSONSchema(props) {
const { name, version, includePrerelease } = props; const { name, version, includePrerelease } = props;
const [jsonSchema, setJsonSchema] = useState(null) const [jsonSchema, setJsonSchema] = useState(null)
const [selectedVersion, setSelectedVersion] = useState(version)
const isInBrowser = ExecutionEnvironment.canUseDOM const isInBrowser = ExecutionEnvironment.canUseDOM
const {pluginId} = useActivePlugin({failfast: true}) const search = useLocation().search;
const {name: siteVersion} = useActiveVersion(pluginId) const queryVersion = new URLSearchParams(search).get('version');
const schemaUrl = name === 'set' ? SCHEMA_BASE_URL_SET : SCHEMA_BASE_URL; const schemaUrl = name === 'set' ? SCHEMA_BASE_URL_SET : SCHEMA_BASE_URL;
const schemaName = name === 'set' ? SCHEMA_FILE_NAME_SET : SCHEMA_FILE_NAME; const schemaName = name === 'set' ? SCHEMA_FILE_NAME_SET : SCHEMA_FILE_NAME;
const gitlabId = name === 'set' ? GITLAB_PROJECT_ID_SET : GITLAB_PROJECT_ID; const gitlabProjectId = name === 'set' ? GITLAB_PROJECT_ID_SET : GITLAB_PROJECT_ID;
const {execute: executeList, status: statusList, value: versions} = useAsync(getVersionList, {
projectId: GITLAB_PROJECT_ID,
includePrerelease: includePrerelease !== undefined,
}, false)
const {execute, status, error, value: latestVersion} = useAsync(getLatestVersion, { const [versionList, selectedVersion, setSelectedVersion] =
siteVersion: selectedVersion === undefined ? '*' : selectedVersion, useVersion(version, queryVersion, gitlabProjectId, includePrerelease, null)
projectId: GITLAB_PROJECT_ID,
includePrerelease: includePrerelease !== undefined,
}, false)
if (isInBrowser) { if (isInBrowser) {
useEffect(() => {
executeList()
}, [])
useEffect(async () => { useEffect(async () => {
if (!selectedVersion.includes('*')) { if (!selectedVersion.includes('*')) {
setJsonSchema(await loadSchema(selectedVersion, name)) setJsonSchema(await loadSchema(selectedVersion, name))
} }
}, [selectedVersion]) }, [selectedVersion])
useEffect(async () => {
if (statusList === 'success') {
execute()
}
}, [statusList])
useEffect(async () => {
if (status === 'success') {
setSelectedVersion(latestVersion)
setJsonSchema(await loadSchema(latestVersion, name))
}
}, [status])
} }
return ( return (
<BrowserOnly fallback={<div>Lädt...</div>}> <BrowserOnly fallback={<div>Lädt...</div>}>
{() => ( {() => (
<div> <div>
<p>Die aktuell angezeigte Version des JSON Schema ist {status === 'success' && <p>Die aktuell angezeigte Version {status === 'success' &&
<code>{selectedVersion}</code>} {status === 'success' && <code>{selectedVersion}</code>} {selectedVersion &&
<DownloadLabel baseURL={schemaUrl} version={selectedVersion} artifact={schemaName} label="JSON Schema"/>}. <DownloadLabel baseURL={schemaUrl} version={selectedVersion} artifact={schemaName} label="JSON Schema"/>}.
</p> </p>
{statusList === 'success' && <VersionSelect {versionList && <VersionSelect
versions={versions} versions={versionList}
version={selectedVersion} version={selectedVersion}
setVersion={setSelectedVersion} setVersion={setSelectedVersion}
gitlabId={gitlabId}/> gitlabId={gitlabProjectId}/>
} }
<br /> <br />
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment