Skip to content

Commit

Permalink
feat(docs): finished adding dynamic pages and sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
aednikanov committed Sep 18, 2024
1 parent 61b9fde commit 6c7815f
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 17 deletions.
16 changes: 16 additions & 0 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Note: type annotations allow type checking and IDEs autocompletion

require("dotenv").config();
const { fetchAndGenerateSidebarItems } = require("./src/helpers/index.ts");
const capitalize = require("lodash.capitalize");
const { themes } = require("prism-react-renderer");
const codeTheme = themes.dracula;
const remarkCodesandbox = require("remark-codesandbox");
Expand Down Expand Up @@ -32,6 +34,7 @@ const config = {

customFields: {
LD_CLIENT_ID: process.env.LD_CLIENT_ID,
sidebarData: {},
},

trailingSlash: true,
Expand Down Expand Up @@ -122,6 +125,19 @@ const config = {
editUrl: "https://github.com/MetaMask/metamask-docs/edit/main/",
sidebarPath: require.resolve("./services-sidebar.js"),
breadcrumbs: false,
sidebarItemsGenerator: async function ({ defaultSidebarItemsGenerator, ...args }) {
config.customFields.sidebarData = args;
let sidebarItems = await defaultSidebarItemsGenerator(args);
const networkName = "linea";
const dynamicSidebarItems = await fetchAndGenerateSidebarItems(networkName);
const updatedItems = sidebarItems.map(item => {
if (item?.label === capitalize(networkName) && item?.items) {
item.items = [...item.items, ...dynamicSidebarItems]
}
return item;
})
return [...updatedItems];
},
},
],
[
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"dotenv": "^16.4.5",
"js-cookie": "^3.0.5",
"launchdarkly-js-client-sdk": "^3.3.0",
"lodash.capitalize": "^4.2.1",
"lodash.debounce": "^4.0.8",
"lodash.isobject": "^3.0.2",
"node-polyfill-webpack-plugin": "^2.0.1",
Expand Down
62 changes: 46 additions & 16 deletions src/components/ParserOpenRPC/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import clsx from "clsx";
import { useColorMode } from "@docusaurus/theme-common";
import { trackClickForSegment, trackInputChangeForSegment } from "@site/src/lib/segmentAnalytics";
import { MetamaskProviderContext } from "@site/src/theme/Root";
import { useLocation } from "@docusaurus/router";

interface ParserProps {
network: NETWORK_NAMES;
Expand Down Expand Up @@ -40,6 +41,16 @@ export default function ParserOpenRPC({ network, method, extraContent }: ParserP
const [drawerLabel, setDrawerLabel] = useState(null);
const [isComplexTypeView, setIsComplexTypeView] = useState(false);
const { colorMode } = useColorMode();
const location = useLocation();
const isWalletReferencePage = location.pathname.includes("/wallet/reference");
const trackAnalyticsForRequest = (response) => {
trackClickForSegment({
eventName: "Request Sent",
clickType: "Request Sent",
userExperience: "B",
...(response?.code && { responseStatus: response.code }),
});
}
const openModal = () => {
setModalOpen(true);
trackClickForSegment({
Expand Down Expand Up @@ -132,21 +143,40 @@ export default function ParserOpenRPC({ network, method, extraContent }: ParserP
};

const onSubmitRequestHandle = async () => {
if (!metaMaskProvider) return
try {
const response = await metaMaskProvider?.request({
method: method,
params: paramsData
})
setReqResult(response);
trackClickForSegment({
eventName: "Request Sent",
clickType: "Request Sent",
userExperience: "B",
...(response?.code && { responseStatus: response.code }),
});
} catch (e) {
setReqResult(e);
if (isMetamaskNetwork) {
if (!metaMaskProvider) return
try {
const response = await metaMaskProvider?.request({
method: method,
params: paramsData
})
setReqResult(response);
trackAnalyticsForRequest(response);
} catch (e) {
setReqResult(e);
}
} else {
const NETWORK_URL = "https://linea-mainnet.infura.io";
const API_KEY = "366ba274ec6f4cf1810de6003cbb9a5e";
const URL = `${NETWORK_URL}/v3/${API_KEY}`;
let params = {
method: "POST",
"Content-Type": "application/json",
body: JSON.stringify({
jsonrpc: "2.0",
method,
params: paramsData,
id: 1,
}),
};
const res = await fetch(URL, params);
if (res.ok) {
const response = await res.json();
setReqResult(response.result);
trackAnalyticsForRequest(response.result);
} else {
console.error("error");
}
}
};

Expand Down Expand Up @@ -228,7 +258,7 @@ export default function ParserOpenRPC({ network, method, extraContent }: ParserP
</div>
<div className={global.colRight}>
<div className={global.stickyCol}>
{!metaMaskAccount && <AuthBox handleConnect={metaMaskConnectHandler} />}
{isWalletReferencePage && !metaMaskAccount && <AuthBox handleConnect={metaMaskConnectHandler} />}
<RequestBox
isMetamaskInstalled={!!metaMaskAccount}
method={method}
Expand Down
25 changes: 25 additions & 0 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as capitalize from "lodash.capitalize"

export const fetchAndGenerateSidebarItems = async (networkName) => {
try {
const response = await fetch(`https://sot-network-methods.vercel.app/specs/${networkName}`);
const data = await response.json();
const dynamicItems = data.methods.map((method) => ({
type: "link",
label: method.name,
href: `/services/reference/linea/json-rpc-methods-new/${method.name}`,
})).sort((a, b) => a.label.localeCompare(b.label));
return [
{
type: "category",
label: "JSON-RPC Methods NEW",
collapsed: true,
collapsible: true,
items: dynamicItems,
},
];
} catch (error) {
console.error("Error fetching methods:", error);
return [];
}
}
125 changes: 125 additions & 0 deletions src/pages/CustomPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import Layout from "@theme/Layout";
import { NETWORK_NAMES } from "@site/src/plugins/plugin-json-rpc";
import ParserOpenRPC from "@site/src/components/ParserOpenRPC";
import React, { useEffect, useState } from "react";
import DocSidebar from '@theme/DocSidebar';
import styles from "@site/src/theme/Layout/styles.module.css"
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { fetchAndGenerateSidebarItems } from "@site/src/helpers";
import * as capitalize from "lodash.capitalize"

function generateSidebarItems(docs) {
const categories = {};

docs.forEach((doc) => {
if (doc.id === 'index') {
categories['Introduction'] = {
type: 'link',
href: '/services',
label: capitalize(doc.frontMatter?.sidebar_label || doc.title),
};
return;
}

const pathParts = doc.sourceDirName.split('/');
let currentCategory = categories;
let isIndexPage = doc.id.endsWith('/index');

pathParts.forEach((part, index) => {
if (!currentCategory[part]) {
if (isIndexPage && index === pathParts.length - 2) {
currentCategory[part] = {
type: 'category',
label: capitalize(doc.frontMatter?.sidebar_label || doc.frontMatter?.title || part),
collapsed: true,
collapsible: true,
link: {
type: 'generated-index',
slug: pathParts.slice(0, index + 1).join('/')
},
items: []
};
} else {
currentCategory[part] = {
type: 'category',
label: capitalize(part),
collapsed: true,
collapsible: true,
items: []
};
}
}

if (index === pathParts.length - 1 && !isIndexPage) {
currentCategory[part].items.push({
type: 'link',
label: capitalize(doc.frontMatter?.title || doc.title),
href: `/services/${doc.id.replace(/\/index$/, '')}`,
sidebar_position: doc.frontMatter?.sidebar_position || Number.MAX_SAFE_INTEGER
});
}
currentCategory = currentCategory[part].items;
});
});

const convertToArray = (categoryObj) => {
return Object.values(categoryObj).map((category) => {
if (category.items && typeof category.items === 'object') {
category.items = convertToArray(category.items);
if (category.items.every(item => item.sidebar_position !== undefined)) {
category.items.sort((a, b) => (a.sidebar_position || Number.MAX_SAFE_INTEGER) - (b.sidebar_position || Number.MAX_SAFE_INTEGER));
}
}
return category;
});
};
return convertToArray(categories);
}

const sidebar_wrapper_classes = "theme-doc-sidebar-container docSidebarContainer_node_modules-@docusaurus-theme-classic-lib-theme-DocRoot-Layout-Sidebar-styles-module"

const CustomPage = (props) => {
const customData = props.route.customData;
const { siteConfig } = useDocusaurusContext();
const [formattedData, setFormattedData] = useState([]);
const networkName = "linea";

useEffect(() => {
fetchAndGenerateSidebarItems(networkName).then(generatedItems => {
setFormattedData(generateSidebarItems(siteConfig.customFields.sidebarData.docs).map(item => {
if (item?.label === "Reference" && item?.items) {
return {
...item,
items: item.items.map(referenceItem => {
if (referenceItem?.label === capitalize(networkName) && referenceItem?.items) {
return { ...referenceItem, items: [...referenceItem.items, ...generatedItems] };
}
return referenceItem;
})
}
}
return item;
}));
});
}, []);

return formattedData ? (
<Layout>
<div className={styles.pageWrapper}>
<aside className={sidebar_wrapper_classes}>
<DocSidebar sidebar={formattedData} path="" onCollapse={() => {}} isHidden={false} />
</aside>
<div className={styles.mainContainer}>
<div className={styles.contentWrapper}>
<ParserOpenRPC
network={NETWORK_NAMES.linea}
method={customData.name}
/>
</div>
</div>
</div>
</Layout>
) : null;
};

export default CustomPage;
30 changes: 29 additions & 1 deletion src/plugins/plugin-json-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,42 @@ const requests = [
},
];

function generateMethodMDX(page) {
return `---
title: '${page.name}'
---
# ${page.name}
`;
}

export default function useNetworksMethodPlugin() {
return {
name: "plugin-json-rpc",
async contentLoaded({ actions }) {
const { setGlobalData } = actions;
const { setGlobalData, createData, addRoute } = actions;
await fetchMultipleData(requests)
.then((responseArray) => {
const networkName = "linea";
setGlobalData({ netData: responseArray });
return Promise.all(responseArray[responseArray.findIndex(item => item.name === networkName) || 0].data.methods.map(async (page) => {

const methodMDXContent = generateMethodMDX(page);

const filePath = await createData(
`services/reference/linea/json-rpc-methods-new/${page.name}.mdx`,
methodMDXContent
);

return addRoute({
path: `/services/reference/linea/json-rpc-methods-new/${page.name}`,
component: require.resolve("../pages/CustomPage/index.tsx"),
exact: true,
modules: {
methodFile: filePath,
},
customData: { ...page }
});
}));
})
.catch(() => {
setGlobalData({ netData: [] });
Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12493,6 +12493,13 @@ __metadata:
languageName: node
linkType: hard

"lodash.capitalize@npm:^4.2.1":
version: 4.2.1
resolution: "lodash.capitalize@npm:4.2.1"
checksum: d9195f31d48c105206f1099946d8bbc8ab71435bc1c8708296992a31a992bb901baf120fdcadd773098ac96e62a79e6b023ee7d26a2deb0d6c6aada930e6ad0a
languageName: node
linkType: hard

"lodash.debounce@npm:^4.0.8":
version: 4.0.8
resolution: "lodash.debounce@npm:4.0.8"
Expand Down Expand Up @@ -13380,6 +13387,7 @@ __metadata:
eslint-plugin-react: ^7.34.2
js-cookie: ^3.0.5
launchdarkly-js-client-sdk: ^3.3.0
lodash.capitalize: ^4.2.1
lodash.debounce: ^4.0.8
lodash.isobject: ^3.0.2
node-polyfill-webpack-plugin: ^2.0.1
Expand Down

0 comments on commit 6c7815f

Please sign in to comment.