From 12b92a66f131d5b0b111f8d65b9636046931cb11 Mon Sep 17 00:00:00 2001 From: Francesco Canovai Date: Thu, 15 May 2025 13:36:57 +0200 Subject: [PATCH] docs: autoselect version (#344) Define functions that can be used in mdx pages to dinamically choose the correct version according to the documentation page viewed. Closes #343 Signed-off-by: Francesco Canovai Signed-off-by: Leonardo Cecchi Signed-off-by: Armando Ruocco Co-authored-by: Leonardo Cecchi Co-authored-by: Armando Ruocco --- .../{installation.md => installation.mdx} | 14 +--- web/docs/migration.md | 2 +- web/docs/usage.md | 2 +- .../components/HomepageFeatures/feature.tsx | 49 ++++++++++++ web/src/components/HomepageFeatures/index.tsx | 78 +++---------------- web/src/components/Installation/index.tsx | 16 ++++ web/src/hooks/versions.ts | 36 +++++++++ web/src/pages/index.tsx | 6 +- web/tsconfig.json | 8 +- 9 files changed, 125 insertions(+), 86 deletions(-) rename web/docs/{installation.md => installation.mdx} (92%) create mode 100644 web/src/components/HomepageFeatures/feature.tsx create mode 100644 web/src/components/Installation/index.tsx create mode 100644 web/src/hooks/versions.ts diff --git a/web/docs/installation.md b/web/docs/installation.mdx similarity index 92% rename from web/docs/installation.md rename to web/docs/installation.mdx index 7dfa73c..85bd41b 100644 --- a/web/docs/installation.md +++ b/web/docs/installation.mdx @@ -4,8 +4,6 @@ sidebar_position: 20 # Installation - - :::important 1. The plugin **must** be installed in the same namespace as the CloudNativePG operator (typically `cnpg-system`). @@ -56,17 +54,12 @@ Both checks are required before proceeding with the installation. ## Installing the Barman Cloud Plugin +import { InstallationSnippet } from '@site/src/components/Installation'; + Install the plugin using `kubectl` by applying the manifest for the latest release: - - -```sh -kubectl apply -f \ - https://github.com/cloudnative-pg/plugin-barman-cloud/releases/download/v0.4.0/manifest.yaml -``` - - + Example output: @@ -114,4 +107,3 @@ following command: kubectl apply -f \ https://raw.githubusercontent.com/cloudnative-pg/plugin-barman-cloud/refs/heads/main/manifest.yaml ``` - diff --git a/web/docs/migration.md b/web/docs/migration.md index 3c4ba98..b91fa0d 100644 --- a/web/docs/migration.md +++ b/web/docs/migration.md @@ -13,7 +13,7 @@ If you're currently relying on the built-in Barman Cloud integration, you can migrate seamlessly to the new **plugin-based architecture** using the Barman Cloud Plugin, with **no downtime**. Follow these steps: -- [Install the Barman Cloud Plugin](installation.md) +- [Install the Barman Cloud Plugin](installation.mdx) - Create an `ObjectStore` resource by translating the contents of the `.spec.backup.barmanObjectStore` section from your existing `Cluster` definition diff --git a/web/docs/usage.md b/web/docs/usage.md index 869dfe2..dcff072 100644 --- a/web/docs/usage.md +++ b/web/docs/usage.md @@ -6,7 +6,7 @@ sidebar_position: 30 -After [installing the plugin](installation.md) in the same namespace as the +After [installing the plugin](installation.mdx) in the same namespace as the CloudNativePG operator, enabling your PostgreSQL cluster to use the Barman Cloud Plugin involves just a few steps: diff --git a/web/src/components/HomepageFeatures/feature.tsx b/web/src/components/HomepageFeatures/feature.tsx new file mode 100644 index 0000000..3a64556 --- /dev/null +++ b/web/src/components/HomepageFeatures/feature.tsx @@ -0,0 +1,49 @@ +import type {ComponentProps, ComponentType, ReactElement} from "react"; +import clsx from "clsx"; +import styles from "@site/src/components/HomepageFeatures/styles.module.css"; +import Heading from "@theme/Heading"; + +type FeatureItem = { + title: string; + Svg: ComponentType>; + description: string; +}; + +function Feature({title, Svg, description}: FeatureItem): ReactElement { + return ( +
+
+ +
+
+ {title} +

{description}

+
+
+ ); +} + +export function FeatureList(): ReactElement { + return ( +
+ + + +
+ ) +} diff --git a/web/src/components/HomepageFeatures/index.tsx b/web/src/components/HomepageFeatures/index.tsx index 1f43ae4..9e4b245 100644 --- a/web/src/components/HomepageFeatures/index.tsx +++ b/web/src/components/HomepageFeatures/index.tsx @@ -1,71 +1,13 @@ -import type {ReactNode} from 'react'; -import clsx from 'clsx'; -import Heading from '@theme/Heading'; +import type {ReactElement} from 'react'; import styles from './styles.module.css'; +import {FeatureList} from './feature'; -type FeatureItem = { - title: string; - Svg: React.ComponentType>; - description: ReactNode; -}; - -const FeatureList: FeatureItem[] = [ - { - title: 'Backup your clusters', - Svg: require('@site/static/img/undraw_going-up_g8av.svg').default, - description: ( - <> - Securely backup your CloudNativePG clusters to object storage with - configurable retention policies and compression options. - - ), - }, - { - title: 'Restore to any point in time', - Svg: require('@site/static/img/undraw_season-change_ohe6.svg').default, - description: ( - <> - Perform flexible restores to any point in time using a combination of - base backups and WAL archives. - - ), - }, - { - title: 'Cloud-native architecture', - Svg: require('@site/static/img/undraw_maintenance_rjtm.svg').default, - description: ( - <> - Seamlessly integrate with all major cloud providers and on-premises object storage - solutions. - - ), - }, -]; - -function Feature({title, Svg, description}: FeatureItem) { - return ( -
-
- -
-
- {title} -

{description}

-
-
- ); -} - -export default function HomepageFeatures(): ReactNode { - return ( -
-
-
- {FeatureList.map((props, idx) => ( - - ))} -
-
-
- ); +export default function HomepageFeatures(): ReactElement { + return ( +
+
+ +
+
+ ); } diff --git a/web/src/components/Installation/index.tsx b/web/src/components/Installation/index.tsx new file mode 100644 index 0000000..064a0ea --- /dev/null +++ b/web/src/components/Installation/index.tsx @@ -0,0 +1,16 @@ +import {ReactElement} from 'react'; +import CodeBlock from '@theme/CodeBlock'; +import {useCurrentVersion} from '@site/src/hooks/versions'; + +// InstallationSnippet is the kubectl incantation to install the lastest +// available version of the Barman Cloud Plugin. +export function InstallationSnippet(): ReactElement { + const latest = useCurrentVersion('latestReleased'); + return ( + + {`kubectl apply -f \\ + https://github.com/cloudnative-pg/plugin-barman-cloud/releases/download/v${latest}/manifest.yaml`} + + ); +} + diff --git a/web/src/hooks/versions.ts b/web/src/hooks/versions.ts new file mode 100644 index 0000000..785cc2f --- /dev/null +++ b/web/src/hooks/versions.ts @@ -0,0 +1,36 @@ +import {useActiveVersion, useLatestVersion, useVersions} from '@docusaurus/plugin-content-docs/client'; + + +export function useCurrentVersion(fallback: 'latest' | 'latestReleased' = 'latest'): string { + switch (fallback) { + case 'latestReleased': + return useLatestReleasedVersion(); + case 'latest': { + const version = useActiveVersion('default'); + return version?.name ?? useLatestVersion('default')?.name; + } + default: + // The following line ensures that if `fallback` is not 'latest' or 'latestReleased', + // an error is thrown. This can be useful for catching unexpected states. + throw new Error(`Unhandled fallback type: ${fallback}`); + } +} + +export function useLatestReleasedVersion(): string { + const allVersions = useVersions('default'); + + // Filter out "current" to only consider versioned docs + const versionedDocs = allVersions.filter(version => version.name !== 'current'); + + // Handle the case where no versioned documents are found + if (versionedDocs.length === 0) { + return "unknown_version"; + } + + const sortedVersions = versionedDocs.sort((a, b) => { + return b.name.localeCompare(a.name, undefined, { numeric: true, sensitivity: 'base' }); + }); + + // The latest version is the first in the sorted list since versionedDocs was not empty, + return sortedVersions[0].name; +} diff --git a/web/src/pages/index.tsx b/web/src/pages/index.tsx index bc6fbe9..427ca31 100644 --- a/web/src/pages/index.tsx +++ b/web/src/pages/index.tsx @@ -1,4 +1,4 @@ -import type {ReactNode} from 'react'; +import type {ReactElement, ReactNode} from 'react'; import clsx from 'clsx'; import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; @@ -8,7 +8,7 @@ import Heading from '@theme/Heading'; import styles from './index.module.css'; -function HomepageHeader() { +function HomepageHeader(): ReactElement { const { siteConfig } = useDocusaurusContext(); return (
@@ -21,7 +21,7 @@ function HomepageHeader() { ); } -export default function Home(): ReactNode { +export default function Home(): ReactElement { const {siteConfig} = useDocusaurusContext(); return (