@digi-frontend/dgate-api-documentation 1.0.50 → 1.0.52
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/_virtual/index6.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 +1 -1
- package/dist/src/helpers/docs.helper.js.map +1 -1
- package/dist/src/helpers/layout.helper.js +1 -1
- package/dist/src/helpers/layout.helper.js.map +1 -1
- package/dist/src/layout/docsComponents/DocsAside/DocsAside.js +1 -1
- package/dist/src/layout/docsComponents/DocsAside/DocsAside.js.map +1 -1
- package/dist/src/layout/docsComponents/DocsContent/DocsContent.js +1 -1
- package/dist/src/layout/docsComponents/DocsContent/DocsContent.js.map +1 -1
- package/dist/src/layout/docsComponents/DocsContent/EndpointPage/index.js +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/DocsHeader/DocsHeader.js +1 -1
- package/dist/src/layout/docsComponents/DocsHeader/DocsHeader.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/src/layout/layout.js +1 -1
- package/dist/src/layout/layout.js.map +1 -1
- package/dist/src/layout/layout.module.css.js +1 -1
- package/dist/src/validator/form.scheme.js +1 -1
- package/dist/src/validator/form.scheme.js.map +1 -1
- package/dist/styles.css +638 -596
- package/dist/types/helpers/docs.helper.d.ts +2 -2
- package/dist/types/layout/docsComponents/DocsContent/DocsContent.d.ts +2 -1
- package/dist/types/layout/docsComponents/DocsContent/TagPage/index.d.ts +4 -1
- package/dist/types/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.d.ts +12 -6
- package/dist/types/layout/docsLayout.d.ts +5 -4
- package/dist/types/layout/layout.d.ts +1 -1
- package/dist/types/types/index.d.ts +27 -0
- package/dist/types/types/layout.type.d.ts +1 -0
- package/dist/types/types/openApi.d.ts +1 -0
- package/dist/types/validator/form.scheme.d.ts +1 -0
- package/package.json +1 -2
- package/src/components/MethodAccordion/MethodAccordion.tsx +372 -4
- package/src/helpers/docs.helper.ts +17 -4
- package/src/helpers/layout.helper.ts +19 -2
- package/src/layout/docsComponents/DocsAside/DocsAside.tsx +6 -7
- package/src/layout/docsComponents/DocsContent/DocsContent.tsx +24 -3
- package/src/layout/docsComponents/DocsContent/EndpointPage/index.tsx +132 -121
- package/src/layout/docsComponents/DocsContent/EndpointPage/style.scss +45 -0
- package/src/layout/docsComponents/DocsContent/TagPage/index.tsx +49 -17
- package/src/layout/docsComponents/DocsHeader/DocsHeader.tsx +34 -1
- package/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.tsx +106 -79
- package/src/layout/docsLayout.tsx +43 -17
- package/src/layout/layout.module.css +1 -1
- package/src/layout/layout.tsx +36 -18
- package/src/types/index.ts +28 -0
- package/src/types/layout.type.ts +1 -0
- package/src/types/openApi.ts +1 -0
- package/src/validator/form.scheme.ts +9 -1
|
@@ -1,29 +1,60 @@
|
|
|
1
1
|
import './style.scss'
|
|
2
|
-
import React, { useState } from 'react'
|
|
2
|
+
import React, { useEffect, useState } from 'react'
|
|
3
3
|
import SVGLoader from '../../../components/SVGLoader/SVGLoader'
|
|
4
4
|
import { arrowDownGray, arrowRightGray, document, eye } from '../../../assets/icons'
|
|
5
|
+
import { EndpointData, OverviewData } from 'src/layout/docsLayout'
|
|
5
6
|
|
|
6
7
|
const DocsSideMenuTree = ({
|
|
7
8
|
apis,
|
|
8
9
|
setActiveItemData,
|
|
10
|
+
activeItemData,
|
|
11
|
+
activeType,
|
|
12
|
+
expandedSections,
|
|
13
|
+
setExpandedSections,
|
|
9
14
|
isFirstApiExpanded,
|
|
10
15
|
setIsFirstApiExpanded,
|
|
11
16
|
setActiveType,
|
|
17
|
+
}: {
|
|
18
|
+
apis: OverviewData[]
|
|
19
|
+
setActiveItemData: React.Dispatch<React.SetStateAction<OverviewData | EndpointData>>
|
|
20
|
+
activeItemData: OverviewData | EndpointData
|
|
21
|
+
expandedSections: Record<string, boolean>
|
|
22
|
+
setExpandedSections: React.Dispatch<React.SetStateAction<Record<string, boolean>>>
|
|
23
|
+
isFirstApiExpanded: boolean
|
|
24
|
+
setIsFirstApiExpanded: React.Dispatch<React.SetStateAction<boolean>>
|
|
25
|
+
setActiveType: React.Dispatch<React.SetStateAction<'OVERVIEW' | 'ENDPOINT'>>
|
|
26
|
+
activeType: 'OVERVIEW' | 'ENDPOINT'
|
|
12
27
|
}) => {
|
|
13
|
-
|
|
28
|
+
// Auto-expand first API only once
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!apis?.length || !isFirstApiExpanded) return
|
|
31
|
+
|
|
32
|
+
const firstApi = apis[0]
|
|
33
|
+
const sectionKey = `api-${firstApi.apiSpecId}-section`
|
|
34
|
+
const overviewKey = `api-${firstApi.apiSpecId}-overview`
|
|
35
|
+
|
|
36
|
+
setExpandedSections((prev) => ({
|
|
37
|
+
...prev,
|
|
38
|
+
[sectionKey]: true,
|
|
39
|
+
[overviewKey]: true,
|
|
40
|
+
}))
|
|
41
|
+
|
|
42
|
+
setActiveItemData(firstApi)
|
|
43
|
+
setActiveType('OVERVIEW')
|
|
44
|
+
setIsFirstApiExpanded(false)
|
|
45
|
+
}, [apis, isFirstApiExpanded])
|
|
14
46
|
|
|
15
47
|
const toggleSection = (apiId, sectionId: string, resetOthers?: boolean, key?: string[]) => {
|
|
16
|
-
isFirstApiExpanded && setIsFirstApiExpanded(false)
|
|
17
48
|
if (resetOthers && key) {
|
|
18
49
|
const filteredExpandedSections = Object.fromEntries(
|
|
19
|
-
Object.entries({ ...expandedSections }).filter(([expandKey
|
|
50
|
+
Object.entries({ ...expandedSections }).filter(([expandKey]) => {
|
|
20
51
|
// Close other APIs sections
|
|
21
52
|
if (!expandKey.includes(apiId)) return false
|
|
22
53
|
// always return the clicked on section
|
|
23
|
-
|
|
54
|
+
if (expandKey === sectionId) return true
|
|
24
55
|
// filter all sections containing the key
|
|
25
|
-
|
|
26
|
-
|
|
56
|
+
if (key.some((k) => expandKey.includes(k))) return false
|
|
57
|
+
return true
|
|
27
58
|
})
|
|
28
59
|
)
|
|
29
60
|
|
|
@@ -39,65 +70,94 @@ const DocsSideMenuTree = ({
|
|
|
39
70
|
}
|
|
40
71
|
}
|
|
41
72
|
|
|
42
|
-
const renderEndpoints = (endpoints, api) =>
|
|
43
|
-
|
|
44
|
-
const
|
|
73
|
+
const renderEndpoints = (endpoints: EndpointData[], api: OverviewData) =>
|
|
74
|
+
endpoints.map((endpoint, index) => {
|
|
75
|
+
const key = `api-${api.apiSpecId}-resource-${endpoint.id}`
|
|
76
|
+
const isExpanded = expandedSections[key]
|
|
45
77
|
|
|
46
78
|
return (
|
|
47
79
|
<div
|
|
48
80
|
key={index}
|
|
49
81
|
className={`api-docs-api-tree__endpoint api-docs-api-tree__endpoint--${endpoint.method.toLowerCase()}`}
|
|
50
82
|
onClick={() => {
|
|
51
|
-
if (!
|
|
83
|
+
if (!isExpanded) {
|
|
52
84
|
setActiveItemData({
|
|
53
85
|
...endpoint,
|
|
54
86
|
api: {
|
|
55
|
-
id: api.
|
|
87
|
+
id: api.apiSpecId,
|
|
56
88
|
title: api.title,
|
|
57
89
|
description: api.description,
|
|
58
90
|
version: api.version,
|
|
91
|
+
...api,
|
|
59
92
|
},
|
|
60
93
|
})
|
|
61
94
|
setActiveType('ENDPOINT')
|
|
62
|
-
toggleSection(api.
|
|
63
|
-
'resource',
|
|
64
|
-
'overview',
|
|
65
|
-
])
|
|
95
|
+
toggleSection(api.apiSpecId, key, true, ['resource', 'overview'])
|
|
66
96
|
}
|
|
67
97
|
}}
|
|
68
|
-
data-active={
|
|
98
|
+
data-active={isExpanded}
|
|
69
99
|
>
|
|
70
100
|
<span className="api-docs-api-tree__endpoint-method">{endpoint.method}</span>
|
|
71
101
|
<span className="api-docs-api-tree__endpoint-name">{endpoint.path}</span>
|
|
72
102
|
</div>
|
|
73
103
|
)
|
|
74
104
|
})
|
|
75
|
-
}
|
|
76
105
|
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
106
|
+
const renderSubSection = (
|
|
107
|
+
tagName: string,
|
|
108
|
+
data: EndpointData[],
|
|
109
|
+
api: OverviewData,
|
|
110
|
+
sectionIndex: number
|
|
111
|
+
) => {
|
|
112
|
+
const sectionKey = `api-${api.apiSpecId}-section-${sectionIndex}`
|
|
113
|
+
const isSectionExpanded = expandedSections[sectionKey]
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<div key={sectionKey} className="api-docs-api-tree__subsection">
|
|
117
|
+
<div
|
|
118
|
+
className="api-docs-api-tree__subsection-header"
|
|
119
|
+
onClick={() => toggleSection(api.apiSpecId, sectionKey)}
|
|
120
|
+
>
|
|
121
|
+
{isSectionExpanded ? (
|
|
122
|
+
<SVGLoader src={arrowDownGray} />
|
|
123
|
+
) : (
|
|
124
|
+
<SVGLoader src={arrowRightGray} />
|
|
125
|
+
)}
|
|
126
|
+
<span className="api-docs-api-tree__subsection-title">{tagName}</span>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
{isSectionExpanded && (
|
|
130
|
+
<div className="api-docs-api-tree__endpoints">{renderEndpoints(data, api)}</div>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
81
133
|
)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const renderApiSection = (api: OverviewData) => {
|
|
137
|
+
const sectionKey = `api-${api.apiSpecId}-section`
|
|
138
|
+
const endpointsKey = `api-${api.apiSpecId}-endpoints`
|
|
139
|
+
const overviewKey = `api-${api.apiSpecId}-overview`
|
|
140
|
+
|
|
141
|
+
const isApiExpanded = expandedSections[sectionKey]
|
|
142
|
+
const isOverviewExpanded =
|
|
143
|
+
'apiSpecId' in activeItemData &&
|
|
144
|
+
activeItemData.apiSpecId === api.apiSpecId &&
|
|
145
|
+
activeType === 'OVERVIEW'
|
|
146
|
+
const isEndpointActive =
|
|
147
|
+
'api' in activeItemData &&
|
|
148
|
+
activeItemData.api.id === api.apiSpecId &&
|
|
149
|
+
'path' in activeItemData &&
|
|
150
|
+
'method' in activeItemData
|
|
91
151
|
|
|
92
152
|
return (
|
|
93
153
|
<div
|
|
94
|
-
key={api.
|
|
154
|
+
key={api.apiSpecId}
|
|
95
155
|
className="api-docs-api-tree__section"
|
|
96
156
|
data-active={isEndpointActive || isOverviewExpanded}
|
|
97
157
|
>
|
|
98
158
|
<div
|
|
99
159
|
className="api-docs-api-tree__section-header"
|
|
100
|
-
onClick={() => toggleSection(api.
|
|
160
|
+
onClick={() => toggleSection(api.apiSpecId, sectionKey)}
|
|
101
161
|
>
|
|
102
162
|
{isApiExpanded ? <SVGLoader src={arrowDownGray} /> : <SVGLoader src={arrowRightGray} />}
|
|
103
163
|
<SVGLoader src={document} />
|
|
@@ -107,42 +167,40 @@ const DocsSideMenuTree = ({
|
|
|
107
167
|
{isApiExpanded && (
|
|
108
168
|
<>
|
|
109
169
|
<div
|
|
110
|
-
className=
|
|
170
|
+
className="api-docs-api-tree__section__overview"
|
|
111
171
|
onClick={() => {
|
|
112
172
|
if (!isOverviewExpanded) {
|
|
113
|
-
toggleSection(api.
|
|
173
|
+
toggleSection(api.apiSpecId, overviewKey, true, ['resource'])
|
|
114
174
|
setActiveItemData(api)
|
|
115
175
|
setActiveType('OVERVIEW')
|
|
116
176
|
}
|
|
117
177
|
}}
|
|
118
178
|
data-active={isOverviewExpanded}
|
|
119
179
|
>
|
|
120
|
-
|
|
180
|
+
<SVGLoader src={eye} />
|
|
121
181
|
<span>Overview</span>
|
|
122
182
|
</div>
|
|
183
|
+
|
|
123
184
|
<div
|
|
124
185
|
className="api-docs-api-tree__section__endpoints"
|
|
125
|
-
onClick={() =>
|
|
126
|
-
toggleSection(api.id, `api-${api.id}-endpoints`)
|
|
127
|
-
}}
|
|
186
|
+
onClick={() => toggleSection(api.apiSpecId, endpointsKey)}
|
|
128
187
|
data-active={isEndpointActive && !isOverviewExpanded}
|
|
129
188
|
>
|
|
130
|
-
{
|
|
189
|
+
{expandedSections[endpointsKey] ? (
|
|
131
190
|
<SVGLoader src={arrowDownGray} />
|
|
132
191
|
) : (
|
|
133
192
|
<SVGLoader src={arrowRightGray} />
|
|
134
193
|
)}
|
|
135
194
|
<span>Endpoints</span>
|
|
136
195
|
</div>
|
|
137
|
-
|
|
196
|
+
|
|
197
|
+
{expandedSections[endpointsKey] && (
|
|
138
198
|
<div className="api-docs-api-tree__subsections">
|
|
139
199
|
{Object.entries(api.tags)
|
|
140
|
-
.sort(([a], [b]) =>
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
})
|
|
145
|
-
.map(([tagName, data], index) => renderSubSection(tagName, data, api, index))}
|
|
200
|
+
.sort(([a], [b]) =>
|
|
201
|
+
a === 'default' ? 1 : b === 'default' ? -1 : a.localeCompare(b)
|
|
202
|
+
)
|
|
203
|
+
.map(([tagName, data], i) => renderSubSection(tagName, data, api, i))}
|
|
146
204
|
</div>
|
|
147
205
|
)}
|
|
148
206
|
</>
|
|
@@ -151,38 +209,7 @@ const DocsSideMenuTree = ({
|
|
|
151
209
|
)
|
|
152
210
|
}
|
|
153
211
|
|
|
154
|
-
|
|
155
|
-
const sectionKey = `api-${api.id}-section-${sectionIndex}`
|
|
156
|
-
const isSectionExpanded = expandedSections[sectionKey]
|
|
157
|
-
|
|
158
|
-
return (
|
|
159
|
-
<div key={sectionKey} className="api-docs-api-tree__subsection">
|
|
160
|
-
<>
|
|
161
|
-
<div
|
|
162
|
-
className="api-docs-api-tree__subsection-header"
|
|
163
|
-
onClick={() => toggleSection(api.id, sectionKey)}
|
|
164
|
-
>
|
|
165
|
-
{isSectionExpanded ? (
|
|
166
|
-
<SVGLoader src={arrowDownGray} />
|
|
167
|
-
) : (
|
|
168
|
-
<SVGLoader src={arrowRightGray} />
|
|
169
|
-
)}
|
|
170
|
-
<span className="api-docs-api-tree__subsection-title">{tagName}</span>
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
{isSectionExpanded && (
|
|
174
|
-
<div className="api-docs-api-tree__endpoints">{renderEndpoints(data, api)}</div>
|
|
175
|
-
)}
|
|
176
|
-
</>
|
|
177
|
-
</div>
|
|
178
|
-
)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return (
|
|
182
|
-
<aside className="api-docs-api-tree">
|
|
183
|
-
{apis.map((api, index) => renderApiSection(api, index))}
|
|
184
|
-
</aside>
|
|
185
|
-
)
|
|
212
|
+
return <aside className="api-docs-api-tree">{apis.map((api) => renderApiSection(api))}</aside>
|
|
186
213
|
}
|
|
187
214
|
|
|
188
215
|
export default DocsSideMenuTree
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import React, { JSX, useEffect, useState } from 'react'
|
|
1
|
+
import React, { JSX, useEffect, useRef, useState } from 'react'
|
|
2
2
|
import Layout from './docsComponents'
|
|
3
3
|
import { HTTPMethod, OpenAPIFile, Parameter, RequestBody, Responses } from '@entities/openApi'
|
|
4
4
|
import { transformOpenApiToDocs } from '../helpers/docs.helper'
|
|
5
|
+
import { ApiSpecModel } from '@entities/index'
|
|
5
6
|
|
|
6
7
|
interface ILayoutProps {
|
|
7
|
-
|
|
8
|
+
apis?: ApiSpecModel[]
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export interface TagData {
|
|
@@ -28,43 +29,68 @@ export interface EndpointData extends TagData {
|
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
export interface OverviewData {
|
|
32
|
-
id: string
|
|
32
|
+
export interface OverviewData extends Omit<ApiSpecModel, 'metaData'> {
|
|
33
33
|
description: string
|
|
34
34
|
title: string
|
|
35
35
|
version: string
|
|
36
36
|
tags: Record<string, TagData[]>
|
|
37
|
+
servers: OpenAPIFile['servers']
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
const DocsLayout = ({
|
|
40
|
+
const DocsLayout = ({ apis }: ILayoutProps): JSX.Element => {
|
|
40
41
|
const [transformedOpenApis, setTransformedOpenApis] = useState([])
|
|
41
42
|
const [isFirstApiExpanded, setIsFirstApiExpanded] = useState(true)
|
|
42
|
-
const [activeItemData, setActiveItemData] = useState<OverviewData | EndpointData>()
|
|
43
|
-
const [activeType, setActiveType] = useState<'OVERVIEW' | 'ENDPOINT'>()
|
|
43
|
+
const [activeItemData, setActiveItemData] = useState<OverviewData | EndpointData | {}>({})
|
|
44
|
+
const [activeType, setActiveType] = useState<'OVERVIEW' | 'ENDPOINT'>('OVERVIEW')
|
|
45
|
+
const [expandedSections, setExpandedSections] = useState({})
|
|
46
|
+
const allData = useRef([]);
|
|
44
47
|
const [pending, setPending] = useState(true)
|
|
48
|
+
console.log({ apis, transformedOpenApis, activeItemData })
|
|
45
49
|
useEffect(() => {
|
|
46
50
|
if (transformedOpenApis.length === 0) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const t = structuredClone(apis)
|
|
52
|
+
?.map((o3) => transformOpenApiToDocs(o3))
|
|
53
|
+
.sort((a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase()))
|
|
54
|
+
setTransformedOpenApis(t)
|
|
55
|
+
allData.current = t
|
|
56
|
+
if (t.length > 0) {
|
|
57
|
+
setPending(false)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}, [apis])
|
|
61
|
+
|
|
62
|
+
const updateFilteredData = (filteredItems, isReset=false) => {
|
|
63
|
+
if(isReset){
|
|
64
|
+
setTransformedOpenApis(allData.current)
|
|
65
|
+
return;
|
|
53
66
|
}
|
|
54
|
-
|
|
67
|
+
setTransformedOpenApis(filteredItems)
|
|
68
|
+
}
|
|
55
69
|
|
|
56
70
|
return (
|
|
57
71
|
<Layout>
|
|
58
|
-
<Layout.DocsHeader />
|
|
72
|
+
<Layout.DocsHeader transformedOpenApis={transformedOpenApis} updateFilteredData={updateFilteredData}/>
|
|
59
73
|
<Layout.DocsSideMenuTree
|
|
60
74
|
apis={transformedOpenApis}
|
|
61
75
|
setActiveItemData={setActiveItemData}
|
|
76
|
+
activeItemData={activeItemData}
|
|
77
|
+
expandedSections={expandedSections}
|
|
78
|
+
setExpandedSections={setExpandedSections}
|
|
62
79
|
isFirstApiExpanded={isFirstApiExpanded}
|
|
80
|
+
activeType={activeType}
|
|
63
81
|
setIsFirstApiExpanded={setIsFirstApiExpanded}
|
|
64
82
|
setActiveType={setActiveType}
|
|
65
83
|
/>
|
|
66
|
-
{!pending &&
|
|
67
|
-
|
|
84
|
+
{!pending && Object.keys(activeItemData).length > 0 && (
|
|
85
|
+
<Layout.DocsContent
|
|
86
|
+
data={activeItemData}
|
|
87
|
+
activeType={activeType}
|
|
88
|
+
setActiveItemData={setActiveItemData}
|
|
89
|
+
setActiveType={setActiveType}
|
|
90
|
+
setExpandedSections={setExpandedSections}
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
93
|
+
{activeType === 'ENDPOINT' && <Layout.DocsAside data={activeItemData as EndpointData} />}
|
|
68
94
|
</Layout>
|
|
69
95
|
)
|
|
70
96
|
}
|
package/src/layout/layout.tsx
CHANGED
|
@@ -20,25 +20,34 @@ interface ILayoutProps {
|
|
|
20
20
|
openApiErrors?: any
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const Layout = ({
|
|
23
|
+
const Layout = ({
|
|
24
|
+
openApiJson,
|
|
25
|
+
handleSave,
|
|
26
|
+
setIsFormDirty,
|
|
27
|
+
openApiErrors,
|
|
28
|
+
}: ILayoutProps): JSX.Element => {
|
|
24
29
|
const clonedOpenApiJson = structuredClone(openApiJson)
|
|
25
30
|
const transformedOpenApi = transformOpenApiObject(clonedOpenApiJson)
|
|
26
31
|
const formik = useFormik<TransformedOpenApi>({
|
|
27
32
|
initialValues: structuredClone(transformedOpenApi),
|
|
28
33
|
validationSchema: schemaValidation,
|
|
29
34
|
validateOnMount: true,
|
|
30
|
-
onSubmit: (values, { validateForm, resetForm }) => {
|
|
35
|
+
onSubmit: (values, { validateForm, resetForm, setSubmitting }) => {
|
|
31
36
|
// Handle save logic
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
try {
|
|
38
|
+
const originalOpenApiForm = transformOpenApiObjectToOrigin(values)
|
|
39
|
+
handleSave(originalOpenApiForm)
|
|
40
|
+
resetForm({
|
|
41
|
+
values: values, // You can reset it to the same values if you want
|
|
42
|
+
})
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
validateForm(values)
|
|
45
|
+
} catch (err) {
|
|
46
|
+
setSubmitting(false)
|
|
47
|
+
}
|
|
39
48
|
},
|
|
40
49
|
})
|
|
41
|
-
const { dirty, isValid, isSubmitting, values, setFieldValue, handleSubmit } = formik
|
|
50
|
+
const { dirty, isValid, isSubmitting, values, setFieldValue, handleSubmit, errors } = formik
|
|
42
51
|
const [isPublishDialogOpen, setIsPublishDialogOpen] = useState(false)
|
|
43
52
|
const [openMethodIndex, setOpenMethodIndex] = useState<number | null>(null)
|
|
44
53
|
|
|
@@ -48,6 +57,11 @@ const Layout = ({ openApiJson, handleSave, setIsFormDirty, openApiErrors }: ILay
|
|
|
48
57
|
}
|
|
49
58
|
}, [dirty])
|
|
50
59
|
|
|
60
|
+
// keep it here until production
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
console.log({ values, errors })
|
|
63
|
+
}, [values])
|
|
64
|
+
|
|
51
65
|
return (
|
|
52
66
|
<div className={styles.docsLayout}>
|
|
53
67
|
{dirty && (
|
|
@@ -109,7 +123,7 @@ const Layout = ({ openApiJson, handleSave, setIsFormDirty, openApiErrors }: ILay
|
|
|
109
123
|
<div className={`${styles.livePreviewSide} ${styles.docSide}`}>
|
|
110
124
|
{transformedOpenApi && (
|
|
111
125
|
<FormikProvider value={formik}>
|
|
112
|
-
<LivePreview transformedData={transformedOpenApi} openApiErrors={openApiErrors}/>
|
|
126
|
+
<LivePreview transformedData={transformedOpenApi} openApiErrors={openApiErrors} />
|
|
113
127
|
</FormikProvider>
|
|
114
128
|
)}
|
|
115
129
|
</div>
|
|
@@ -118,14 +132,18 @@ const Layout = ({ openApiJson, handleSave, setIsFormDirty, openApiErrors }: ILay
|
|
|
118
132
|
status="warning"
|
|
119
133
|
content={
|
|
120
134
|
<>
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
135
|
+
<h5
|
|
136
|
+
style={{
|
|
137
|
+
fontWeight: 600,
|
|
138
|
+
fontSize: '1.5rem',
|
|
139
|
+
lineHeight: '1.875rem',
|
|
140
|
+
color: '#FAAD14',
|
|
141
|
+
textAlign: 'center',
|
|
142
|
+
margin: 0,
|
|
143
|
+
}}
|
|
144
|
+
>
|
|
145
|
+
Publish Changes
|
|
146
|
+
</h5>
|
|
129
147
|
<p
|
|
130
148
|
style={{
|
|
131
149
|
textAlign: 'center',
|
package/src/types/index.ts
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { OpenAPIFile } from './openApi'
|
|
2
|
+
|
|
3
|
+
export interface ApiSpecModel {
|
|
4
|
+
apiSpecId: string
|
|
5
|
+
contextPath: string
|
|
6
|
+
apiVersions: {
|
|
7
|
+
addVersionToContextPath: boolean
|
|
8
|
+
apiSpecId: string
|
|
9
|
+
name: string
|
|
10
|
+
metaData: {
|
|
11
|
+
version: string
|
|
12
|
+
}
|
|
13
|
+
}[]
|
|
14
|
+
associatedProduct: {
|
|
15
|
+
availableOnDevPortal: boolean
|
|
16
|
+
name: string
|
|
17
|
+
premium: boolean
|
|
18
|
+
productId: number
|
|
19
|
+
}
|
|
20
|
+
metaData: {
|
|
21
|
+
version: string
|
|
22
|
+
apiVersionOf: string
|
|
23
|
+
openApiJson: OpenAPIFile
|
|
24
|
+
tags: string[]
|
|
25
|
+
createdDateTime: string
|
|
26
|
+
lastUpdatedDateTime: string
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/types/layout.type.ts
CHANGED
package/src/types/openApi.ts
CHANGED
|
@@ -11,7 +11,14 @@ export const schemaValidation = yup.object({
|
|
|
11
11
|
servers: yup
|
|
12
12
|
.array(
|
|
13
13
|
yup.object({
|
|
14
|
-
url: yup
|
|
14
|
+
url: yup
|
|
15
|
+
.string()
|
|
16
|
+
.required()
|
|
17
|
+
.test(
|
|
18
|
+
'is-url-or-slash',
|
|
19
|
+
'Must be a valid URL or "/"',
|
|
20
|
+
(value) => value === '/' || yup.string().url().isValidSync(value)
|
|
21
|
+
),
|
|
15
22
|
description: yup.string().optional(),
|
|
16
23
|
})
|
|
17
24
|
)
|
|
@@ -29,6 +36,7 @@ export const schemaValidation = yup.object({
|
|
|
29
36
|
description: yup.string().trim().optional(),
|
|
30
37
|
type: yup.string().optional(),
|
|
31
38
|
tags: yup.array().of(yup.string()).optional(),
|
|
39
|
+
requestBody: yup.mixed().optional(),
|
|
32
40
|
})
|
|
33
41
|
)
|
|
34
42
|
.required(),
|