@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.
Files changed (60) hide show
  1. package/dist/_virtual/index3.js +1 -1
  2. package/dist/_virtual/index4.js +1 -1
  3. package/dist/_virtual/index5.js +1 -1
  4. package/dist/_virtual/index6.js +1 -1
  5. package/dist/node_modules/toposort/index.js +1 -1
  6. package/dist/node_modules/yup/index.esm.js +1 -1
  7. package/dist/src/components/MethodAccordion/MethodAccordion.js +1 -1
  8. package/dist/src/components/MethodAccordion/MethodAccordion.js.map +1 -1
  9. package/dist/src/helpers/docs.helper.js +1 -1
  10. package/dist/src/helpers/docs.helper.js.map +1 -1
  11. package/dist/src/helpers/layout.helper.js +1 -1
  12. package/dist/src/helpers/layout.helper.js.map +1 -1
  13. package/dist/src/layout/docsComponents/DocsAside/DocsAside.js +1 -1
  14. package/dist/src/layout/docsComponents/DocsAside/DocsAside.js.map +1 -1
  15. package/dist/src/layout/docsComponents/DocsContent/DocsContent.js +1 -1
  16. package/dist/src/layout/docsComponents/DocsContent/DocsContent.js.map +1 -1
  17. package/dist/src/layout/docsComponents/DocsContent/EndpointPage/index.js +1 -1
  18. package/dist/src/layout/docsComponents/DocsContent/EndpointPage/index.js.map +1 -1
  19. package/dist/src/layout/docsComponents/DocsContent/TagPage/index.js +1 -1
  20. package/dist/src/layout/docsComponents/DocsContent/TagPage/index.js.map +1 -1
  21. package/dist/src/layout/docsComponents/DocsHeader/DocsHeader.js +1 -1
  22. package/dist/src/layout/docsComponents/DocsHeader/DocsHeader.js.map +1 -1
  23. package/dist/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.js +1 -1
  24. package/dist/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.js.map +1 -1
  25. package/dist/src/layout/docsLayout.js +1 -1
  26. package/dist/src/layout/docsLayout.js.map +1 -1
  27. package/dist/src/layout/layout.js +1 -1
  28. package/dist/src/layout/layout.js.map +1 -1
  29. package/dist/src/layout/layout.module.css.js +1 -1
  30. package/dist/src/validator/form.scheme.js +1 -1
  31. package/dist/src/validator/form.scheme.js.map +1 -1
  32. package/dist/styles.css +638 -596
  33. package/dist/types/helpers/docs.helper.d.ts +2 -2
  34. package/dist/types/layout/docsComponents/DocsContent/DocsContent.d.ts +2 -1
  35. package/dist/types/layout/docsComponents/DocsContent/TagPage/index.d.ts +4 -1
  36. package/dist/types/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.d.ts +12 -6
  37. package/dist/types/layout/docsLayout.d.ts +5 -4
  38. package/dist/types/layout/layout.d.ts +1 -1
  39. package/dist/types/types/index.d.ts +27 -0
  40. package/dist/types/types/layout.type.d.ts +1 -0
  41. package/dist/types/types/openApi.d.ts +1 -0
  42. package/dist/types/validator/form.scheme.d.ts +1 -0
  43. package/package.json +1 -2
  44. package/src/components/MethodAccordion/MethodAccordion.tsx +372 -4
  45. package/src/helpers/docs.helper.ts +17 -4
  46. package/src/helpers/layout.helper.ts +19 -2
  47. package/src/layout/docsComponents/DocsAside/DocsAside.tsx +6 -7
  48. package/src/layout/docsComponents/DocsContent/DocsContent.tsx +24 -3
  49. package/src/layout/docsComponents/DocsContent/EndpointPage/index.tsx +132 -121
  50. package/src/layout/docsComponents/DocsContent/EndpointPage/style.scss +45 -0
  51. package/src/layout/docsComponents/DocsContent/TagPage/index.tsx +49 -17
  52. package/src/layout/docsComponents/DocsHeader/DocsHeader.tsx +34 -1
  53. package/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.tsx +106 -79
  54. package/src/layout/docsLayout.tsx +43 -17
  55. package/src/layout/layout.module.css +1 -1
  56. package/src/layout/layout.tsx +36 -18
  57. package/src/types/index.ts +28 -0
  58. package/src/types/layout.type.ts +1 -0
  59. package/src/types/openApi.ts +1 -0
  60. 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
- const [expandedSections, setExpandedSections] = useState({})
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
- else if (expandKey === sectionId) return true
54
+ if (expandKey === sectionId) return true
24
55
  // filter all sections containing the key
