@digi-frontend/dgate-api-documentation 1.0.53 → 1.0.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/index3.js +1 -1
- package/dist/_virtual/index4.js +1 -1
- package/dist/_virtual/index5.js +1 -1
- package/dist/node_modules/toposort/index.js +1 -1
- package/dist/node_modules/yup/index.esm.js +1 -1
- package/dist/src/components/MethodAccordion/MethodAccordion.js +1 -1
- package/dist/src/components/MethodAccordion/MethodAccordion.js.map +1 -1
- package/dist/src/helpers/docs.helper.js.map +1 -1
- package/dist/src/layout/docsComponents/DocsContent/DocsContent.js.map +1 -1
- package/dist/src/layout/docsComponents/DocsContent/EndpointPage/index.js.map +1 -1
- package/dist/src/layout/docsComponents/DocsContent/TagPage/index.js +1 -1
- package/dist/src/layout/docsComponents/DocsContent/TagPage/index.js.map +1 -1
- package/dist/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.js +1 -1
- package/dist/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.js.map +1 -1
- package/dist/src/layout/docsLayout.js +1 -1
- package/dist/src/layout/docsLayout.js.map +1 -1
- package/dist/styles.css +482 -482
- package/dist/types/layout/docsComponents/DocsContent/DocsContent.d.ts +5 -0
- package/dist/types/layout/docsComponents/DocsContent/EndpointPage/index.d.ts +2 -1
- package/dist/types/layout/docsComponents/DocsContent/TagPage/index.d.ts +6 -5
- package/dist/types/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.d.ts +4 -2
- package/dist/types/layout/docsLayout.d.ts +4 -3
- package/package.json +3 -1
- package/rollup.config.js +2 -2
- package/src/components/MethodAccordion/MethodAccordion.tsx +5 -3
- package/src/helpers/docs.helper.ts +1 -0
- package/src/layout/docsComponents/DocsContent/DocsContent.tsx +6 -4
- package/src/layout/docsComponents/DocsContent/EndpointPage/index.tsx +13 -11
- package/src/layout/docsComponents/DocsContent/TagPage/index.tsx +58 -4
- package/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.tsx +11 -33
- package/src/layout/docsLayout.tsx +99 -21
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import './style.scss';
|
|
2
3
|
import { EndpointData, OverviewData } from 'src/layout/docsLayout';
|
|
3
4
|
declare const DocsContent: ({ data, activeType, setActiveItemData, setActiveType, setExpandedSections, }: {
|
|
4
5
|
data: OverviewData | EndpointData;
|
|
5
6
|
activeType: "OVERVIEW" | "ENDPOINT";
|
|
7
|
+
setActiveItemData: React.Dispatch<React.SetStateAction<OverviewData | EndpointData>>;
|
|
8
|
+
setActiveType: React.Dispatch<React.SetStateAction<"OVERVIEW" | "ENDPOINT">>;
|
|
9
|
+
setExpandedSections: React.Dispatch<React.SetStateAction<Record<string, boolean>>>;
|
|
10
|
+
toggleSection: (apiId: string, sectionId: string, resetOthers?: boolean, key?: string[]) => void;
|
|
6
11
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
7
12
|
export default DocsContent;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import './style.scss';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { EndpointData, OverviewData } from 'src/layout/docsLayout';
|
|
3
|
+
export declare const TagPage: ({ data, setActiveItemData, setActiveType, setExpandedSections, }: {
|
|
4
|
+
data: OverviewData;
|
|
5
|
+
setActiveItemData: React.Dispatch<React.SetStateAction<OverviewData | EndpointData>>;
|
|
6
|
+
setActiveType: React.Dispatch<React.SetStateAction<"OVERVIEW" | "ENDPOINT">>;
|
|
7
|
+
setExpandedSections: React.Dispatch<React.SetStateAction<Record<string, boolean>>>;
|
|
7
8
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import './style.scss';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { EndpointData, OverviewData } from 'src/layout/docsLayout';
|
|
4
|
-
declare const DocsSideMenuTree: ({ apis, setActiveItemData, activeItemData, activeType, expandedSections, setExpandedSections, isFirstApiExpanded, setIsFirstApiExpanded, setActiveType, }: {
|
|
4
|
+
declare const DocsSideMenuTree: ({ apis, setActiveItemData, activeItemData, activeType, expandedSections, setExpandedSections, isFirstApiExpanded, setIsFirstApiExpanded, setActiveType, toggleSection, canSelectFirstApi, }: {
|
|
5
5
|
apis: OverviewData[];
|
|
6
6
|
setActiveItemData: React.Dispatch<React.SetStateAction<OverviewData | EndpointData>>;
|
|
7
7
|
activeItemData: OverviewData | EndpointData;
|
|
8
8
|
expandedSections: Record<string, boolean>;
|
|
9
|
-
setExpandedSections:
|
|
9
|
+
setExpandedSections: (newSections: Record<string, boolean>) => void;
|
|
10
10
|
isFirstApiExpanded: boolean;
|
|
11
11
|
setIsFirstApiExpanded: React.Dispatch<React.SetStateAction<boolean>>;
|
|
12
12
|
setActiveType: React.Dispatch<React.SetStateAction<"OVERVIEW" | "ENDPOINT">>;
|
|
13
13
|
activeType: "OVERVIEW" | "ENDPOINT";
|
|
14
|
+
toggleSection: (apiId: string, sectionId: string, resetOthers?: boolean, key?: string[]) => void;
|
|
15
|
+
canSelectFirstApi?: boolean;
|
|
14
16
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
15
17
|
export default DocsSideMenuTree;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { JSX } from 'react';
|
|
1
|
+
import React, { JSX } from 'react';
|
|
2
2
|
import { HTTPMethod, OpenAPIFile, Parameter, RequestBody, Responses } from '@entities/openApi';
|
|
3
3
|
import { ApiSpecModel } from '@entities/index';
|
|
4
4
|
interface ILayoutProps {
|
|
5
5
|
apis?: ApiSpecModel[];
|
|
6
|
+
activeApiId?: string;
|
|
6
7
|
}
|
|
7
8
|
export interface TagData {
|
|
8
9
|
id: string;
|
|
@@ -30,5 +31,5 @@ export interface OverviewData extends Omit<ApiSpecModel, 'metaData'> {
|
|
|
30
31
|
tags: Record<string, TagData[]>;
|
|
31
32
|
servers: OpenAPIFile['servers'];
|
|
32
33
|
}
|
|
33
|
-
declare const
|
|
34
|
-
export default
|
|
34
|
+
declare const _default: React.MemoExoticComponent<({ apis, activeApiId }: ILayoutProps) => JSX.Element>;
|
|
35
|
+
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digi-frontend/dgate-api-documentation",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.55",
|
|
4
4
|
"main": "dist/src/index.js",
|
|
5
5
|
"module": "dist/src/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"description": "",
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"digitinary-ui": "1.0.166",
|
|
20
|
+
"fast-json-stable-stringify": "^2.1.0",
|
|
20
21
|
"formik": "^2.4.6",
|
|
21
22
|
"html-react-parser": "^5.2.2",
|
|
22
23
|
"js-yaml": "^4.1.0",
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"@rollup/plugin-commonjs": "^28.0.2",
|
|
33
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
32
34
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
33
35
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
34
36
|
"@rollup/plugin-url": "^8.0.2",
|
package/rollup.config.js
CHANGED
|
@@ -5,7 +5,7 @@ import postcss from 'rollup-plugin-postcss'
|
|
|
5
5
|
import { terser } from 'rollup-plugin-terser'
|
|
6
6
|
import url from '@rollup/plugin-url'
|
|
7
7
|
import sass from 'rollup-plugin-sass'
|
|
8
|
-
import json from '@rollup/plugin-json'
|
|
8
|
+
import json from '@rollup/plugin-json'
|
|
9
9
|
|
|
10
10
|
export default {
|
|
11
11
|
input: 'src/index.ts',
|
|
@@ -31,7 +31,7 @@ export default {
|
|
|
31
31
|
sass({
|
|
32
32
|
output: 'dist/styles.css',
|
|
33
33
|
}),
|
|
34
|
-
json()
|
|
34
|
+
json(),
|
|
35
35
|
],
|
|
36
36
|
external: ['react', 'react-dom'],
|
|
37
37
|
}
|
|
@@ -690,8 +690,10 @@ const MethodsAccordion = ({
|
|
|
690
690
|
headers: {},
|
|
691
691
|
})
|
|
692
692
|
|
|
693
|
-
setFieldValue
|
|
694
|
-
|
|
693
|
+
if (setFieldValue) {
|
|
694
|
+
setFieldValue('responses', clonedResponses)
|
|
695
|
+
responseIndex = 0
|
|
696
|
+
}
|
|
695
697
|
}
|
|
696
698
|
setCurrentResponseIndex(responseIndex)
|
|
697
699
|
indexRef.current = responseIndex
|
|
@@ -699,7 +701,7 @@ const MethodsAccordion = ({
|
|
|
699
701
|
generateResponseTableData(method.responses[responseIndex].headers, responseIndex)
|
|
700
702
|
)
|
|
701
703
|
}
|
|
702
|
-
}, [selectedStatusCode, method.responses])
|
|
704
|
+
}, [selectedStatusCode, method.responses, setFieldValue])
|
|
703
705
|
|
|
704
706
|
useEffect(() => {
|
|
705
707
|
if (indexRef.current && indexRef.current > -1) {
|
|
@@ -8,6 +8,7 @@ export const transformOpenApiToDocs = (api: ApiSpecModel): OverviewData => {
|
|
|
8
8
|
typeof api.metaData.openApiJson === 'string'
|
|
9
9
|
? JSON.parse(api.metaData.openApiJson)
|
|
10
10
|
: api.metaData.openApiJson
|
|
11
|
+
|
|
11
12
|
const groupedPathsByTags: Record<string, TagData[]> = { default: [] }
|
|
12
13
|
const validTags = new Set(parsedOpenApi.tags.map(({ name }) => name))
|
|
13
14
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import './style.scss'
|
|
3
|
-
import SVGLoader from '../../../components/SVGLoader/SVGLoader'
|
|
4
|
-
import { CopySticker } from '../../../assets/icons/index'
|
|
5
3
|
import { TagPage } from './TagPage'
|
|
6
4
|
import { EndpointPage } from './EndpointPage'
|
|
7
5
|
import { EndpointData, OverviewData } from 'src/layout/docsLayout'
|
|
@@ -15,18 +13,22 @@ const DocsContent = ({
|
|
|
15
13
|
}: {
|
|
16
14
|
data: OverviewData | EndpointData
|
|
17
15
|
activeType: 'OVERVIEW' | 'ENDPOINT'
|
|
16
|
+
setActiveItemData: React.Dispatch<React.SetStateAction<OverviewData | EndpointData>>
|
|
17
|
+
setActiveType: React.Dispatch<React.SetStateAction<'OVERVIEW' | 'ENDPOINT'>>
|
|
18
|
+
setExpandedSections: React.Dispatch<React.SetStateAction<Record<string, boolean>>>
|
|
19
|
+
toggleSection: (apiId: string, sectionId: string, resetOthers?: boolean, key?: string[]) => void
|
|
18
20
|
}) => {
|
|
19
21
|
return (
|
|
20
22
|
<main>
|
|
21
23
|
{activeType === 'OVERVIEW' ? (
|
|
22
24
|
<TagPage
|
|
23
|
-
data={data}
|
|
25
|
+
data={data as OverviewData}
|
|
24
26
|
setActiveItemData={setActiveItemData}
|
|
25
27
|
setActiveType={setActiveType}
|
|
26
28
|
setExpandedSections={setExpandedSections}
|
|
27
29
|
/>
|
|
28
30
|
) : (
|
|
29
|
-
<EndpointPage data={data} />
|
|
31
|
+
<EndpointPage data={data as EndpointData} />
|
|
30
32
|
)}
|
|
31
33
|
</main>
|
|
32
34
|
)
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
DownArrowIcon,
|
|
7
7
|
RequestOption,
|
|
8
8
|
} from '../../../../assets/icons/index'
|
|
9
|
-
import {
|
|
9
|
+
import { SelectGroup } from 'digitinary-ui'
|
|
10
10
|
import { useEffect, useState } from 'react'
|
|
11
11
|
import { EndpointData } from 'src/layout/docsLayout'
|
|
12
12
|
import { handleStatusColor } from '../../../../helpers/methodAccordion.helper'
|
|
@@ -14,7 +14,7 @@ import { httpStatusCodes } from '../../../../constants/index'
|
|
|
14
14
|
import styles from '../../Codebox/style.module.scss'
|
|
15
15
|
import Tooltip from '../../../../components/Tooltip/Tooltip'
|
|
16
16
|
|
|
17
|
-
export const EndpointPage = ({ data }) => {
|
|
17
|
+
export const EndpointPage = ({ data }: { data: EndpointData }) => {
|
|
18
18
|
const [activeTab, setActiveTab] = useState('header')
|
|
19
19
|
|
|
20
20
|
const httpStatusCodeOptions = httpStatusCodes.map((code) => ({
|
|
@@ -177,15 +177,17 @@ export const EndpointPage = ({ data }) => {
|
|
|
177
177
|
</tr>
|
|
178
178
|
</thead>
|
|
179
179
|
<tbody>
|
|
180
|
-
{!!headersList &&
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
180
|
+
{!!headersList &&
|
|
181
|
+
Object.keys(headersList) &&
|
|
182
|
+
Object.keys(headersList).map((key, index) => (
|
|
183
|
+
<tr>
|
|
184
|
+
<td>{key}</td>
|
|
185
|
+
<td>{headersList[key]?.required.toString()}</td>
|
|
186
|
+
<td>{headersList[key]?.schema?.type}</td>
|
|
187
|
+
<td>{headersList[key]?.schema?.enum?.join('/')}</td>
|
|
188
|
+
<td>{headersList[key]?.description}</td>
|
|
189
|
+
</tr>
|
|
190
|
+
))}
|
|
189
191
|
</tbody>
|
|
190
192
|
</table>
|
|
191
193
|
</div>
|
|
@@ -1,9 +1,57 @@
|
|
|
1
1
|
import './style.scss'
|
|
2
2
|
import SVGLoader from '../../../../components/SVGLoader/SVGLoader'
|
|
3
3
|
import { arrowRightGray, CopySticker } from '../../../../assets/icons/index'
|
|
4
|
-
import { OverviewData } from 'src/layout/docsLayout'
|
|
4
|
+
import { EndpointData, OverviewData } from 'src/layout/docsLayout'
|
|
5
|
+
|
|
6
|
+
export const TagPage = ({
|
|
7
|
+
data,
|
|
8
|
+
setActiveItemData,
|
|
9
|
+
setActiveType,
|
|
10
|
+
setExpandedSections,
|
|
11
|
+
}: {
|
|
12
|
+
data: OverviewData
|
|
13
|
+
setActiveItemData: React.Dispatch<React.SetStateAction<OverviewData | EndpointData>>
|
|
14
|
+
setActiveType: React.Dispatch<React.SetStateAction<'OVERVIEW' | 'ENDPOINT'>>
|
|
15
|
+
setExpandedSections: React.Dispatch<React.SetStateAction<Record<string, boolean>>>
|
|
16
|
+
}) => {
|
|
17
|
+
const handleVersionClick = (verObj) => {
|
|
18
|
+
if (verObj.apiSpecId === data.apiSpecId) {
|
|
19
|
+
setActiveType('OVERVIEW')
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const matchedVersion = data.apiVersions.find((v) => v.apiSpecId === verObj.apiSpecId)
|
|
24
|
+
|
|
25
|
+
if (!matchedVersion) {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const newData = {
|
|
30
|
+
...data,
|
|
31
|
+
...matchedVersion,
|
|
32
|
+
version: matchedVersion.metaData?.version || '',
|
|
33
|
+
title: matchedVersion.name || '',
|
|
34
|
+
apiSpecId: matchedVersion.apiSpecId,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setActiveItemData({
|
|
38
|
+
...newData,
|
|
39
|
+
api: {
|
|
40
|
+
id: newData.apiSpecId,
|
|
41
|
+
title: newData.title,
|
|
42
|
+
description: newData.description,
|
|
43
|
+
version: newData.version,
|
|
44
|
+
...newData,
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
setActiveType('OVERVIEW')
|
|
49
|
+
setExpandedSections((prev) => ({
|
|
50
|
+
...prev,
|
|
51
|
+
[`api-${newData.apiSpecId}-section`]: true,
|
|
52
|
+
}))
|
|
53
|
+
}
|
|
5
54
|
|
|
6
|
-
export const TagPage = ({ data, setActiveItemData, setActiveType, setExpandedSections }) => {
|
|
7
55
|
const handleClick = (endpoint) => {
|
|
8
56
|
setActiveItemData({
|
|
9
57
|
...endpoint,
|
|
@@ -44,7 +92,9 @@ export const TagPage = ({ data, setActiveItemData, setActiveType, setExpandedSec
|
|
|
44
92
|
className="icon"
|
|
45
93
|
onClick={() =>
|
|
46
94
|
navigator.clipboard.writeText(
|
|
47
|
-
`${
|
|
95
|
+
`${
|
|
96
|
+
!!data && !!data.servers && data.servers.length > 0 ? data.servers[0]?.url : '-'
|
|
97
|
+
}`
|
|
48
98
|
)
|
|
49
99
|
}
|
|
50
100
|
>
|
|
@@ -102,7 +152,11 @@ export const TagPage = ({ data, setActiveItemData, setActiveType, setExpandedSec
|
|
|
102
152
|
<h4>API Versions</h4>
|
|
103
153
|
<div className="version-list">
|
|
104
154
|
{data.apiVersions.map((verObj, index) => (
|
|
105
|
-
<button
|
|
155
|
+
<button
|
|
156
|
+
key={index}
|
|
157
|
+
className="version-btn"
|
|
158
|
+
onClick={() => handleVersionClick(verObj)}
|
|
159
|
+
>
|
|
106
160
|
{verObj.metaData?.version || 'N/A'}
|
|
107
161
|
</button>
|
|
108
162
|
))}
|
|
@@ -14,62 +14,38 @@ const DocsSideMenuTree = ({
|
|
|
14
14
|
isFirstApiExpanded,
|
|
15
15
|
setIsFirstApiExpanded,
|
|
16
16
|
setActiveType,
|
|
17
|
+
toggleSection,
|
|
18
|
+
canSelectFirstApi,
|
|
17
19
|
}: {
|
|
18
20
|
apis: OverviewData[]
|
|
19
21
|
setActiveItemData: React.Dispatch<React.SetStateAction<OverviewData | EndpointData>>
|
|
20
22
|
activeItemData: OverviewData | EndpointData
|
|
21
23
|
expandedSections: Record<string, boolean>
|
|
22
|
-
setExpandedSections:
|
|
24
|
+
setExpandedSections: (newSections: Record<string, boolean>) => void
|
|
23
25
|
isFirstApiExpanded: boolean
|
|
24
26
|
setIsFirstApiExpanded: React.Dispatch<React.SetStateAction<boolean>>
|
|
25
27
|
setActiveType: React.Dispatch<React.SetStateAction<'OVERVIEW' | 'ENDPOINT'>>
|
|
26
28
|
activeType: 'OVERVIEW' | 'ENDPOINT'
|
|
29
|
+
toggleSection: (apiId: string, sectionId: string, resetOthers?: boolean, key?: string[]) => void
|
|
30
|
+
canSelectFirstApi?: boolean
|
|
27
31
|
}) => {
|
|
28
32
|
// Auto-expand first API only once
|
|
29
33
|
useEffect(() => {
|
|
30
|
-
if (!apis?.length || !isFirstApiExpanded) return
|
|
34
|
+
if (canSelectFirstApi || !apis?.length || !isFirstApiExpanded) return
|
|
31
35
|
|
|
32
36
|
const firstApi = apis[0]
|
|
33
37
|
const sectionKey = `api-${firstApi.apiSpecId}-section`
|
|
34
38
|
const overviewKey = `api-${firstApi.apiSpecId}-overview`
|
|
35
39
|
|
|
36
|
-
setExpandedSections(
|
|
37
|
-
...prev,
|
|
40
|
+
setExpandedSections({
|
|
38
41
|
[sectionKey]: true,
|
|
39
42
|
[overviewKey]: true,
|
|
40
|
-
})
|
|
41
|
-
|
|
43
|
+
})
|
|
42
44
|
setActiveItemData(firstApi)
|
|
43
45
|
setActiveType('OVERVIEW')
|
|
44
46
|
setIsFirstApiExpanded(false)
|
|
45
47
|
}, [apis, isFirstApiExpanded])
|
|
46
48
|
|
|
47
|
-
const toggleSection = (apiId, sectionId: string, resetOthers?: boolean, key?: string[]) => {
|
|
48
|
-
if (resetOthers && key) {
|
|
49
|
-
const filteredExpandedSections = Object.fromEntries(
|
|
50
|
-
Object.entries({ ...expandedSections }).filter(([expandKey]) => {
|
|
51
|
-
// Close other APIs sections
|
|
52
|
-
if (!expandKey.includes(apiId)) return false
|
|
53
|
-
// always return the clicked on section
|
|
54
|
-
if (expandKey === sectionId) return true
|
|
55
|
-
// filter all sections containing the key
|
|
56
|
-
if (key.some((k) => expandKey.includes(k))) return false
|
|
57
|
-
return true
|
|
58
|
-
})
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
setExpandedSections({
|
|
62
|
-
...filteredExpandedSections,
|
|
63
|
-
[sectionId]: !expandedSections[sectionId],
|
|
64
|
-
})
|
|
65
|
-
} else {
|
|
66
|
-
setExpandedSections((prev) => ({
|
|
67
|
-
...prev,
|
|
68
|
-
[sectionId]: !prev[sectionId],
|
|
69
|
-
}))
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
49
|
const renderEndpoints = (endpoints: EndpointData[], api: OverviewData) =>
|
|
74
50
|
endpoints.map((endpoint, index) => {
|
|
75
51
|
const key = `api-${api.apiSpecId}-resource-${endpoint.id}`
|
|
@@ -200,7 +176,9 @@ const DocsSideMenuTree = ({
|
|
|
200
176
|
.sort(([a], [b]) =>
|
|
201
177
|
a === 'default' ? 1 : b === 'default' ? -1 : a.localeCompare(b)
|
|
202
178
|
)
|
|
203
|
-
.map(([tagName, data], i) =>
|
|
179
|
+
.map(([tagName, data], i) =>
|
|
180
|
+
renderSubSection(tagName, data as EndpointData[], api, i)
|
|
181
|
+
)}
|
|
204
182
|
</div>
|
|
205
183
|
)}
|
|
206
184
|
</>
|
|
@@ -3,9 +3,11 @@ import Layout from './docsComponents'
|
|
|
3
3
|
import { HTTPMethod, OpenAPIFile, Parameter, RequestBody, Responses } from '@entities/openApi'
|
|
4
4
|
import { transformOpenApiToDocs } from '../helpers/docs.helper'
|
|
5
5
|
import { ApiSpecModel } from '@entities/index'
|
|
6
|
+
import stableStringify from 'fast-json-stable-stringify'
|
|
6
7
|
|
|
7
8
|
interface ILayoutProps {
|
|
8
9
|
apis?: ApiSpecModel[]
|
|
10
|
+
activeApiId?: string
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export interface TagData {
|
|
@@ -37,16 +39,60 @@ export interface OverviewData extends Omit<ApiSpecModel, 'metaData'> {
|
|
|
37
39
|
servers: OpenAPIFile['servers']
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
function areEqual(prev: ILayoutProps, next: ILayoutProps): boolean {
|
|
43
|
+
return (
|
|
44
|
+
stableStringify(prev.apis ?? []) === stableStringify(next.apis ?? []) &&
|
|
45
|
+
prev.activeApiId === next.activeApiId
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const DocsLayout = ({ apis, activeApiId }: ILayoutProps): JSX.Element => {
|
|
50
|
+
const [transformedOpenApis, setTransformedOpenApis] = useState<OverviewData[]>([])
|
|
42
51
|
const [isFirstApiExpanded, setIsFirstApiExpanded] = useState(true)
|
|
43
|
-
const [activeItemData, setActiveItemData] = useState<
|
|
52
|
+
const [activeItemData, setActiveItemData] = useState<
|
|
53
|
+
OverviewData | EndpointData | Record<string, never>
|
|
54
|
+
>({})
|
|
44
55
|
const [activeType, setActiveType] = useState<'OVERVIEW' | 'ENDPOINT'>('OVERVIEW')
|
|
45
|
-
const [expandedSections, setExpandedSections] = useState({})
|
|
46
|
-
const allData = useRef([])
|
|
56
|
+
const [expandedSections, setExpandedSections] = useState<Record<string, boolean>>({})
|
|
57
|
+
const allData = useRef([])
|
|
47
58
|
const [pending, setPending] = useState(true)
|
|
59
|
+
const [canSelectFirstApi, setCanSelectFirstApi] = useState(false)
|
|
60
|
+
|
|
61
|
+
const toggleSection = (
|
|
62
|
+
apiId: string,
|
|
63
|
+
sectionId: string,
|
|
64
|
+
resetOthers?: boolean,
|
|
65
|
+
key?: string[]
|
|
66
|
+
) => {
|
|
67
|
+
setCanSelectFirstApi(false)
|
|
68
|
+
if (resetOthers && key) {
|
|
69
|
+
const filteredExpandedSections = Object.fromEntries(
|
|
70
|
+
Object.entries({ ...expandedSections }).filter(([expandKey]) => {
|
|
71
|
+
// Close other APIs sections
|
|
72
|
+
if (!expandKey.includes(apiId)) return false
|
|
73
|
+
// always return the clicked on section
|
|
74
|
+
if (expandKey === sectionId) return true
|
|
75
|
+
// filter all sections containing the key
|
|
76
|
+
if (key.some((k) => expandKey.includes(k))) return false
|
|
77
|
+
return true
|
|
78
|
+
})
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
setExpandedSections({
|
|
82
|
+
...filteredExpandedSections,
|
|
83
|
+
[sectionId]: !expandedSections[sectionId],
|
|
84
|
+
})
|
|
85
|
+
} else {
|
|
86
|
+
setExpandedSections((prev) => ({
|
|
87
|
+
...prev,
|
|
88
|
+
[sectionId]: !expandedSections[sectionId],
|
|
89
|
+
}))
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
48
93
|
useEffect(() => {
|
|
49
94
|
if (transformedOpenApis.length === 0) {
|
|
95
|
+
setCanSelectFirstApi(!!activeApiId)
|
|
50
96
|
const t = structuredClone(apis)
|
|
51
97
|
?.map((o3) => transformOpenApiToDocs(o3))
|
|
52
98
|
.sort((a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase()))
|
|
@@ -58,35 +104,67 @@ const DocsLayout = ({ apis }: ILayoutProps): JSX.Element => {
|
|
|
58
104
|
}
|
|
59
105
|
}, [apis])
|
|
60
106
|
|
|
61
|
-
const updateFilteredData = (filteredItems, isReset=false) => {
|
|
62
|
-
if(isReset){
|
|
107
|
+
const updateFilteredData = (filteredItems, isReset = false) => {
|
|
108
|
+
if (isReset) {
|
|
63
109
|
setTransformedOpenApis(allData.current)
|
|
64
|
-
return
|
|
110
|
+
return
|
|
65
111
|
}
|
|
66
112
|
setTransformedOpenApis(filteredItems)
|
|
67
113
|
}
|
|
68
114
|
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
if (activeApiId && transformedOpenApis.length > 0) {
|
|
117
|
+
const activeApi = transformedOpenApis.find((api) => api.apiSpecId === activeApiId)
|
|
118
|
+
const sectionKey = `api-${activeApi.apiSpecId}-section`
|
|
119
|
+
const overviewKey = `api-${activeApi.apiSpecId}-overview`
|
|
120
|
+
|
|
121
|
+
setExpandedSections((prev) => ({
|
|
122
|
+
...prev,
|
|
123
|
+
[sectionKey]: true,
|
|
124
|
+
[overviewKey]: true,
|
|
125
|
+
}))
|
|
126
|
+
setActiveItemData(activeApi)
|
|
127
|
+
setActiveType('OVERVIEW')
|
|
128
|
+
setIsFirstApiExpanded(false)
|
|
129
|
+
setCanSelectFirstApi(true)
|
|
130
|
+
}
|
|
131
|
+
}, [activeApiId, transformedOpenApis])
|
|
132
|
+
|
|
69
133
|
return (
|
|
70
134
|
<Layout>
|
|
71
|
-
<Layout.DocsHeader
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
setActiveItemData={setActiveItemData}
|
|
75
|
-
activeItemData={activeItemData}
|
|
76
|
-
expandedSections={expandedSections}
|
|
77
|
-
setExpandedSections={setExpandedSections}
|
|
78
|
-
isFirstApiExpanded={isFirstApiExpanded}
|
|
79
|
-
activeType={activeType}
|
|
80
|
-
setIsFirstApiExpanded={setIsFirstApiExpanded}
|
|
81
|
-
setActiveType={setActiveType}
|
|
135
|
+
<Layout.DocsHeader
|
|
136
|
+
transformedOpenApis={transformedOpenApis}
|
|
137
|
+
updateFilteredData={updateFilteredData}
|
|
82
138
|
/>
|
|
139
|
+
{!pending && (
|
|
140
|
+
<Layout.DocsSideMenuTree
|
|
141
|
+
apis={transformedOpenApis}
|
|
142
|
+
setActiveItemData={setActiveItemData}
|
|
143
|
+
activeItemData={activeItemData as OverviewData | EndpointData}
|
|
144
|
+
expandedSections={expandedSections}
|
|
145
|
+
setExpandedSections={(newExpandedSections) =>
|
|
146
|
+
setExpandedSections((prev) => ({
|
|
147
|
+
...prev,
|
|
148
|
+
...newExpandedSections,
|
|
149
|
+
}))
|
|
150
|
+
}
|
|
151
|
+
isFirstApiExpanded={isFirstApiExpanded}
|
|
152
|
+
activeType={activeType}
|
|
153
|
+
setIsFirstApiExpanded={setIsFirstApiExpanded}
|
|
154
|
+
setActiveType={setActiveType}
|
|
155
|
+
toggleSection={toggleSection}
|
|
156
|
+
canSelectFirstApi={canSelectFirstApi}
|
|
157
|
+
/>
|
|
158
|
+
)}
|
|
159
|
+
|
|
83
160
|
{!pending && Object.keys(activeItemData).length > 0 && (
|
|
84
161
|
<Layout.DocsContent
|
|
85
|
-
data={activeItemData}
|
|
162
|
+
data={activeItemData as OverviewData | EndpointData}
|
|
86
163
|
activeType={activeType}
|
|
87
164
|
setActiveItemData={setActiveItemData}
|
|
88
165
|
setActiveType={setActiveType}
|
|
89
166
|
setExpandedSections={setExpandedSections}
|
|
167
|
+
toggleSection={toggleSection}
|
|
90
168
|
/>
|
|
91
169
|
)}
|
|
92
170
|
{activeType === 'ENDPOINT' && <Layout.DocsAside data={activeItemData as EndpointData} />}
|
|
@@ -94,4 +172,4 @@ const DocsLayout = ({ apis }: ILayoutProps): JSX.Element => {
|
|
|
94
172
|
)
|
|
95
173
|
}
|
|
96
174
|
|
|
97
|
-
export default DocsLayout
|
|
175
|
+
export default React.memo(DocsLayout, areEqual)
|