From 680e1e73721bde8d7079152885882f09d2929d9d Mon Sep 17 00:00:00 2001 From: "vault-token-factory-spectrocloud[bot]" <133815545+vault-token-factory-spectrocloud[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:26:50 +0000 Subject: [PATCH] docs: change simple cards to use versioned link DOC-1502 (#4971) (#5044) * docs: change simple cards to use versioned link DOC-1502 * docs: fix bad link * docs: add versioned link test cases * docs: add readme to used images list * docs: skip vale on additional capabilities page * Optimised images with calibre/image-actions * docs: adjust readme * docs: remove wrongly added div --------- Co-authored-by: vault-token-factory-spectrocloud[bot] <133815545+vault-token-factory-spectrocloud[bot]@users.noreply.github.com> (cherry picked from commit ab95159a539e910b6842710c7d4f6169a5b67e57) Co-authored-by: Adelina Simion <43963729+addetz@users.noreply.github.com> --- README.md | 10 +++-- .../additional-capabilities.md | 8 ++-- docs/docs-content/getting-started/aws/aws.md | 12 +++--- .../getting-started/azure/azure.md | 12 +++--- docs/docs-content/getting-started/gcp/gcp.md | 12 +++--- .../getting-started/getting-started.md | 12 +++--- .../getting-started/introduction.md | 8 ++-- .../getting-started/vmware/vmware.md | 14 +++---- docs/docs-content/tutorials/tutorials.md | 14 ++++--- scripts/find-unused-images.sh | 6 ++- .../SimpleCardGrid/SimpleCardGrid.test.tsx | 16 +++++--- .../SimpleCardGrid/SimpleCardGrid.tsx | 37 ++++++++++-------- .../VersionedLink/VersionedLink.test.tsx | 26 ++++++++++++ .../VersionedLink/VersionedLink.tsx | 18 ++++++++- .../assets/docs/images/hide_copy_button.webp | Bin 0 -> 4206 bytes .../docs/images/hide_copy_button_example.webp | Bin 0 -> 5912 bytes 16 files changed, 132 insertions(+), 73 deletions(-) create mode 100644 static/assets/docs/images/hide_copy_button.webp create mode 100644 static/assets/docs/images/hide_copy_button_example.webp diff --git a/README.md b/README.md index e22c47da8d..54ad6a3a48 100644 --- a/README.md +++ b/README.md @@ -541,7 +541,9 @@ To add a video, use the following syntax. Ensure you capitalize the letter "V": ### Simple Card Grid This is a custom component that creates a grid of simple text cards with two columns, styled according to our color -scheme. The rows of cards are dynamically created according to the list of specified cards. +scheme. The rows of cards are dynamically created according to the list of specified cards. This component uses the +`VersionedLink` under the covers. URLs should be specified as discussed in the [Internal Links](#internal-links) +section. ```js diff --git a/docs/docs-content/getting-started/additional-capabilities/additional-capabilities.md b/docs/docs-content/getting-started/additional-capabilities/additional-capabilities.md index 2d19746ff4..ba6c473f19 100644 --- a/docs/docs-content/getting-started/additional-capabilities/additional-capabilities.md +++ b/docs/docs-content/getting-started/additional-capabilities/additional-capabilities.md @@ -55,6 +55,8 @@ Started section to learn how they can grow with Palette and have a long-term rel In this section, you get an overview of other parts of Palette not yet covered by your Getting Started journey so far. Explore more through the following pages. + + diff --git a/docs/docs-content/getting-started/aws/aws.md b/docs/docs-content/getting-started/aws/aws.md index 65b549b94a..286e0d2313 100644 --- a/docs/docs-content/getting-started/aws/aws.md +++ b/docs/docs-content/getting-started/aws/aws.md @@ -30,37 +30,37 @@ your cluster is deployed, you can update it using cluster profile updates. title: "Set up Palette with AWS", description: "Set up the prerequisites of using Palette with AWS.", buttonText: "Learn more", - relativeURL: "./setup", + url: "/getting-started/aws/setup", }, { title: "Create a Cluster Profile", description: "Create a full cluster profile in Palette.", buttonText: "Learn more", - relativeURL: "./create-cluster-profile", + url: "/getting-started/aws/create-cluster-profile", }, { title: "Deploy a Cluster", description: "Deploy a Palette host cluster to AWS.", buttonText: "Learn more", - relativeURL: "./deploy-k8s-cluster", + url: "/getting-started/aws/deploy-k8s-cluster", }, { title: "Deploy Cluster Profile Updates", description: "Update your deployed clusters using Palette Cluster Profiles.", buttonText: "Learn more", - relativeURL: "./update-k8s-cluster", + url: "/getting-started/aws/update-k8s-cluster", }, { title: "Cluster Management with Terraform", description: "Deploy and update a Palette host cluster with Terraform.", buttonText: "Learn more", - relativeURL: "./deploy-manage-k8s-cluster-tf", + url: "/getting-started/aws/deploy-manage-k8s-cluster-tf", }, { title: "Scale, Upgrade, and Secure Clusters", description: "Learn how to scale, upgrade, and secure Palette host clusters deployed to AWS.", buttonText: "Learn more", - relativeURL: "./scale-secure-cluster", + url: "/getting-started/aws/scale-secure-cluster", }, ]} /> diff --git a/docs/docs-content/getting-started/azure/azure.md b/docs/docs-content/getting-started/azure/azure.md index 3503036dde..a610b2854b 100644 --- a/docs/docs-content/getting-started/azure/azure.md +++ b/docs/docs-content/getting-started/azure/azure.md @@ -30,37 +30,37 @@ your cluster is deployed, you can update it using cluster profile updates. title: "Set up Palette with Azure", description: "Set up the prerequisites of using Palette with Azure.", buttonText: "Learn more", - relativeURL: "./setup", + url: "/getting-started/azure/setup", }, { title: "Create a Cluster Profile", description: "Create a full cluster profile in Palette.", buttonText: "Learn more", - relativeURL: "./create-cluster-profile", + url: "/getting-started/azure/create-cluster-profile", }, { title: "Deploy a Cluster", description: "Deploy a Palette host cluster to Azure.", buttonText: "Learn more", - relativeURL: "./deploy-k8s-cluster", + url: "/getting-started/azure/deploy-k8s-cluster", }, { title: "Deploy Cluster Profile Updates", description: "Update your deployed clusters using Palette Cluster Profiles.", buttonText: "Learn more", - relativeURL: "./update-k8s-cluster", + url: "/getting-started/azure/update-k8s-cluster", }, { title: "Cluster Management with Terraform", description: "Deploy and update a Palette host cluster with Terraform.", buttonText: "Learn more", - relativeURL: "./deploy-manage-k8s-cluster-tf", + url: "/getting-started/azure/deploy-manage-k8s-cluster-tf", }, { title: "Scale, Upgrade, and Secure Clusters", description: "Learn how to scale, upgrade, and secure Palette host clusters deployed to Azure.", buttonText: "Learn more", - relativeURL: "./scale-secure-cluster", + url: "/getting-started/azure/scale-secure-cluster", }, ]} /> diff --git a/docs/docs-content/getting-started/gcp/gcp.md b/docs/docs-content/getting-started/gcp/gcp.md index b15e5200ce..db882c84d7 100644 --- a/docs/docs-content/getting-started/gcp/gcp.md +++ b/docs/docs-content/getting-started/gcp/gcp.md @@ -30,37 +30,37 @@ your cluster is deployed, you can update it using cluster profile updates. title: "Set up Palette with GCP", description: "Set up the prerequisites of using Palette with GCP.", buttonText: "Learn more", - relativeURL: "./setup", + url: "/getting-started/gcp/setup", }, { title: "Create a Cluster Profile", description: "Create a full cluster profile in Palette.", buttonText: "Learn more", - relativeURL: "./create-cluster-profile", + url: "/getting-started/gcp/create-cluster-profile", }, { title: "Deploy a Cluster", description: "Deploy a Palette host cluster to GCP.", buttonText: "Learn more", - relativeURL: "./deploy-k8s-cluster", + url: "/getting-started/gcp/deploy-k8s-cluster", }, { title: "Deploy Cluster Profile Updates", description: "Update your deployed clusters using Palette Cluster Profiles.", buttonText: "Learn more", - relativeURL: "./update-k8s-cluster", + url: "/getting-started/gcp/update-k8s-cluster", }, { title: "Cluster Management with Terraform", description: "Deploy and update a Palette host cluster with Terraform.", buttonText: "Learn more", - relativeURL: "./deploy-manage-k8s-cluster-tf", + url: "/getting-started/gcp/deploy-manage-k8s-cluster-tf", }, { title: "Scale, Upgrade, and Secure Clusters", description: "Learn how to scale, upgrade, and secure Palette host clusters deployed to GCP.", buttonText: "Learn more", - relativeURL: "./scale-secure-cluster", + url: "/getting-started/gcp/scale-secure-cluster", }, ]} /> diff --git a/docs/docs-content/getting-started/getting-started.md b/docs/docs-content/getting-started/getting-started.md index fc29e91d72..70be39162c 100644 --- a/docs/docs-content/getting-started/getting-started.md +++ b/docs/docs-content/getting-started/getting-started.md @@ -57,37 +57,37 @@ Explore more through the following pages. title: "Introduction to Palette", description: "Learn about what makes Palette different.", buttonText: "Learn more", - relativeURL: "./introduction", + url: "/getting-started/introduction", }, { title: "Deploy a Cluster to Amazon Web Services (AWS)", description: "Deploy and update a Palette host cluster to AWS.", buttonText: "Learn more", - relativeURL: "./aws", + url: "/getting-started/aws", }, { title: "Deploy a Cluster to Microsoft Azure", description: "Deploy and update a Palette host cluster to Azure.", buttonText: "Learn more", - relativeURL: "./azure", + url: "/getting-started/azure", }, { title: "Deploy a Cluster to Google Cloud Platform (GCP)", description: "Deploy and update a Palette host cluster to Google Cloud.", buttonText: "Learn more", - relativeURL: "./gcp", + url: "/getting-started/gcp", }, { title: "Deploy a Cluster to VMware", description: "Deploy and update a Palette host cluster to VMware vSphere.", buttonText: "Learn more", - relativeURL: "./vmware", + url: "/getting-started/vmware", }, { title: "Additional Capabilities", description: "Learn about Palette's additional capabilities.", buttonText: "Learn more", - relativeURL: "./additional-capabilities", + url: "/getting-started/additional-capabilities", }, ]} /> diff --git a/docs/docs-content/getting-started/introduction.md b/docs/docs-content/getting-started/introduction.md index b06c076a1b..26182269af 100644 --- a/docs/docs-content/getting-started/introduction.md +++ b/docs/docs-content/getting-started/introduction.md @@ -89,25 +89,25 @@ Select your infrastructure provider to start exploring Palette. title: "Deploy a Cluster to Amazon Web Services (AWS)", description: "Deploy and update a Palette host cluster to AWS.", buttonText: "Learn more", - relativeURL: "../aws", + url: "/getting-started/aws", }, { title: "Deploy a Cluster to Microsoft Azure", description: "Deploy and update a Palette host cluster to Azure.", buttonText: "Learn more", - relativeURL: "../azure", + url: "/getting-started/azure", }, { title: "Deploy a Cluster to Google Cloud Platform (GCP)", description: "Deploy and update a Palette host cluster to Google Cloud.", buttonText: "Learn more", - relativeURL: "../gcp", + url: "/getting-started/gcp", }, { title: "Deploy a Cluster to VMware", description: "Deploy and update a Palette host cluster to VMware vSphere.", buttonText: "Learn more", - relativeURL: "../vmware", + url: "/getting-started/vmware", }, ]} /> diff --git a/docs/docs-content/getting-started/vmware/vmware.md b/docs/docs-content/getting-started/vmware/vmware.md index efb584707a..a44cc8e358 100644 --- a/docs/docs-content/getting-started/vmware/vmware.md +++ b/docs/docs-content/getting-started/vmware/vmware.md @@ -30,43 +30,43 @@ Once your cluster is deployed, you can update it using cluster profile updates. title: "Set up Palette with VMware", description: "Set up the prerequisites of using Palette with VMware.", buttonText: "Learn more", - relativeURL: "./setup", + url: "/getting-started/vmware/setup", }, { title: "Deploy a PCG", description: "Learn to deploy a PCG with Palette CLI.", buttonText: "Learn more", - relativeURL: "./deploy-pcg", + url: "/getting-started/vmware/deploy-pcg", }, { title: "Create a Cluster Profile", description: "Create a full cluster profile in Palette.", buttonText: "Learn more", - relativeURL: "./create-cluster-profile", + url: "/getting-started/vmware/create-cluster-profile", }, { title: "Deploy a Cluster", description: "Deploy a Palette host cluster to VMware.", buttonText: "Learn more", - relativeURL: "./deploy-k8s-cluster", + url: "/getting-started/vmware/deploy-k8s-cluster", }, { title: "Deploy Cluster Profile Updates", description: "Update your deployed clusters using Palette Cluster Profiles.", buttonText: "Learn more", - relativeURL: "./update-k8s-cluster", + url: "/getting-started/vmware/update-k8s-cluster", }, { title: "Cluster Management with Terraform", description: "Deploy and update a Palette host cluster with Terraform.", buttonText: "Learn more", - relativeURL: "./deploy-manage-k8s-cluster-tf", + url: "/getting-started/vmware/deploy-manage-k8s-cluster-tf", }, { title: "Scale, Upgrade, and Secure Clusters", description: "Learn how to scale, upgrade, and secure Palette host clusters deployed to VMware.", buttonText: "Learn more", - relativeURL: "./scale-secure-cluster", + url: "/getting-started/vmware/scale-secure-cluster", }, ]} /> diff --git a/docs/docs-content/tutorials/tutorials.md b/docs/docs-content/tutorials/tutorials.md index 365b63f138..7cc5aec711 100644 --- a/docs/docs-content/tutorials/tutorials.md +++ b/docs/docs-content/tutorials/tutorials.md @@ -32,6 +32,8 @@ concepts. Explore more through the following tutorials. + + diff --git a/scripts/find-unused-images.sh b/scripts/find-unused-images.sh index 0adc4a4d62..512d24f921 100755 --- a/scripts/find-unused-images.sh +++ b/scripts/find-unused-images.sh @@ -5,7 +5,7 @@ set -e # Create a list of all the images we have and save it to a json. # Trim the path static/assets/docs/images. -find static/assets/docs/images -type f \( -name "*.gif" -o -name "*.webp" \) ! -name ".DS_STORE" ! -name ".DS_Store" | sed 's|static/assets/docs/images||g' > all_images.json +find static/assets/docs/images README.md -type f \( -name "*.gif" -o -name "*.webp" \) ! -name ".DS_STORE" ! -name ".DS_Store" | sed 's|static/assets/docs/images||g' > all_images.json image_count=$(wc -l < all_images.json) echo "Detected $image_count .webp and .gif assets in static/assets/docs/images..." @@ -28,9 +28,10 @@ echo "$branches" > evaluated_branches.json for current_branch in $branches; do git checkout $current_branch + grep -Hn -E "\.webp|\.gif" README.md > readme_used_images.json find docs -type f -name "*.md" -exec grep -Hn -E "\.webp|\.gif" {} \; > docs_used_images.json find _partials -type f -name "*.mdx" -exec grep -Hn -E "\.webp|\.gif" {} \; > partials_used_images.json - cat docs_used_images.json partials_used_images.json > used_images.json + cat readme_used_images.json docs_used_images.json partials_used_images.json > used_images.json line_number=1 for img in $(cat all_images.json); do @@ -48,6 +49,7 @@ echo "Detected $unused_image_count unused webp assets in static/assets/docs/imag # Clean up files rm all_images.json +rm readme_used_images.json rm docs_used_images.json rm partials_used_images.json rm used_images.json diff --git a/src/components/SimpleCardGrid/SimpleCardGrid.test.tsx b/src/components/SimpleCardGrid/SimpleCardGrid.test.tsx index 3de9a9eb61..06b16822ea 100644 --- a/src/components/SimpleCardGrid/SimpleCardGrid.test.tsx +++ b/src/components/SimpleCardGrid/SimpleCardGrid.test.tsx @@ -8,12 +8,18 @@ jest.mock("./SimpleCardFooterArrow", () => { }); }); +jest.mock("../VersionedLink", () => { + return jest.fn(({ url, component }) => { + return {component}; + }); +}); + describe("Display SimpleCardGrid", () => { interface testCard { title: string; description: string; buttonText: string; - relativeURL: string; + url: string; } interface testCase { @@ -26,19 +32,19 @@ describe("Display SimpleCardGrid", () => { title: "First Card", description: "Card 1", buttonText: "Learn more 1", - relativeURL: "./getting-started-1", + url: "/getting-started/getting-started-1", }, { title: "Second Card", description: "Card 2", buttonText: "Learn more 2", - relativeURL: "./getting-started-2", + url: "/getting-started/getting-started-2", }, { title: "Third Card", description: "Card 3", buttonText: "Learn more 3", - relativeURL: "./getting-started-3", + url: "/getting-started/getting-started-3", }, ]; @@ -74,7 +80,7 @@ describe("Display SimpleCardGrid", () => { expect(screen.getByText(tc.buttonText, { selector: "button" })).toBeInTheDocument(); expect( screen.getAllByRole("link").filter((value) => { - return value.getAttribute("href") == tc.relativeURL; + return value.getAttribute("href") == tc.url; }) ).not.toBeNull(); }); diff --git a/src/components/SimpleCardGrid/SimpleCardGrid.tsx b/src/components/SimpleCardGrid/SimpleCardGrid.tsx index 8c77cee138..d2c007e05f 100644 --- a/src/components/SimpleCardGrid/SimpleCardGrid.tsx +++ b/src/components/SimpleCardGrid/SimpleCardGrid.tsx @@ -1,6 +1,7 @@ import React from "react"; import styles from "./SimpleCardGrid.module.scss"; import SimpleCardFooterArrow from "./SimpleCardFooterArrow"; +import VersionedLink from "../VersionedLink"; interface SimpleCardProps { cards?: SimpleCard[]; @@ -12,10 +13,9 @@ interface SimpleCard { index?: number; description: string; buttonText: string; - relativeURL: string; + url: string; hideNumber?: boolean; } - interface SimpleCardHeader { index?: number; hideNumber?: boolean; @@ -31,8 +31,8 @@ export default function SimpleCardGrid({ cards = [], hideNumber = false }: Simpl index={index + 1} description={card.description} buttonText={card.buttonText} - relativeURL={card.relativeURL} key={`simpleCard-${index}`} + url={card.url} hideNumber={hideNumber} /> ))} @@ -40,22 +40,25 @@ export default function SimpleCardGrid({ cards = [], hideNumber = false }: Simpl ); } -function SimpleCard({ title, index, description, buttonText, relativeURL, hideNumber }: SimpleCard) { +function SimpleCard({ title, index, description, buttonText, url, hideNumber }: SimpleCard) { + const body = SimpleCardBody(title, description, buttonText, index, hideNumber); + return ; +} + +function SimpleCardBody(title: string, description: string, buttonText: string, index?: number, hideNumber?: boolean) { return ( - -
- -
-

{description}

-
-
- -
+
+ +
+

{description}

-
+
+ +
+
); } diff --git a/src/components/VersionedLink/VersionedLink.test.tsx b/src/components/VersionedLink/VersionedLink.test.tsx index 61b824cd5b..3fcd0500e9 100644 --- a/src/components/VersionedLink/VersionedLink.test.tsx +++ b/src/components/VersionedLink/VersionedLink.test.tsx @@ -20,6 +20,19 @@ describe("Versioned link", () => { expect(link).toBe(url); }); + it("latest version with component", () => { + prevVersionPath = ""; + const componentText = "Component text"; + const component =

{componentText}

; + const url = "/path/url"; + render(); + const componentRender = screen.getByText(componentText); + expect(componentRender).not.toBeNull(); + const link = screen.getByRole("link").getAttribute("href"); + expect(link).not.toBeNull(); + expect(link).toBe(url); + }); + it("previous version", () => { prevVersionPath = "/v4.3.1"; const text = "Test link"; @@ -30,6 +43,19 @@ describe("Versioned link", () => { expect(link).toBe(prevVersionPath.concat(url)); }); + it("previous version with component", () => { + prevVersionPath = "/v4.3.1"; + const componentText = "Component text"; + const component =

{componentText}

; + const url = "/path/url"; + render(); + const componentRender = screen.getByText(componentText); + expect(componentRender).not.toBeNull(); + const link = screen.getByRole("link").getAttribute("href"); + expect(link).not.toBeNull(); + expect(link).toBe(prevVersionPath.concat(url)); + }); + it("url with back dots", () => { prevVersionPath = ""; const text = "Test link"; diff --git a/src/components/VersionedLink/VersionedLink.tsx b/src/components/VersionedLink/VersionedLink.tsx index ee67c639ed..5f1235f364 100644 --- a/src/components/VersionedLink/VersionedLink.tsx +++ b/src/components/VersionedLink/VersionedLink.tsx @@ -2,7 +2,9 @@ import React from "react"; import GetVersionPath from "./CheckVersion"; interface ComponentProperties { - [key: string]: string; + text?: string; + url: string; + component?: React.ReactElement; } export default function VersionedLink(props: ComponentProperties) { @@ -17,10 +19,24 @@ export default function VersionedLink(props: ComponentProperties) { "Versioned links should not be used for external URLs. Please use the default markdown syntax instead." ); } + + // Versioning detected if (path != "") { const versionedURL = path.concat(props.url); + + // Component Mode detected + if (props.component != null) { + return {props.component}; + } + + // Text mode detected return {props.text}; } + // Component mode of versioned link detected without versioning + if (props.component != null) { + return {props.component}; + } + return {props.text}; } diff --git a/static/assets/docs/images/hide_copy_button.webp b/static/assets/docs/images/hide_copy_button.webp new file mode 100644 index 0000000000000000000000000000000000000000..eb7afe852eb7ef167239f96c418faa13acff77c0 GIT binary patch literal 4206 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 S6BS%zM{OEFc)11u0R9Ue*>F|> literal 0 HcmV?d00001 diff --git a/static/assets/docs/images/hide_copy_button_example.webp b/static/assets/docs/images/hide_copy_button_example.webp new file mode 100644 index 0000000000000000000000000000000000000000..5b9176cade7ab8c18430e47858eacc7f45df91da GIT binary patch literal 5912 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 literal 0 HcmV?d00001