diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 58f8aec4f..1211c685d 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -80,6 +80,10 @@ const config = { label: 'Akuity.io', position: 'left', }, + { + type: 'custom-version-dropdown', + position: 'right', + }, { href: 'https://kargo.io/', label: 'Kargo.io', diff --git a/docs/src/components/VersionDropdown.css b/docs/src/components/VersionDropdown.css new file mode 100644 index 000000000..8ed8242f6 --- /dev/null +++ b/docs/src/components/VersionDropdown.css @@ -0,0 +1,18 @@ +.version_dropdown { + appearance: none; + -webkit-appearance: none; /* For Safari */ + -moz-appearance: none; /* For Firefox */ + position: relative; + background-color: transparent; + border: 1px solid #ccc; + border-radius: 5px; + cursor: pointer; + padding: 5px 10px; + font-size: 1rem; + font-family: 'Monospace', 'Roboto', 'Open Sans', 'Lato', 'Courier New', monospace; + font-weight: bold; +} + +.version_dropdown option { + font-weight: normal; /* Keeps options normal weight */ +} diff --git a/docs/src/components/VersionDropdown.js b/docs/src/components/VersionDropdown.js new file mode 100644 index 000000000..ebf4984dd --- /dev/null +++ b/docs/src/components/VersionDropdown.js @@ -0,0 +1,122 @@ +import React, { useState, useEffect } from 'react'; +import './VersionDropdown.css'; + +function VersionDropdown() { + console.log("Navbar Version dropdown initialized"); + + const githubApiUrl = 'https://api.github.com/repos/akuity/kargo/branches?protected=true'; + const protocol = 'https://'; + const domain = 'docs.kargo.io'; + const latestVersionLabel = 'Latest Version'; + const latestVersionUrl = `${protocol}${domain}`; + const edgeVersionLabel = 'Edge Version (main)'; + const edgeVersionUrl = `${protocol}main.${domain}`; + const unrecognizedVersionLabel = 'Unrecognized Version'; + + const [versions, setVersions] = useState([]); + const [loading, setLoading] = useState(true); + const [currentVersion, setCurrentVersion] = useState(''); + + // Change the implementation of the currentUrl function to aid in testing + const currentUrl = () => new URL(window.location.href); + + const versionLabel = (major, minor) => `v${major}.${minor}`; + + const fetchVersions = async () => { + try { + console.log("Before fetching versions"); + const response = await fetch(githubApiUrl); + const branches = await response.json(); + console.log("Fetched branches are: ", branches); + + const releaseBranches = branches + .map(branch => branch.name) + .filter(name => /^release-([1-9]\d*\.\d+)$/.test(name)) + .map(name => { + const [major, minor] = name.replace('release-', '').split('.'); + return { + version: versionLabel(major, minor), + url: `${protocol}${name.replace('.', '-')}.${domain}` + }; + }); + + console.log("These are release branches before sorting and updating 0 element: ", releaseBranches); + releaseBranches.sort((a, b) => { + if (a.version > b.version) { + return -1; + } + if (a.version < b.version) { + return 1; + } + return 0; + }); + // Overwrite the first element with the latest version + releaseBranches[0] = { + version: latestVersionLabel, + url: latestVersionUrl + }; + // Put the "edge" version at the end of the list + releaseBranches.push({ + version: edgeVersionLabel, + url: edgeVersionUrl, + }) + const currentVersion = getCurrentVersion(); + // If the current version is not recognized, add it to the end of the list + if (currentVersion === unrecognizedVersionLabel) { + const url = currentUrl(); + releaseBranches.push({ + version: unrecognizedVersionLabel, + url: `${url.protocol}//${url.hostname}${url.port ? `:${url.port}` : ''}` + }); + } + console.log("These are release branches: ", releaseBranches); + setVersions(releaseBranches); + setLoading(false); + } catch (error) { + console.error('Error fetching versions:', error); + setLoading(false); + } + }; + + const getCurrentVersion = () => { + const url = currentUrl(); + if (url.hostname === new URL(latestVersionUrl).hostname && !url.port) { + return 'Latest Version'; + } + if (url.hostname === new URL(edgeVersionUrl).hostname && !url.port) { + return 'Edge Version (main)'; + } + const match = url.hostname.match(/^release-(\d+)-(\d+)\.docs\.kargo\.io$/); + return match && !url.port ? versionLabel(match[1], match[2]) : unrecognizedVersionLabel; + }; + + useEffect(() => { + setCurrentVersion(getCurrentVersion()); + fetchVersions(); + }, []); + + const handleVersionChange = (event) => { + const selectedVersion = versions.find(v => v.version === event.target.value); + if (selectedVersion) { + window.location.href = selectedVersion.url; + } + }; + + if (loading) return null; + + return ( + + ); +} + +export default VersionDropdown; diff --git a/docs/src/theme/NavbarItem/ComponentTypes.js b/docs/src/theme/NavbarItem/ComponentTypes.js new file mode 100644 index 000000000..0704000ff --- /dev/null +++ b/docs/src/theme/NavbarItem/ComponentTypes.js @@ -0,0 +1,7 @@ +import VersionDropdown from '@site/src/components/VersionDropdown'; +import DefaultComponentTypes from '@theme-original/NavbarItem/ComponentTypes'; + +export default { + ...DefaultComponentTypes, + 'custom-version-dropdown': VersionDropdown, +};