25
- else if (key.some((k) => expandKey.includes(k))) return false
26
- else return true
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
- return endpoints.map((endpoint, index) => {
44
- const isResourceExpanded = expandedSections[`api-${api.id}-resource-${endpoint.id}`]
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 (!isResourceExpanded) {
83
+ if (!isExpanded) {
52
84
  setActiveItemData({
53
85
  ...endpoint,
54
86
  api: {
55
- id: api.id,
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.id, `api-${api.id}-resource-${endpoint.id}`, true, [
63
- 'resource',
64
- 'overview',
65
- ])
95
+ toggleSection(api.apiSpecId, key, true, ['resource', 'overview'])
66
96
  }
67
97
  }}
68
- data-active={isResourceExpanded}
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 renderApiSection = (api, index) => {
78
- const isApiExpanded = expandedSections[`api-${api.id}-section`]
79
- const isEndpointActive = Object.keys(expandedSections).some((k) =>
80
- k.includes(`api-${api.id}-resource`)
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
- const isEndpointsExpanded = expandedSections[`api-${api.id}-endpoints`]
83
- const isOverviewExpanded = expandedSections[`api-${api.id}-overview`]
84
-
85
- if (isFirstApiExpanded && index === 0 && !isApiExpanded) {
86
- toggleSection(api.id, `api-${api.id}-section`)
87
- toggleSection(api.id, `api-${api.id}-overview`)
88
- setActiveItemData(api)
89
- setActiveType('OVERVIEW')
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.id}
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.id, `api-${api.id}-section`)}
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={`api-docs-api-tree__section__overview`}
170
+ className="api-docs-api-tree__section__overview"
111
171
  onClick={() => {
112
172
  if (!isOverviewExpanded) {
113
- toggleSection(api.id, `api-${api.id}-overview`, true, ['resource'])
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
- {<SVGLoader src={eye} />}
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
- {isEndpointsExpanded ? (
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
- {isEndpointsExpanded && (
196
+
197
+ {expandedSections[endpointsKey] && (
138
198
  <div className="api-docs-api-tree__subsections">
139
199
  {Object.entries(api.tags)
140
- .sort(([a], [b]) => {
141
- if (a === 'default') return 1
142
- if (b === 'default') return -1
143
- return a.localeCompare(b)
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
- const renderSubSection = (tagName, data, api, sectionIndex) => {
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
- openApiJson?: OpenAPIFile[]
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 = ({ openApiJson }: ILayoutProps): JSX.Element => {
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
- setTransformedOpenApis(
48
- structuredClone(openApiJson)
49
- ?.map((o3) => transformOpenApiToDocs(o3))
50
- .sort((a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase()))
51
- )
52
- setPending(false)
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
- }, [openApiJson])
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 && <Layout.DocsContent data={activeItemData} />}
67
- {activeType === 'ENDPOINT' && <Layout.DocsAside data={activeItemData} />}
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
  }
@@ -25,7 +25,7 @@
25
25
  .editorSectionHead_title {
26
26
  position: sticky;
27
27
  top: 0;
28
- z-index: 99999 !important;
28
+ z-index: 1399 !important;
29
29
  }
30
30
  .editorSectionHead,
31
31
  .editorSectionHead_title {
@@ -20,25 +20,34 @@ interface ILayoutProps {
20
20
  openApiErrors?: any
21
21
  }
22
22
 
23
- const Layout = ({ openApiJson, handleSave, setIsFormDirty, openApiErrors }: ILayoutProps): JSX.Element => {
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
- const originalOpenApiForm = transformOpenApiObjectToOrigin(values)
33
- handleSave(originalOpenApiForm)
34
- resetForm({
35
- values: values, // You can reset it to the same values if you want
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
- validateForm(values)
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
- <h5 style={{
122
- fontWeight: 600,
123
- fontSize: '1.5rem',
124
- lineHeight: '1.875rem',
125
- color: '#FAAD14',
126
- textAlign: 'center',
127
- margin: 0
128
- }}>Publish Changes</h5>
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',
@@ -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
+ }
@@ -20,6 +20,7 @@ export type TransformedMethod = {
20
20
  contentType?: string
21
21
  schema?: unknown
22
22
  }
23
+ headers: any
23
24
  }[]
24
25
  }
25
26
 
@@ -75,6 +75,7 @@ export interface RequestBody {
75
75
  export interface Responses {
76
76
  [statusCode: string]: {
77
77
  description: string
78
+ headers?: any
78
79
  content?: {
79
80
  [contentType: string]: {
80
81
  schema: Schema
@@ -11,7 +11,14 @@ export const schemaValidation = yup.object({
11
11
  servers: yup
12
12
  .array(
13
13
  yup.object({
14
- url: yup.string().url().required(),
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(),