@digi-frontend/dgate-api-documentation 1.0.18 → 1.0.21

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 (30) 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/InfoForm/InfoForm.js +1 -1
  8. package/dist/src/components/InfoForm/InfoForm.js.map +1 -1
  9. package/dist/src/components/LivePreview/LivePreview.js +1 -1
  10. package/dist/src/components/LivePreview/LivePreview.js.map +1 -1
  11. package/dist/src/components/MethodAccordion/MethodAccordion.js +1 -1
  12. package/dist/src/components/MethodAccordion/MethodAccordion.js.map +1 -1
  13. package/dist/src/components/table/table.js +1 -1
  14. package/dist/src/components/table/table.js.map +1 -1
  15. package/dist/src/components/table/tags-table.js +1 -1
  16. package/dist/src/components/table/tags-table.js.map +1 -1
  17. package/dist/src/layout/layout.js +1 -1
  18. package/dist/src/layout/layout.js.map +1 -1
  19. package/dist/styles.css +298 -280
  20. package/dist/types/components/MethodAccordion/MethodAccordion.d.ts +4 -3
  21. package/dist/types/layout/layout.d.ts +2 -1
  22. package/package.json +2 -2
  23. package/src/components/InfoForm/InfoForm.module.scss +13 -0
  24. package/src/components/InfoForm/InfoForm.tsx +32 -18
  25. package/src/components/LivePreview/LivePreview.tsx +29 -6
  26. package/src/components/MethodAccordion/MethodAccordion.module.scss +13 -0
  27. package/src/components/MethodAccordion/MethodAccordion.tsx +60 -18
  28. package/src/components/table/table.tsx +1 -0
  29. package/src/components/table/tags-table.tsx +2 -2
  30. package/src/layout/layout.tsx +15 -3
@@ -30,18 +30,21 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
30
30
  if (values && values.components && values.components.securitySchemes) {
31
31
  const authenticatorKeys = Object.keys(values.components.securitySchemes)
32
32
  if (authenticatorKeys.length) {
33
- setAuthType(values.components.securitySchemes[authenticatorKeys[0]].scheme)
33
+ setAuthType(
34
+ values.components.securitySchemes[authenticatorKeys[0]].scheme ||
35
+ values.components.securitySchemes[authenticatorKeys[0]].type
36
+ )
34
37
  }
35
38
  }
36
39
  }, [])
37
40
 
38
41
  useEffect(() => {
39
- setTableRecords(generateTableData(tableData))
42
+ setTableRecords(generateTableRecords(tableData))
40
43
  }, [tableData])
41
44
 
42
45
  useEffect(() => {
43
46
  if (values.tags && values.tags.length) {
44
- setTableRecords(generateTableData(values.tags))
47
+ setTableRecords(generateTableRecords(values.tags))
45
48
  setTableData(values.tags)
46
49
  }
47
50
  }, [values.tags])
@@ -77,7 +80,7 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
77
80
 
78
81
  const saveNewRow = (tag) => {
79
82
  setTableData([...tableData, tag])
80
- const oldTags = values.tags || [];
83
+ const oldTags = values.tags || []
81
84
  setFieldValue(`tags`, [...oldTags, tag])
82
85
  }
83
86
 
@@ -88,7 +91,7 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
88
91
  setOpenDeleteDialog(true)
89
92
  }
90
93
 
