docs: sort API reference sidebar items and sections (#12032)
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import type { OpenAPI } from "types"
|
import type { OpenAPI } from "types"
|
||||||
import { findSidebarItem, useSidebar } from "docs-ui"
|
import { findSidebarItem, useSidebar } from "docs-ui"
|
||||||
import { Fragment, Suspense, useEffect } from "react"
|
import { Fragment, Suspense, useEffect, useMemo } from "react"
|
||||||
import dynamic from "next/dynamic"
|
import dynamic from "next/dynamic"
|
||||||
import type { TagOperationProps } from "../Operation"
|
import type { TagOperationProps } from "../Operation"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
@@ -10,6 +10,7 @@ import getTagChildSidebarItems from "@/utils/get-tag-child-sidebar-items"
|
|||||||
import { useLoading } from "@/providers/loading"
|
import { useLoading } from "@/providers/loading"
|
||||||
import DividedLoading from "@/components/DividedLoading"
|
import DividedLoading from "@/components/DividedLoading"
|
||||||
import { Sidebar } from "types"
|
import { Sidebar } from "types"
|
||||||
|
import { compareOperations } from "../../../utils/sort-operations-utils"
|
||||||
|
|
||||||
const TagOperation = dynamic<TagOperationProps>(
|
const TagOperation = dynamic<TagOperationProps>(
|
||||||
async () => import("../Operation")
|
async () => import("../Operation")
|
||||||
@@ -57,26 +58,53 @@ const TagPaths = ({ tag, className, paths }: TagPathsProps) => {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [paths, shownSidebar?.sidebar_id])
|
}, [paths, shownSidebar?.sidebar_id])
|
||||||
|
|
||||||
|
const sortedOperations = useMemo(() => {
|
||||||
|
const sortedOperations: {
|
||||||
|
endpointPath: string
|
||||||
|
method: string
|
||||||
|
operation: OpenAPI.Operation
|
||||||
|
}[] = []
|
||||||
|
|
||||||
|
Object.entries(paths).forEach(([endpointPath, operations]) => {
|
||||||
|
Object.entries(operations).forEach(([method, operation]) => {
|
||||||
|
sortedOperations.push({
|
||||||
|
endpointPath,
|
||||||
|
method,
|
||||||
|
operation: operation as OpenAPI.Operation,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
sortedOperations.sort((a, b) => {
|
||||||
|
return compareOperations({
|
||||||
|
httpMethodA: a.method,
|
||||||
|
httpMethodB: b.method,
|
||||||
|
summaryA: a.operation.summary,
|
||||||
|
summaryB: b.operation.summary,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return sortedOperations
|
||||||
|
}, [paths])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<div className={clsx("relative", className)}>
|
<div className={clsx("relative", className)}>
|
||||||
{loading && <DividedLoading className="mt-7" />}
|
{loading && <DividedLoading className="mt-7" />}
|
||||||
{Object.entries(paths).map(([endpointPath, operations], pathIndex) => (
|
{sortedOperations.map(
|
||||||
<Fragment key={pathIndex}>
|
({ endpointPath, method, operation }, operationIndex) => (
|
||||||
{Object.entries(operations).map(
|
<Fragment key={operationIndex}>
|
||||||
([method, operation], operationIndex) => (
|
<TagOperation
|
||||||
<TagOperation
|
method={method}
|
||||||
method={method}
|
operation={operation}
|
||||||
operation={operation as OpenAPI.Operation}
|
tag={tag}
|
||||||
tag={tag}
|
key={`${operationIndex}`}
|
||||||
key={`${pathIndex}-${operationIndex}`}
|
endpointPath={endpointPath}
|
||||||
endpointPath={endpointPath}
|
className={clsx("pt-7")}
|
||||||
className={clsx("pt-7")}
|
/>
|
||||||
/>
|
</Fragment>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
import { OpenAPI } from "types"
|
import { OpenAPI } from "types"
|
||||||
import { ReactNode, createContext, useContext, useEffect, useMemo } from "react"
|
import { ReactNode, createContext, useContext, useEffect, useMemo } from "react"
|
||||||
import { Sidebar } from "types"
|
|
||||||
import getTagChildSidebarItems from "../utils/get-tag-child-sidebar-items"
|
import getTagChildSidebarItems from "../utils/get-tag-child-sidebar-items"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import { UpdateActionType, UpdateSidebarItemTypes, useSidebar } from "docs-ui"
|
import { UpdateActionType, useSidebar } from "docs-ui"
|
||||||
import { getSectionId } from "docs-utils"
|
import { getSectionId } from "docs-utils"
|
||||||
|
|
||||||
type BaseSpecsContextType = {
|
type BaseSpecsContextType = {
|
||||||
|
|||||||
6
www/apps/api-reference/types/global.d.ts
vendored
6
www/apps/api-reference/types/global.d.ts
vendored
@@ -1,6 +1,12 @@
|
|||||||
|
import { Sidebar } from "types"
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
analytics?: any
|
analytics?: any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SidebarItem = Sidebar.SidebarItem & {
|
||||||
|
http_method?: string
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { OpenAPI } from "types"
|
import type { OpenAPI, Sidebar } from "types"
|
||||||
import dynamic from "next/dynamic"
|
import dynamic from "next/dynamic"
|
||||||
import type { MethodLabelProps } from "@/components/MethodLabel"
|
import type { MethodLabelProps } from "@/components/MethodLabel"
|
||||||
import { Sidebar } from "types"
|
|
||||||
import { getSectionId } from "docs-utils"
|
import { getSectionId } from "docs-utils"
|
||||||
|
import { SidebarItem } from "../types/global"
|
||||||
|
import { compareOperations } from "./sort-operations-utils"
|
||||||
const MethodLabel = dynamic<MethodLabelProps>(
|
const MethodLabel = dynamic<MethodLabelProps>(
|
||||||
async () => import("../components/MethodLabel")
|
async () => import("../components/MethodLabel")
|
||||||
) as React.FC<MethodLabelProps>
|
) as React.FC<MethodLabelProps>
|
||||||
@@ -11,7 +11,7 @@ const MethodLabel = dynamic<MethodLabelProps>(
|
|||||||
export default function getTagChildSidebarItems(
|
export default function getTagChildSidebarItems(
|
||||||
paths: OpenAPI.PathsObject
|
paths: OpenAPI.PathsObject
|
||||||
): Sidebar.SidebarItem[] {
|
): Sidebar.SidebarItem[] {
|
||||||
const items: Sidebar.SidebarItem[] = []
|
const items: SidebarItem[] = []
|
||||||
Object.entries(paths).forEach(([, operations]) => {
|
Object.entries(paths).forEach(([, operations]) => {
|
||||||
Object.entries(operations).map(([method, operation]) => {
|
Object.entries(operations).map(([method, operation]) => {
|
||||||
const definedOperation = operation as OpenAPI.Operation
|
const definedOperation = operation as OpenAPI.Operation
|
||||||
@@ -30,9 +30,19 @@ export default function getTagChildSidebarItems(
|
|||||||
<MethodLabel method={definedMethod} className="h-fit" />
|
<MethodLabel method={definedMethod} className="h-fit" />
|
||||||
),
|
),
|
||||||
loaded: true,
|
loaded: true,
|
||||||
|
http_method: definedMethod,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
.sort((a, b) => {
|
||||||
|
return compareOperations({
|
||||||
|
httpMethodA: a.http_method || "",
|
||||||
|
httpMethodB: b.http_method || "",
|
||||||
|
summaryA: (a as Sidebar.SidebarItemLink).title,
|
||||||
|
summaryB: (b as Sidebar.SidebarItemLink).title,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(({ http_method, ...rest }) => rest)
|
||||||
}
|
}
|
||||||
|
|||||||
33
www/apps/api-reference/utils/sort-operations-utils.ts
Normal file
33
www/apps/api-reference/utils/sort-operations-utils.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
export const getMethodOrder = (method: string) => {
|
||||||
|
switch (method) {
|
||||||
|
case "get":
|
||||||
|
return 1
|
||||||
|
case "post":
|
||||||
|
return 2
|
||||||
|
case "delete":
|
||||||
|
return 3
|
||||||
|
default:
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const compareOperations = ({
|
||||||
|
httpMethodA,
|
||||||
|
httpMethodB,
|
||||||
|
summaryA,
|
||||||
|
summaryB,
|
||||||
|
}: {
|
||||||
|
httpMethodA: string
|
||||||
|
httpMethodB: string
|
||||||
|
summaryA: string
|
||||||
|
summaryB: string
|
||||||
|
}) => {
|
||||||
|
const aOrder = getMethodOrder(httpMethodA)
|
||||||
|
const bOrder = getMethodOrder(httpMethodB)
|
||||||
|
|
||||||
|
if (aOrder !== bOrder) {
|
||||||
|
return aOrder - bOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
return summaryA.localeCompare(summaryB)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user