Skip to content

Commit

Permalink
Improve version handling logic (#1192)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sporiff authored Nov 11, 2024
2 parents 663a88f + cc626c4 commit 7b1c3b8
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 105 deletions.
41 changes: 30 additions & 11 deletions src/components/Cards/CategoryCard.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ interface Props {
const { child } = Astro.props;
const childVersion = child?.version ?? "0";
const childCategory = child?.slug?.includes("/sdk") ? "sdk" : "api";
const categoryId = `category-${childCategory}-${childVersion}`;
const categoryClass = `category-${childCategory}-${childVersion}`;
---

<div
id={categoryId}
class={classNames(
"xs:w-full lg:w-[calc(33.3%-8px)] h-auto min-h-[144px] group",
{
hidden: !!child.version,
},
categoryClass,
)}
>
<a class="!no-underline !text-black" href={`/${child.slug}`}>
Expand All @@ -37,19 +37,38 @@ const categoryId = `category-${childCategory}-${childVersion}`;

<script>
import { $versions as $sdkVersions } from "@store/sdkVersionsStore";
import { $versions as $apiVersions } from "@store/apiVersionsStore";

document.addEventListener("DOMContentLoaded", () => {
const currentSdkVersion = $sdkVersions.get()?.currentVersion?.value || "0";
const currentApiVersion = $apiVersions.get()?.currentVersion?.value || "0";
const currentSdkVersion = $sdkVersions.get().currentVersion.value || "v5";
// Helper function to hide all versioned items initially
const hideAllVersionedItems = () => {
const versionedItems = document.querySelectorAll(
"[class*='category-sdk']",
);
versionedItems.forEach((item) => {
if (!item.classList.contains("hidden")) item.classList.add("hidden");
});
};

const categories = document.querySelectorAll(
`#category-sdk-${currentSdkVersion}, #category-api-${currentApiVersion}, #category-version-0`,
);
// Helper function to show items for the current versions
const showCurrentVersionItems = (sdkVersion: string) => {
hideAllVersionedItems();
// Select and show items for the current SDK versions
const versionedItems = document.querySelectorAll(
`.category-sdk-${sdkVersion}, .category-sdk-0`,
);
versionedItems.forEach((item) => {
item.classList.remove("hidden");
item.classList.add("block");
});
};

categories.forEach((item) => {
item.classList.remove("hidden");
item.classList.add("block");
// Subscribe to version changes in the Nanostores
$sdkVersions.subscribe((store) => {
const sdkVersion = store.currentVersion?.value;
if (sdkVersion) {
showCurrentVersionItems(sdkVersion);
}
});
});
</script>
61 changes: 39 additions & 22 deletions src/components/Layout/LeftSidebar/Sidebar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,18 @@ const sidebar = languageTree[lang as Languages];
---

<aside
id="sidebar-navigation"
class="h-screen xs:hidden xs:absolute xs:z-30 xs:w-full lg:max-w-[294px] lg:flex lg:sticky top-0 flex flex-col border-r-[1.5px] bg-white border-[#E0EAFF] sidebar-open:flex"
title="Site Navigation"
>
{/* Header with audience switch */}
<SidebarHeader
homeUrl={homeUrl}
lang={lang}
redirects={redirects}
versions={versions}
/>
{/* Search input */}
<SidebarSearch />
<NavigationTree sidebar={sidebar} currentSlug={currentSlug} />
{/* Language switcher */}
<div class="h-[63px] border-t-[1px] border-[#CDD0E0]">
<LanguageSwitch
lang={lang}
Expand All @@ -47,28 +45,51 @@ const sidebar = languageTree[lang as Languages];

<script>
import { $versions as $sdkVersions } from "@store/sdkVersionsStore";
import { $versions as $apiVersions } from "@store/apiVersionsStore";
import { toggleCollapse } from "./utils/toggleCollapse";

document.addEventListener("DOMContentLoaded", () => {
// versioning logic
const showItems = (items: NodeListOf<Element>) => {
items.forEach((item) => {
item.className = item.className.replace("hidden", "");
// Helper function to hide all versioned items initially
const hideAllVersionedItems = () => {
const versionedItems = document.querySelectorAll(
"[class*='item-version-sdk']",
);
versionedItems.forEach((item) => {
if (!item.classList.contains("hidden")) item.classList.add("hidden");
});
};

const currentSdkVersion = $sdkVersions.get()?.currentVersion;
const currentApiVersion = $apiVersions.get()?.currentVersion;
// need to unhide SDK/API items that match the current version, also need to unhide unversioned items
const sidebarItems = document.querySelectorAll(
`.item-version-sdk-${currentSdkVersion.value}, .item-version-api-${currentApiVersion.value}`,
);
// Helper function to show items for the current versions
const showCurrentVersionItems = (sdkVersion: string) => {
hideAllVersionedItems();
// Select and show items for the current SDK versions
const versionedItems = document.querySelectorAll(
`.item-version-sdk-${sdkVersion}`,
);
versionedItems.forEach((item) => {
item.classList.remove("hidden");
});
};

showItems(sidebarItems);
// Initial setup: Get current versions from stores and display relevant items
const setupSidebar = () => {
const currentSdkVersion =
$sdkVersions.get()?.currentVersion?.value || "v5";
showCurrentVersionItems(currentSdkVersion);
};

const items = document.querySelectorAll(".toggle-collapse");
// Run the initial setup on page load
setupSidebar();

// Subscribe to version changes in the Nanostore
$sdkVersions.subscribe((store) => {
const sdkVersion = store.currentVersion?.value;
if (sdkVersion) {
showCurrentVersionItems(sdkVersion);
}
});

// Expandable/collapsible item logic
const items = document.querySelectorAll(".toggle-collapse");
items.forEach((item) => {
item.addEventListener("click", () => {
const slug = item!
Expand All @@ -80,20 +101,16 @@ const sidebar = languageTree[lang as Languages];
});
});

// Scroll the active item into the center of the sidebar
// Scroll the active item into view
const activeItem = document.querySelector(".text-link-active");
const sidebar = document.getElementById("sidebar-navigation");

if (activeItem && sidebar) {
const { top: itemTop, height: itemHeight } =
activeItem.getBoundingClientRect();
const { top: sidebarTop, height: sidebarHeight } =
sidebar.getBoundingClientRect();

const offset = itemTop - sidebarTop - (sidebarHeight - itemHeight) / 2;
sidebar.scrollBy({
top: offset,
});
sidebar.scrollBy({ top: offset });
}
});
</script>
139 changes: 68 additions & 71 deletions src/components/Version/SdkVersionSwitch.astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ interface Props {
}
const { lang, currentPage } = Astro.props;
const t = useTranslations(lang as keyof Locales);
// Find the current page data and any redirects from the frontmatter
// Get current page data and redirects from frontmatter
const pageData = findEntryBySlug(currentPage);
const redirects = pageData?.redirects || {};
const defaultVersion =
Expand All @@ -25,7 +24,6 @@ const defaultVersion =
class="flex flex-col w-full min-h-90px justify-start gap-y-4 bg-slate-100 p-6 rounded-lg mb-14"
data-redirects={JSON.stringify(redirects)}
data-default-version={defaultVersion}
data-lang={lang}
>
<label for="combobox">{t("sdkversionswitch.label")}</label>
<div class="relative w-full">
Expand Down Expand Up @@ -58,83 +56,82 @@ const defaultVersion =
<script>
import { $versions, changeVersionValue } from "@store/sdkVersionsStore";

document.addEventListener("DOMContentLoaded", function () {
document.addEventListener("DOMContentLoaded", () => {
const versionSelect = document.getElementById(
"combobox",
) as HTMLSelectElement | null;
const comboboxHolder = document.getElementById("combobox-holder");
const defaultVersion =
comboboxHolder?.getAttribute("data-default-version") || "";

if (versionSelect && comboboxHolder) {
const redirectsAttribute = comboboxHolder.getAttribute("data-redirects");
const lang = comboboxHolder.getAttribute("data-lang");
let redirects = redirectsAttribute ? JSON.parse(redirectsAttribute) : {};
for (const key in redirects) {
if (redirects.hasOwnProperty(key)) {
// Check if the value starts with the required string
if (!redirects[key].startsWith(`/${lang}/`)) {
// Prepend the required string if it doesn't start with it
redirects[key] = redirects[key].replace("/en/", `/${lang}/`);
}
}
}

const urlParams = new URLSearchParams(window.location.search);
const urlVersion = urlParams.get("version");

// Wait for the store to be ready before displaying the select text
$versions.subscribe((store) => {
const currentVersion = store.currentVersion;

// Set the select input value from URL param, store, or default
if (urlVersion && versionSelect.options.namedItem(urlVersion)) {
versionSelect.value = urlVersion;
} else if (currentVersion) {
versionSelect.value = currentVersion.value;
} else {
versionSelect.value = defaultVersion;
}

// Show the select text once version is loaded
const redirects = comboboxHolder?.getAttribute("data-redirects");
const redirectsMap = redirects ? JSON.parse(redirects) : {};

// Utility functions
const isVersionedPath = (path: string) => /\/sdk\/.+\/v\d/.test(path);
const currentPath = window.location.pathname;
const urlParams = new URLSearchParams(window.location.search);
const urlVersionParam = urlParams.get("version");
const pathRegex = /^\/[a-z]{2}\/sdk\/?$/;

// 1. Initialize version select input from store and URL
$versions.subscribe((store) => {
const currentVersion = store.currentVersion.value;
if (versionSelect) {
versionSelect.value =
urlVersionParam || currentVersion || defaultVersion;
versionSelect.classList.remove("text-transparent");
}
});

// 2. Handle URL and version synchronization
const syncVersion = (targetVersion: string) => {
// If redirect for version exists, navigate to it
if (redirectsMap[targetVersion]) {
window.location.href = redirectsMap[targetVersion];
} else if (!pathRegex.test(currentPath)) {
// Otherwise, modify path to include the version in URL if needed
const updatedUrl = isVersionedPath(currentPath)
? currentPath.replace(/\/v\d/, `/${targetVersion}`)
: `${currentPath}/v${targetVersion}`;
window.location.href = updatedUrl;
}
};

// 3. Handle page load cases
if (
!urlVersionParam &&
isVersionedPath(currentPath) &&
!pathRegex.test(currentPath)
) {
// Case 1: Page is versioned, no ?version param
const pathVersionMatch = currentPath.match(/\/v(\d+)/);
const pathVersion = pathVersionMatch
? pathVersionMatch[1]
: defaultVersion;
changeVersionValue({
label: `v${pathVersion}`,
value: `v${pathVersion}`,
});

// Handle version change and redirect logic
versionSelect.addEventListener("change", function () {
const selectedVersion = versionSelect.value;
const selection = { label: selectedVersion, value: selectedVersion };
changeVersionValue(selection);
const currentUrl = window.location.href;

// Check if there's a redirect for the selected version
if (redirects[selectedVersion]) {
window.location.href = redirects[selectedVersion];
} else {
// Fallback logic for changing version in the URL
const defaultVersionReg = /\/(\w*)v\d/gi;
const versionReg = /\/sdk\/(\w*)(\/|$)/gi;

if (selectedVersion === defaultVersion) {
// Redirect to default version URL by removing version part
window.location.href = currentUrl.replace(defaultVersionReg, "$1");
} else {
// Redirect to the selected version
window.location.href = currentUrl.replace(
versionReg,
`/sdk/$1/${selectedVersion}/`,
);
}
}
});

// Check for version in URL query params
if (urlVersion && redirects[urlVersion]) {
changeVersionValue({ label: urlVersion, value: urlVersion });
window.location.href = redirects[urlVersion];
} else if (
!isVersionedPath(currentPath) &&
!urlVersionParam &&
!pathRegex.test(currentPath)
) {
// Case 2: Non-versioned page, no ?version param
changeVersionValue({ label: defaultVersion, value: defaultVersion });
} else if (urlVersionParam) {
// Case 3: ?version param present
const isParamVersion = urlVersionParam.match(/^v\d+$/);
if (isParamVersion) {
syncVersion(urlVersionParam);
}
} else {
console.warn("Version select or combobox holder element not found.");
}

// 4. Change event for version select dropdown
versionSelect?.addEventListener("change", (event) => {
const selectedVersion = (event.target as HTMLSelectElement).value;
changeVersionValue({ label: selectedVersion, value: selectedVersion });
syncVersion(selectedVersion);
});
});
</script>
2 changes: 1 addition & 1 deletion src/layouts/MainLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const t = useTranslations(currentLang as keyof Locales);
<LeftSidebar
homeUrl={homeUrl}
redirects={data.redirects}
lang={currentLang}
lang={currentLang || "en"}
currentSlug={currentSlug}
languageTree={languageTree}
versions={data.versions}
Expand Down

0 comments on commit 7b1c3b8

Please sign in to comment.