91
- const generateTableData = (items) => {
94
+ const generateTableRecords = (items) => {
92
95
  return items.map((item, index) => ({
93
96
  id: index,
94
97
  tagName: item.name,
@@ -131,10 +134,19 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
131
134
  </div>
132
135
  }
133
136
  >
134
- {readOnly ? (
135
- <Button className={styles.editDescBtn} variant="link" color="action">
136
- {item.description ? item.description.substring(0, 12) : '-'}
137
- {item.description && item.description.length > 12 ? '...' : ''}
137
+ {readOnly || values.tags[index].description ? (
138
+ <Button
139
+ className={styles.editDescBtn}
140
+ variant="link"
141
+ color="action"
142
+ endIcon={<SVGLoader src={EditIcon} width="1.5rem" height="1.5rem" />}
143
+ >
144
+ {values.tags[index].description
145
+ ? values.tags[index].description.substring(0, 12)
146
+ : '-'}
147
+ {values.tags[index].description && values.tags[index].description.length > 12
148
+ ? '...'
149
+ : ''}
138
150
  </Button>
139
151
  ) : (
140
152
  <Button
@@ -143,7 +155,9 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
143
155
  color="action"
144
156
  endIcon={<SVGLoader src={EditIcon} width="1.5rem" height="1.5rem" />}
145
157
  >
146
- {readOnly || item.description ? 'View Description' : 'Add Description'}
158
+ {readOnly || values.tags[index].description
159
+ ? 'View Description'
160
+ : 'Add Description'}
147
161
  </Button>
148
162
  )}
149
163
  </Tooltip>
@@ -210,22 +224,22 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
210
224
  </div>
211
225
  }
212
226
  >
213
- {readOnly ? (
227
+ {readOnly || values.tags[index].externalDocs?.description ? (
214
228
  <Button
215
229
  className={styles.editDescBtn}
216
230
  variant="link"
217
231
  color="action"
232
+ endIcon={<SVGLoader src={EditIcon} width="1.5rem" height="1.5rem" />}
218
233
  onClick={() => {
219
- const a = document.createElement('a')
220
- a.href = item.externalDocs?.url
221
- a.target="_blank"
222
- a.click()
234
+ setDescription(item.externalDocs?.description)
235
+ setURL(item.externalDocs?.url)
223
236
  }}
224
237
  >
225
- {item?.externalDocs?.description
226
- ? item?.externalDocs?.description?.substring(0, 12)
238
+ {values.tags[index].externalDocs?.description
239
+ ? values.tags[index].externalDocs?.description?.substring(0, 12)
227
240
  : '-'}
228
- {item?.externalDocs?.description && item?.externalDocs?.description?.length > 12
241
+ {values.tags[index].externalDocs?.description &&
242
+ values.tags[index].externalDocs?.description?.length > 12
229
243
  ? '...'
230
244
  : ''}
231
245
  </Button>
@@ -1,7 +1,6 @@
1
1
  import React, { useEffect, useState } from 'react'
2
2
  import styles from './LivePreview.module.scss'
3
3
  import SimpleLabelValue from '../../components/SimpleLabelValue'
4
-
5
4
  import MethodsAccordion from '../../components/MethodAccordion/MethodAccordion'
6
5
  import { TransformedOpenApi } from '../../types/transformedOpenApi'
7
6
  import { useFormikContext } from 'formik'
@@ -122,12 +121,36 @@ const LivePreview: React.FC<LivePreviewProps> = ({ transformedData }) => {
122
121
 
123
122
  <SimpleLabelValue key={'endpoints'} label={'Endpoints '} />
124
123
  {values.paths.map((path) => (
125
- <div className={styles.methodsContainer}>
126
- {path.methods
124
+ <div className={styles.methodsContainer} key={path.path}>
125
+ {Object.entries(
126
+ path.methods
127
127
  .sort((a, b) => methodColorMapping[a.type].order + methodColorMapping[b.type].order)
128
- .map((method, methodIndex) => (
129
- <MethodsAccordion readOnly method={method} path={path.path} />
130
- ))}
128
+ .reduce((groupedMethods, method) => {
129
+ // Handle methods without tags
130
+ const tags = method.tags?.length ? method?.tags : ['default'];
131
+
132
+ tags.forEach((tag) => {
133
+ if (!groupedMethods[tag]) {
134
+ groupedMethods[tag] = [];
135
+ }
136
+ groupedMethods[tag].push(method);
137
+ });
138
+
139
+ return groupedMethods;
140
+ }, {})
141
+ ).map(([tag, methods]) => (
142
+ <div key={tag}>
143
+ <h3>{tag}</h3>
144
+ {methods?.map((method, methodIndex) => (
145
+ <MethodsAccordion
146
+ readOnly
147
+ method={method}
148
+ path={path.path}
149
+ tags={values.tags}
150
+ />
151
+ ))}
152
+ </div>
153
+ ))}
131
154
  </div>
132
155
  ))}
133
156
  </div>
@@ -134,6 +134,19 @@
134
134
  }
135
135
  }
136
136
  }
137
+
138
+ &:not(:global(.disabled)):global(.success) {
139
+ :global(.endBtnIcon) {
140
+ margin-block: auto;
141
+
142
+ svg {
143
+ width: 1.125rem;
144
+ path {
145
+ fill: #3aaa35;
146
+ }
147
+ }
148
+ }
149
+ }
137
150
  }
138
151
  }
139
152
  }
@@ -1,13 +1,7 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { Accordion, Button, SelectGroup, Switch, TextArea } from 'digitinary-ui'
1
+ import { useEffect, useState } from 'react'
2
+ import { Accordion, Button, SelectGroup, SelectGroupV2, Switch, TextArea } from 'digitinary-ui'
3
3
  import SVGLoader from '../../components/SVGLoader/SVGLoader'
4
- import {
5
- CheckMarkSquare,
6
- DeleteIcon,
7
- DownArrowIcon,
8
- EditIcon,
9
- deleteOutlinedIcon,
10
- } from '../../assets/icons'
4
+ import { DeleteIcon, DownArrowIcon, EditIcon, deleteOutlinedIcon } from '../../assets/icons'
11
5
  import { httpStatusCodes, methodColorMapping, paramsTableHeaders } from '../../constants/index'
12
6
  import Tooltip from '../../components/Tooltip/Tooltip'
13
7
  import { TransformedMethod } from '../../types/layout.type'
@@ -17,6 +11,7 @@ import ParamterTable from '../table/table'
17
11
  import CommonDialog from '../../components/dialog'
18
12
  import JsonInput from '../../components/JsonInput/JsonInput'
19
13
  import styles from './MethodAccordion.module.scss'
14
+ import { Tags } from '@entities/openApi'
20
15
 
21
16
  const httpStatusCodeOptions = httpStatusCodes.map((code) => ({
22
17
  label: (
@@ -36,12 +31,13 @@ const MethodsAccordion = ({
36
31
  path,
37
32
  setFieldValue,
38
33
  readOnly,
34
+ tags,
39
35
  }: {
40
36
  method: TransformedMethod
41
37
  path: string
42
- setFieldValue?: (key: string, value: string) => void
38
+ setFieldValue?: (key: string, value: string | string[]) => void
43
39
  readOnly?: boolean
44
- handleSave: () => void
40
+ tags: Tags[]
45
41
  }) => {
46
42
  const [isExpanded, setIsExpanded] = useState({
47
43
  request: false,
@@ -55,7 +51,7 @@ const MethodsAccordion = ({
55
51
  const [selectedParamIndex, setSelectedParamIndex] = useState<number | null>(null)
56
52
  const [selectedParamName, setSelectedParamName] = useState<string | null>(null)
57
53
  const [tableRecords, setTableRecords] = useState()
58
-
54
+ const [selectionTags, setSelectionTags] = useState([])
59
55
  const [selectedStatusCode, setSelectedStatusCode] = useState(httpStatusCodeOptions[4])
60
56
  const currentResponse =
61
57
  method.responses.find((res) => Number(res.code) === selectedStatusCode.value) || '{}'
@@ -140,15 +136,20 @@ const MethodsAccordion = ({
140
136
  </div>
141
137
  }
142
138
  >
143
- {readOnly ? (
139
+ {readOnly || method.parameters[index].description?.length > 0 ? (
144
140
  <Button
145
141
  className={styles.editDescBtn}
146
142
  variant="link"
147
143
  color="action"
148
- // endIcon={<SVGLoader src={EditIcon} width="1.5rem" height="1.5rem" />}
144
+ endIcon={<SVGLoader src={EditIcon} width="1.5rem" height="1.5rem" />}
149
145
  >
150
- {item.description ? item.description.substring(0, 12) : '-'}
151
- {item.description && item.description.length > 12 ? '...' : ''}
146
+ {method.parameters[index].description
147
+ ? method.parameters[index].description.substring(0, 12)
148
+ : '-'}
149
+ {method.parameters[index].description &&
150
+ method.parameters[index].description.length > 12
151
+ ? '...'
152
+ : ''}
152
153
  </Button>
153
154
  ) : (
154
155
  <Button
@@ -214,6 +215,25 @@ const MethodsAccordion = ({
214
215
  }
215
216
  }, [method, path])
216
217
 
218
+ useEffect(() => {
219
+ // prepare tags selection list
220
+ if (!selectionTags.length) {
221
+ const convertedStringArray = (method?.tags || [])?.map((item) => ({
222
+ label: capitalize(item),
223
+ value: item,
224
+ }))
225
+ const mergedArray = [
226
+ ...convertedStringArray,
227
+ ...(tags || []).map((item) => ({ label: capitalize(item.name), value: item.name })),
228
+ ]
229
+
230
+ const filteredArray = mergedArray.filter(
231
+ (value, index, self) => index === self.findIndex((t) => t.value === value.value)
232
+ )
233
+ setSelectionTags(filteredArray)
234
+ }
235
+ }, [tags, method])
236
+
217
237
  return (
218
238
  <div>
219
239
  <Accordion
@@ -244,6 +264,30 @@ const MethodsAccordion = ({
244
264
  }
245
265
  children={
246
266
  <div className={styles.methodAccordionContent}>
267
+ <SelectGroup
268
+ className={styles.methodDesc}
269
+ disabled={readOnly}
270
+ placeholder="Select Tags"
271
+ label="Tags"
272
+ value={method.tags?.map((t) => ({
273
+ label: capitalize(t),
274
+ value: t,
275
+ }))}
276
+ onChange={(item) => {
277
+ setFieldValue(
278
+ 'tags',
279
+ item.map((i) => i.value)
280
+ )
281
+ }}
282
+ options={[
283
+ {
284
+ list: selectionTags,
285
+ },
286
+ ]}
287
+ isMultiple={true}
288
+ withSearch={false}
289
+ clearable={false}
290
+ />
247
291
  {!readOnly ? (
248
292
  <TextArea
249
293
  className={styles.methodDesc}
@@ -270,7 +314,6 @@ const MethodsAccordion = ({
270
314
  readOnly={readOnly}
271
315
  />
272
316
  </div>
273
-
274
317
  {method?.type !== 'get' && (
275
318
  <Accordion
276
319
  expanded={isExpanded.request}
@@ -313,7 +356,6 @@ const MethodsAccordion = ({
313
356
  }
314
357
  />
315
358
  )}
316
-
317
359
  <Accordion
318
360
  expanded={isExpanded.response}
319
361
  onChange={() => null}
@@ -21,6 +21,7 @@ const ParamterTable = ({
21
21
  const [text, setText] = useState('')
22
22
  const [tooltipRef, setTooltipRef] = useState(null)
23
23
  const { values, errors, setFieldValue, isValid, submitForm, resetForm } = useFormik({
24
+ validateOnMount: true,
24
25
  initialValues: {
25
26
  name: '',
26
27
  in: 'Query',
@@ -16,6 +16,7 @@ const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow,
16
16
  const [tooltipRef, setTooltipRef] = useState(null)
17
17
  const [externalTooltipRefs, setExternalTooltipRefs] = useState(null)
18
18
  const { values, errors, setFieldValue, isValid, submitForm, resetForm } = useFormik({
19
+ validateOnMount: true,
19
20
  initialValues: {
20
21
  name: '',
21
22
  description: '',
@@ -221,8 +222,7 @@ const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow,
221
222
  variant="link"
222
223
  color="action"
223
224
  href={values.externalDocs?.url}
224
- target='_blank'
225
-
225
+ target="_blank"
226
226
  >
227
227
  {values?.externalDocs?.description
228
228
  ? values?.externalDocs?.description?.substring(0, 12)
@@ -1,4 +1,4 @@
1
- import { JSX } from 'react'
1
+ import { JSX, useEffect } from 'react'
2
2
  import { Alert, Button } from 'digitinary-ui'
3
3
  import MethodsAccordion from '../components/MethodAccordion/MethodAccordion'
4
4
  import styles from './layout.module.css'
@@ -15,23 +15,34 @@ import { methodColorMapping } from '../constants/index'
15
15
  interface ILayoutProps {
16
16
  openApiJson?: OpenAPIFile
17
17
  handleSave?: (values: unknown) => unknown
18
+ setIsFormDirty?: any
18
19
  }
19
20
 
20
- const Layout = ({ openApiJson, handleSave }: ILayoutProps): JSX.Element => {
21
+ const Layout = ({ openApiJson, handleSave, setIsFormDirty }: ILayoutProps): JSX.Element => {
21
22
  const clonedOpenApiJson = structuredClone(openApiJson)
22
23
  const transformedOpenApi = transformOpenApiObject(clonedOpenApiJson)
23
24
  const formik = useFormik<TransformedOpenApi>({
24
25
  initialValues: structuredClone(transformedOpenApi),
25
26
  validationSchema: schemaValidation,
26
27
  validateOnMount: true,
27
- onSubmit: (values, { validateForm }) => {
28
+ onSubmit: (values, { validateForm, resetForm }) => {
28
29
  // Handle save logic
29
30
  const originalOpenApiForm = transformOpenApiObjectToOrigin(values)
30
31
  handleSave(originalOpenApiForm)
32
+ resetForm({
33
+ values: values, // You can reset it to the same values if you want
34
+ })
35
+
31
36
  validateForm(values)
32
37
  },
33
38
  })
34
39
 
40
+ useEffect(() => {
41
+ if (setIsFormDirty) {
42
+ setIsFormDirty(formik.dirty)
43
+ }
44
+ }, [formik.dirty])
45
+
35
46
  return (
36
47
  <div className={styles.docsLayout}>
37
48
  <Alert className={styles.apiDocAlert} color="info">
@@ -72,6 +83,7 @@ const Layout = ({ openApiJson, handleSave }: ILayoutProps): JSX.Element => {
72
83
  )
73
84
  .map((method, methodIndex) => (
74
85
  <MethodsAccordion
86
+ tags={formik.values.tags}
75
87
  method={method}
76
88
  path={path.path}
77
89
  setFieldValue={(key, value) => {