diff --git a/www/apps/api-reference/components/Tags/Paths/index.tsx b/www/apps/api-reference/components/Tags/Paths/index.tsx index 27bdc14531..45b0df6001 100644 --- a/www/apps/api-reference/components/Tags/Paths/index.tsx +++ b/www/apps/api-reference/components/Tags/Paths/index.tsx @@ -2,7 +2,7 @@ import type { OpenAPI } from "types" 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 type { TagOperationProps } from "../Operation" import clsx from "clsx" @@ -10,6 +10,7 @@ import getTagChildSidebarItems from "@/utils/get-tag-child-sidebar-items" import { useLoading } from "@/providers/loading" import DividedLoading from "@/components/DividedLoading" import { Sidebar } from "types" +import { compareOperations } from "../../../utils/sort-operations-utils" const TagOperation = dynamic( async () => import("../Operation") @@ -57,26 +58,53 @@ const TagPaths = ({ tag, className, paths }: TagPathsProps) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [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 (
{loading && } - {Object.entries(paths).map(([endpointPath, operations], pathIndex) => ( - - {Object.entries(operations).map( - ([method, operation], operationIndex) => ( - - ) - )} - - ))} + {sortedOperations.map( + ({ endpointPath, method, operation }, operationIndex) => ( + + + + ) + )}
) diff --git a/www/apps/api-reference/providers/base-specs.tsx b/www/apps/api-reference/providers/base-specs.tsx index dc292f2c9e..65ba96e887 100644 --- a/www/apps/api-reference/providers/base-specs.tsx +++ b/www/apps/api-reference/providers/base-specs.tsx @@ -2,10 +2,9 @@ import { OpenAPI } from "types" import { ReactNode, createContext, useContext, useEffect, useMemo } from "react" -import { Sidebar } from "types" import getTagChildSidebarItems from "../utils/get-tag-child-sidebar-items" import { useRouter } from "next/navigation" -import { UpdateActionType, UpdateSidebarItemTypes, useSidebar } from "docs-ui" +import { UpdateActionType, useSidebar } from "docs-ui" import { getSectionId } from "docs-utils" type BaseSpecsContextType = { diff --git a/www/apps/api-reference/types/global.d.ts b/www/apps/api-reference/types/global.d.ts index e3c089e540..08f4da03f8 100644 --- a/www/apps/api-reference/types/global.d.ts +++ b/www/apps/api-reference/types/global.d.ts @@ -1,6 +1,12 @@ +import { Sidebar } from "types" + declare global { interface Window { // eslint-disable-next-line @typescript-eslint/no-explicit-any analytics?: any } } + +export type SidebarItem = Sidebar.SidebarItem & { + http_method?: string +} diff --git a/www/apps/api-reference/utils/get-tag-child-sidebar-items.tsx b/www/apps/api-reference/utils/get-tag-child-sidebar-items.tsx index a73db267de..5499096f70 100644 --- a/www/apps/api-reference/utils/get-tag-child-sidebar-items.tsx +++ b/www/apps/api-reference/utils/get-tag-child-sidebar-items.tsx @@ -1,9 +1,9 @@ -import type { OpenAPI } from "types" +import type { OpenAPI, Sidebar } from "types" import dynamic from "next/dynamic" import type { MethodLabelProps } from "@/components/MethodLabel" -import { Sidebar } from "types" import { getSectionId } from "docs-utils" - +import { SidebarItem } from "../types/global" +import { compareOperations } from "./sort-operations-utils" const MethodLabel = dynamic( async () => import("../components/MethodLabel") ) as React.FC @@ -11,7 +11,7 @@ const MethodLabel = dynamic( export default function getTagChildSidebarItems( paths: OpenAPI.PathsObject ): Sidebar.SidebarItem[] { - const items: Sidebar.SidebarItem[] = [] + const items: SidebarItem[] = [] Object.entries(paths).forEach(([, operations]) => { Object.entries(operations).map(([method, operation]) => { const definedOperation = operation as OpenAPI.Operation @@ -30,9 +30,19 @@ export default function getTagChildSidebarItems( ), loaded: true, + http_method: definedMethod, }) }) }) 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) } diff --git a/www/apps/api-reference/utils/sort-operations-utils.ts b/www/apps/api-reference/utils/sort-operations-utils.ts new file mode 100644 index 0000000000..28b2e667a8 --- /dev/null +++ b/www/apps/api-reference/utils/sort-operations-utils.ts @@ -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) +}