@digi-frontend/dgate-api-documentation 1.0.21 → 1.0.25
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/src/components/InfoForm/InfoForm.js +1 -1
- package/dist/src/components/InfoForm/InfoForm.js.map +1 -1
- package/dist/src/components/JsonInput/JsonInput.js +1 -1
- package/dist/src/components/JsonInput/JsonInput.js.map +1 -1
- package/dist/src/components/LivePreview/LivePreview.js +1 -1
- package/dist/src/components/LivePreview/LivePreview.js.map +1 -1
- package/dist/src/components/MethodAccordion/MethodAccordion.js +1 -1
- package/dist/src/components/MethodAccordion/MethodAccordion.js.map +1 -1
- package/dist/src/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/src/components/table/table.js +1 -1
- package/dist/src/components/table/table.js.map +1 -1
- package/dist/src/components/table/tags-table.js +1 -1
- package/dist/src/components/table/tags-table.js.map +1 -1
- package/dist/src/constants/regex.js +1 -1
- package/dist/src/constants/regex.js.map +1 -1
- package/dist/src/layout/layout.js +1 -1
- package/dist/src/layout/layout.js.map +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 +473 -473
- package/dist/types/components/Tooltip/Tooltip.d.ts +2 -2
- package/dist/types/constants/regex.d.ts +1 -0
- package/dist/types/validator/form.scheme.d.ts +1 -1
- package/package.json +2 -2
- package/src/components/InfoForm/InfoForm.tsx +33 -14
- package/src/components/JsonInput/JsonInput.tsx +7 -1
- package/src/components/LivePreview/LivePreview.tsx +40 -21
- package/src/components/MethodAccordion/MethodAccordion.tsx +36 -14
- package/src/components/Tooltip/Tooltip.scss +3 -3
- package/src/components/Tooltip/Tooltip.tsx +2 -3
- package/src/components/table/table.tsx +3 -1
- package/src/components/table/tags-table.tsx +27 -5
- package/src/constants/regex.ts +1 -0
- package/src/layout/layout.tsx +41 -6
- package/src/validator/form.scheme.ts +9 -9
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
|
+
import { TippyProps } from '@tippyjs/react';
|
|
2
3
|
import 'tippy.js/dist/tippy.css';
|
|
3
4
|
import './Tooltip.scss';
|
|
4
|
-
interface TooltipProps {
|
|
5
|
-
children: ReactNode;
|
|
5
|
+
interface TooltipProps extends TippyProps {
|
|
6
6
|
content: ReactNode;
|
|
7
7
|
success?: boolean;
|
|
8
8
|
onMouseEnter?: (event: React.MouseEvent<HTMLDivElement>) => void;
|
package/package.json
CHANGED
|
@@ -97,6 +97,26 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
|
|
|
97
97
|
tagName: item.name,
|
|
98
98
|
description: (
|
|
99
99
|
<div className={styles.paramDescContainer}>
|
|
100
|
+
<Tooltip
|
|
101
|
+
key={`${index}-description`}
|
|
102
|
+
allowHTML
|
|
103
|
+
disabled={values.tags[index].description?.length <= 12}
|
|
104
|
+
content={<div style={{ padding: '0.625rem' }}>{values.tags[index].description}</div>}
|
|
105
|
+
arrowWithBorder
|
|
106
|
+
placement="bottom-end"
|
|
107
|
+
type="function"
|
|
108
|
+
delay={[0, 0]}
|
|
109
|
+
onShow={() => tooltipRefs[index]?.hide()}
|
|
110
|
+
>
|
|
111
|
+
<p style={{ alignSelf: 'center', fontWeight: 600, fontSize: '1rem' }}>
|
|
112
|
+
{values.tags[index].description
|
|
113
|
+
? values.tags[index].description.substring(0, 12)
|
|
114
|
+
: readOnly && '-'}
|
|
115
|
+
{values.tags[index].description && values.tags[index].description.length > 12
|
|
116
|
+
? '...'
|
|
117
|
+
: ''}
|
|
118
|
+
</p>
|
|
119
|
+
</Tooltip>
|
|
100
120
|
<Tooltip
|
|
101
121
|
arrowWithBorder
|
|
102
122
|
placement="bottom-end"
|
|
@@ -140,14 +160,7 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
|
|
|
140
160
|
variant="link"
|
|
141
161
|
color="action"
|
|
142
162
|
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
|
-
: ''}
|
|
150
|
-
</Button>
|
|
163
|
+
></Button>
|
|
151
164
|
) : (
|
|
152
165
|
<Button
|
|
153
166
|
className={styles.editDescBtn}
|
|
@@ -295,7 +308,7 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
|
|
|
295
308
|
setFieldValue('info.title', '')
|
|
296
309
|
}}
|
|
297
310
|
errorMsg={errors?.info?.title}
|
|
298
|
-
|
|
311
|
+
restrictedCharactersRegex={regex.basic}
|
|
299
312
|
/>
|
|
300
313
|
<div className={styles.apiDocRow}>
|
|
301
314
|
<Input
|
|
@@ -313,14 +326,16 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
|
|
|
313
326
|
label="Description"
|
|
314
327
|
value={values?.info?.description}
|
|
315
328
|
maxLength={120}
|
|
329
|
+
required
|
|
316
330
|
onChange={(value: string) => {
|
|
317
|
-
|
|
331
|
+
if (value === '' || regex.ASCII.test(value)) {
|
|
332
|
+
setFieldValue('info.description', value)
|
|
333
|
+
}
|
|
318
334
|
}}
|
|
319
335
|
onClear={() => {
|
|
320
336
|
setFieldValue('info.description', '')
|
|
321
337
|
}}
|
|
322
338
|
errorMessage={errors?.info?.description}
|
|
323
|
-
restrictedCharsRegex={regex.restrictNone}
|
|
324
339
|
/>
|
|
325
340
|
<div className={styles.paramsTable}>
|
|
326
341
|
<TagsTable
|
|
@@ -346,17 +361,21 @@ const InfoForm = ({ readOnly }: { readOnly?: boolean }) => {
|
|
|
346
361
|
className="delete-msg-container"
|
|
347
362
|
>
|
|
348
363
|
Are you sure you want to delete
|
|
349
|
-
<span className="plan-name">
|
|
364
|
+
<span className="plan-name">
|
|
365
|
+
{' '}
|
|
366
|
+
Tag <strong>{selectedTagName}</strong>
|
|
367
|
+
</span>
|
|
368
|
+
?
|
|
350
369
|
</p>
|
|
351
370
|
}
|
|
352
371
|
onSubmit={{
|
|
353
372
|
onClick: confirmDeleteTag,
|
|
354
|
-
text: '
|
|
373
|
+
text: 'Delete',
|
|
355
374
|
color: 'error',
|
|
356
375
|
fullWidth: true,
|
|
357
376
|
}}
|
|
358
377
|
onCancel={{
|
|
359
|
-
text: '
|
|
378
|
+
text: 'Cancel',
|
|
360
379
|
color: 'normal',
|
|
361
380
|
fullWidth: true,
|
|
362
381
|
}}
|
|
@@ -2,6 +2,12 @@ import React, { useEffect, useState } from 'react'
|
|
|
2
2
|
import yaml from 'js-yaml'
|
|
3
3
|
import styles from './style.module.scss'
|
|
4
4
|
|
|
5
|
+
const errorMapping = {
|
|
6
|
+
BOTH: 'Invalid JSON or YAML format',
|
|
7
|
+
JSON: 'Invalid JSON format',
|
|
8
|
+
YML: 'Invalid YAML format',
|
|
9
|
+
}
|
|
10
|
+
|
|
5
11
|
const JsonInput = ({
|
|
6
12
|
placeholder,
|
|
7
13
|
label,
|
|
@@ -129,7 +135,7 @@ const JsonInput = ({
|
|
|
129
135
|
)}
|
|
130
136
|
</div>
|
|
131
137
|
{(errorMessage || (value !== '' && isValid === false)) && (
|
|
132
|
-
<p className={styles['error-message']}>{errorMessage ||
|
|
138
|
+
<p className={styles['error-message']}>{errorMessage || errorMapping[acceptType]}</p>
|
|
133
139
|
)}
|
|
134
140
|
</div>
|
|
135
141
|
)
|
|
@@ -7,6 +7,7 @@ import { useFormikContext } from 'formik'
|
|
|
7
7
|
import { methodColorMapping, tagsTableHeaders } from '../../constants/index'
|
|
8
8
|
import TagsTable from '../table/tags-table'
|
|
9
9
|
import { Button } from 'digitinary-ui'
|
|
10
|
+
import Tooltip from '../../components/Tooltip/Tooltip'
|
|
10
11
|
|
|
11
12
|
interface LivePreviewProps {
|
|
12
13
|
transformedData?: TransformedOpenApi
|
|
@@ -37,12 +38,23 @@ const LivePreview: React.FC<LivePreviewProps> = ({ transformedData }) => {
|
|
|
37
38
|
id: index,
|
|
38
39
|
tagName: item.name,
|
|
39
40
|
description: (
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
</
|
|
45
|
-
|
|
41
|
+
<Tooltip
|
|
42
|
+
key={`${index}-description`}
|
|
43
|
+
allowHTML
|
|
44
|
+
disabled={item.description?.length <= 12}
|
|
45
|
+
content={<div style={{ padding: '0.625rem' }}>{item.description}</div>}
|
|
46
|
+
arrowWithBorder
|
|
47
|
+
placement="bottom-end"
|
|
48
|
+
type="function"
|
|
49
|
+
delay={[0, 0]}
|
|
50
|
+
>
|
|
51
|
+
<div className={styles.paramDescContainer}>
|
|
52
|
+
<p className={styles.editDescBtn}>
|
|
53
|
+
{item.description ? item.description.substring(0, 12) : '-'}
|
|
54
|
+
{item.description && item.description.length > 12 ? '...' : ''}
|
|
55
|
+
</p>
|
|
56
|
+
</div>
|
|
57
|
+
</Tooltip>
|
|
46
58
|
),
|
|
47
59
|
externalDocs: (
|
|
48
60
|
<div className={styles.paramDescContainer}>
|
|
@@ -91,6 +103,7 @@ const LivePreview: React.FC<LivePreviewProps> = ({ transformedData }) => {
|
|
|
91
103
|
),
|
|
92
104
|
}))
|
|
93
105
|
}
|
|
106
|
+
|
|
94
107
|
return (
|
|
95
108
|
<div>
|
|
96
109
|
<div className="row">
|
|
@@ -99,7 +112,11 @@ const LivePreview: React.FC<LivePreviewProps> = ({ transformedData }) => {
|
|
|
99
112
|
<SimpleLabelValue
|
|
100
113
|
key={'APIAuthenticationType'}
|
|
101
114
|
label={'API authentication type: '}
|
|
102
|
-
value={
|
|
115
|
+
value={
|
|
116
|
+
!!securityKey
|
|
117
|
+
? securitySchemes[securityKey].scheme || securitySchemes[securityKey].type
|
|
118
|
+
: '-'
|
|
119
|
+
}
|
|
103
120
|
/>
|
|
104
121
|
<SimpleLabelValue key={'version'} label={'Version: '} value={info?.version || '-'} />
|
|
105
122
|
<SimpleLabelValue
|
|
@@ -124,20 +141,22 @@ const LivePreview: React.FC<LivePreviewProps> = ({ transformedData }) => {
|
|
|
124
141
|
<div className={styles.methodsContainer} key={path.path}>
|
|
125
142
|
{Object.entries(
|
|
126
143
|
path.methods
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
144
|
+
.sort(
|
|
145
|
+
(a, b) => methodColorMapping[a.type].order + methodColorMapping[b.type].order
|
|
146
|
+
)
|
|
147
|
+
.reduce((groupedMethods, method) => {
|
|
148
|
+
// Handle methods without tags
|
|
149
|
+
const tags = method.tags?.length ? method?.tags : ['default']
|
|
150
|
+
|
|
151
|
+
tags.forEach((tag) => {
|
|
152
|
+
if (!groupedMethods[tag]) {
|
|
153
|
+
groupedMethods[tag] = []
|
|
154
|
+
}
|
|
155
|
+
groupedMethods[tag].push(method)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return groupedMethods
|
|
159
|
+
}, {})
|
|
141
160
|
).map(([tag, methods]) => (
|
|
142
161
|
<div key={tag}>
|
|
143
162
|
<h3>{tag}</h3>
|
|
@@ -100,6 +100,31 @@ const MethodsAccordion = ({
|
|
|
100
100
|
description: (
|
|
101
101
|
<div className={styles.paramDescContainer}>
|
|
102
102
|
<Tooltip
|
|
103
|
+
key={`${index}-description`}
|
|
104
|
+
allowHTML
|
|
105
|
+
disabled={method.parameters[index].description?.length <= 12}
|
|
106
|
+
content={
|
|
107
|
+
<div style={{ padding: '0.625rem' }}>{method.parameters[index].description}</div>
|
|
108
|
+
}
|
|
109
|
+
arrowWithBorder
|
|
110
|
+
placement="bottom-end"
|
|
111
|
+
type="function"
|
|
112
|
+
delay={[0, 0]}
|
|
113
|
+
onShow={() => tooltipRefs[index]?.hide()}
|
|
114
|
+
>
|
|
115
|
+
<p style={{ alignSelf: 'center' }}>
|
|
116
|
+
{method.parameters[index].description
|
|
117
|
+
? method.parameters[index].description.substring(0, 12)
|
|
118
|
+
: '-'}
|
|
119
|
+
{method.parameters[index].description &&
|
|
120
|
+
method.parameters[index].description.length > 12
|
|
121
|
+
? '...'
|
|
122
|
+
: ''}
|
|
123
|
+
</p>
|
|
124
|
+
</Tooltip>
|
|
125
|
+
<Tooltip
|
|
126
|
+
key={`${index}-add-edit-description`}
|
|
127
|
+
allowHTML
|
|
103
128
|
arrowWithBorder
|
|
104
129
|
placement="bottom-end"
|
|
105
130
|
type="function"
|
|
@@ -142,15 +167,7 @@ const MethodsAccordion = ({
|
|
|
142
167
|
variant="link"
|
|
143
168
|
color="action"
|
|
144
169
|
endIcon={<SVGLoader src={EditIcon} width="1.5rem" height="1.5rem" />}
|
|
145
|
-
>
|
|
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
|
-
: ''}
|
|
153
|
-
</Button>
|
|
170
|
+
></Button>
|
|
154
171
|
) : (
|
|
155
172
|
<Button
|
|
156
173
|
className={styles.editDescBtn}
|
|
@@ -210,14 +227,13 @@ const MethodsAccordion = ({
|
|
|
210
227
|
|
|
211
228
|
useEffect(() => {
|
|
212
229
|
if (method?.parameters) {
|
|
213
|
-
setTableRecords(generateTableData(method.parameters))
|
|
214
230
|
setTableData(method.parameters)
|
|
215
231
|
}
|
|
216
232
|
}, [method, path])
|
|
217
233
|
|
|
218
234
|
useEffect(() => {
|
|
219
235
|
// prepare tags selection list
|
|
220
|
-
if (
|
|
236
|
+
if (method?.tags.length || tags.length) {
|
|
221
237
|
const convertedStringArray = (method?.tags || [])?.map((item) => ({
|
|
222
238
|
label: capitalize(item),
|
|
223
239
|
value: item,
|
|
@@ -230,6 +246,7 @@ const MethodsAccordion = ({
|
|
|
230
246
|
const filteredArray = mergedArray.filter(
|
|
231
247
|
(value, index, self) => index === self.findIndex((t) => t.value === value.value)
|
|
232
248
|
)
|
|
249
|
+
|
|
233
250
|
setSelectionTags(filteredArray)
|
|
234
251
|
}
|
|
235
252
|
}, [tags, method])
|
|
@@ -343,6 +360,7 @@ const MethodsAccordion = ({
|
|
|
343
360
|
}
|
|
344
361
|
children={
|
|
345
362
|
<JsonInput
|
|
363
|
+
acceptType="JSON"
|
|
346
364
|
withFooter={!readOnly}
|
|
347
365
|
className={'jsonField'}
|
|
348
366
|
placeholder="Enter your request body as a JSON object...."
|
|
@@ -399,6 +417,7 @@ const MethodsAccordion = ({
|
|
|
399
417
|
}
|
|
400
418
|
children={
|
|
401
419
|
<JsonInput
|
|
420
|
+
acceptType="JSON"
|
|
402
421
|
withFooter={!readOnly}
|
|
403
422
|
className={'jsonField'}
|
|
404
423
|
placeholder="Enter your response as a JSON object..."
|
|
@@ -451,17 +470,20 @@ const MethodsAccordion = ({
|
|
|
451
470
|
className="delete-msg-container"
|
|
452
471
|
>
|
|
453
472
|
Are you sure you want to delete
|
|
454
|
-
<span className="plan-name">
|
|
473
|
+
<span className="plan-name">
|
|
474
|
+
Parameter <strong>{selectedParamName}</strong>
|
|
475
|
+
</span>
|
|
476
|
+
?
|
|
455
477
|
</p>
|
|
456
478
|
}
|
|
457
479
|
onSubmit={{
|
|
458
480
|
onClick: confirmDeleteParameter,
|
|
459
|
-
text: '
|
|
481
|
+
text: 'Delete',
|
|
460
482
|
color: 'error',
|
|
461
483
|
fullWidth: true,
|
|
462
484
|
}}
|
|
463
485
|
onCancel={{
|
|
464
|
-
text: '
|
|
486
|
+
text: 'Cancel',
|
|
465
487
|
color: 'normal',
|
|
466
488
|
fullWidth: true,
|
|
467
489
|
}}
|
|
@@ -113,15 +113,15 @@
|
|
|
113
113
|
height: 1px;
|
|
114
114
|
|
|
115
115
|
&:before {
|
|
116
|
-
width:
|
|
117
|
-
height:
|
|
116
|
+
width: 0.625rem;
|
|
117
|
+
height: 0.625rem;
|
|
118
118
|
background-color: white;
|
|
119
119
|
transform: rotate(45deg);
|
|
120
120
|
border: none;
|
|
121
121
|
border-left: 1px solid #d8dae5 !important;
|
|
122
122
|
border-top: 1px solid #d8dae5 !important;
|
|
123
123
|
z-index: 20000000000;
|
|
124
|
-
top: -0.
|
|
124
|
+
top: -0.45rem;
|
|
125
125
|
transform-origin: center !important;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React, { useState, useEffect, ReactNode } from 'react'
|
|
2
|
-
import Tippy from '@tippyjs/react'
|
|
2
|
+
import Tippy, { TippyProps } from '@tippyjs/react'
|
|
3
3
|
import 'tippy.js/dist/tippy.css'
|
|
4
4
|
import './Tooltip.scss'
|
|
5
5
|
|
|
6
|
-
interface TooltipProps {
|
|
7
|
-
children: ReactNode
|
|
6
|
+
interface TooltipProps extends TippyProps {
|
|
8
7
|
content: ReactNode
|
|
9
8
|
success?: boolean
|
|
10
9
|
onMouseEnter?: (event: React.MouseEvent<HTMLDivElement>) => void
|
|
@@ -8,6 +8,7 @@ import styles from '../MethodAccordion/MethodAccordion.module.scss'
|
|
|
8
8
|
import { useFormik } from 'formik'
|
|
9
9
|
import * as yup from 'yup'
|
|
10
10
|
import { capitalize } from '../../helpers/methodAccordion.helper'
|
|
11
|
+
import regex from '../../constants/regex'
|
|
11
12
|
|
|
12
13
|
const ParamterTable = ({
|
|
13
14
|
id,
|
|
@@ -131,6 +132,7 @@ const ParamterTable = ({
|
|
|
131
132
|
}} // Pass the value directly
|
|
132
133
|
value={values.name} // Bind value to the state
|
|
133
134
|
disabled={readOnly}
|
|
135
|
+
restrictedCharactersRegex={regex.basic}
|
|
134
136
|
/>
|
|
135
137
|
</div>
|
|
136
138
|
</td>
|
|
@@ -225,7 +227,7 @@ const ParamterTable = ({
|
|
|
225
227
|
<TextArea
|
|
226
228
|
value={text || values.description}
|
|
227
229
|
onChange={(value) => {
|
|
228
|
-
setText(value)
|
|
230
|
+
if (value === '' || regex.ASCII.test(value)) setText(value)
|
|
229
231
|
}}
|
|
230
232
|
disabled={readOnly}
|
|
231
233
|
placeholder="Describe parameter..."
|
|
@@ -8,6 +8,9 @@ import { AddRow, EditIcon, DeleteIcon } from '../../assets/icons'
|
|
|
8
8
|
import styles from '../MethodAccordion/MethodAccordion.module.scss'
|
|
9
9
|
import { useFormik } from 'formik'
|
|
10
10
|
import * as yup from 'yup'
|
|
11
|
+
import regex from '../../constants/regex'
|
|
12
|
+
|
|
13
|
+
const urlRegex = /^(https?:\/\/)?(www\.)?([a-zA-Z0-9-]+(\.[a-zA-Z]{2,})+)(\/[^\s]*)?$/
|
|
11
14
|
|
|
12
15
|
const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow, readOnly }) => {
|
|
13
16
|
const [text, setText] = useState('')
|
|
@@ -28,7 +31,20 @@ const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow,
|
|
|
28
31
|
validationSchema: yup.object().shape({
|
|
29
32
|
name: yup.string().required('Tag name is required'),
|
|
30
33
|
description: yup.string().optional(),
|
|
31
|
-
externalDocs: yup
|
|
34
|
+
externalDocs: yup
|
|
35
|
+
.object()
|
|
36
|
+
.shape({
|
|
37
|
+
url: yup
|
|
38
|
+
.string()
|
|
39
|
+
.matches(urlRegex, 'Invalid URL')
|
|
40
|
+
.when('description', (description, schema) => {
|
|
41
|
+
return description?.at(0)
|
|
42
|
+
? schema.required('URL is required when description is provided')
|
|
43
|
+
: schema.optional()
|
|
44
|
+
}),
|
|
45
|
+
description: yup.string().optional(),
|
|
46
|
+
})
|
|
47
|
+
.optional(),
|
|
32
48
|
}),
|
|
33
49
|
onSubmit: (values) => {
|
|
34
50
|
saveNewRow(values)
|
|
@@ -38,7 +54,9 @@ const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow,
|
|
|
38
54
|
resetForm()
|
|
39
55
|
setIsFormOpen(false)
|
|
40
56
|
},
|
|
57
|
+
validateOnChange: true,
|
|
41
58
|
})
|
|
59
|
+
|
|
42
60
|
return (
|
|
43
61
|
<div className="tableSectionContainer">
|
|
44
62
|
<div className="tableContainer">
|
|
@@ -107,7 +125,7 @@ const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow,
|
|
|
107
125
|
size="large"
|
|
108
126
|
type="text"
|
|
109
127
|
onChange={(value) => {
|
|
110
|
-
setFieldValue('name', value)
|
|
128
|
+
!regex.basic.test(value) && setFieldValue('name', value)
|
|
111
129
|
}} // Pass the value directly
|
|
112
130
|
value={values.name} // Bind value to the state
|
|
113
131
|
disabled={readOnly}
|
|
@@ -131,7 +149,7 @@ const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow,
|
|
|
131
149
|
<TextArea
|
|
132
150
|
value={text || values.description}
|
|
133
151
|
onChange={(value) => {
|
|
134
|
-
setText(value)
|
|
152
|
+
if (value === '' || regex.ASCII.test(value)) setText(value)
|
|
135
153
|
}}
|
|
136
154
|
disabled={readOnly}
|
|
137
155
|
placeholder="Describe Tag..."
|
|
@@ -184,7 +202,9 @@ const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow,
|
|
|
184
202
|
placeholder="Describe External Doc..."
|
|
185
203
|
value={externalDesc || values.externalDocs.description}
|
|
186
204
|
disabled={readOnly}
|
|
187
|
-
onChange={(value) =>
|
|
205
|
+
onChange={(value) => {
|
|
206
|
+
if (value === '' || regex.ASCII.test(value)) setExternalDesc(value)
|
|
207
|
+
}}
|
|
188
208
|
/>
|
|
189
209
|
<p className={_styles.editDescTooltipContent_header}>
|
|
190
210
|
External Docs Link
|
|
@@ -193,7 +213,9 @@ const TagsTable = ({ id, headCells, data, isFormOpen, setIsFormOpen, saveNewRow,
|
|
|
193
213
|
placeholder="External Docs Link..."
|
|
194
214
|
value={externalUrl || values.externalDocs.url}
|
|
195
215
|
disabled={readOnly}
|
|
196
|
-
onChange={(value) =>
|
|
216
|
+
onChange={(value) => {
|
|
217
|
+
if (value === '' || regex.ASCII.test(value)) setExternalUrl(value)
|
|
218
|
+
}}
|
|
197
219
|
/>
|
|
198
220
|
{!readOnly && (
|
|
199
221
|
<Button
|
package/src/constants/regex.ts
CHANGED
package/src/layout/layout.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JSX, useEffect } from 'react'
|
|
1
|
+
import { JSX, useEffect, useState } 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'
|
|
@@ -11,6 +11,7 @@ import { FormikProvider, useFormik } from 'formik'
|
|
|
11
11
|
import { schemaValidation } from '../validator/form.scheme'
|
|
12
12
|
import { TransformedOpenApi } from '@entities/transformedOpenApi'
|
|
13
13
|
import { methodColorMapping } from '../constants/index'
|
|
14
|
+
import CommonDialog from '../components/dialog'
|
|
14
15
|
|
|
15
16
|
interface ILayoutProps {
|
|
16
17
|
openApiJson?: OpenAPIFile
|
|
@@ -36,6 +37,7 @@ const Layout = ({ openApiJson, handleSave, setIsFormDirty }: ILayoutProps): JSX.
|
|
|
36
37
|
validateForm(values)
|
|
37
38
|
},
|
|
38
39
|
})
|
|
40
|
+
const [isPublishDialogOpen, setIsPublishDialogOpen] = useState(false)
|
|
39
41
|
|
|
40
42
|
useEffect(() => {
|
|
41
43
|
if (setIsFormDirty) {
|
|
@@ -45,10 +47,11 @@ const Layout = ({ openApiJson, handleSave, setIsFormDirty }: ILayoutProps): JSX.
|
|
|
45
47
|
|
|
46
48
|
return (
|
|
47
49
|
<div className={styles.docsLayout}>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
{formik.dirty && (
|
|
51
|
+
<Alert className={styles.apiDocAlert} color="warning" severity="warning">
|
|
52
|
+
There are changes you made may not be saved
|
|
53
|
+
</Alert>
|
|
54
|
+
)}
|
|
52
55
|
<div className={styles.layoutContainer}>
|
|
53
56
|
<div className={`${styles.editorSide} ${styles.docSide}`}>
|
|
54
57
|
<SectionHead
|
|
@@ -63,7 +66,8 @@ const Layout = ({ openApiJson, handleSave, setIsFormDirty }: ILayoutProps): JSX.
|
|
|
63
66
|
type="submit"
|
|
64
67
|
variant="contained"
|
|
65
68
|
color="primary"
|
|
66
|
-
onClick={
|
|
69
|
+
onClick={() => setIsPublishDialogOpen(true)}
|
|
70
|
+
disabled={!formik.isValid || formik.isSubmitting}
|
|
67
71
|
>
|
|
68
72
|
Save
|
|
69
73
|
</Button>
|
|
@@ -104,6 +108,37 @@ const Layout = ({ openApiJson, handleSave, setIsFormDirty }: ILayoutProps): JSX.
|
|
|
104
108
|
)}
|
|
105
109
|
</div>
|
|
106
110
|
</div>
|
|
111
|
+
<CommonDialog
|
|
112
|
+
status="warning"
|
|
113
|
+
content={
|
|
114
|
+
<p
|
|
115
|
+
style={{
|
|
116
|
+
textAlign: 'center',
|
|
117
|
+
fontWeight: 400,
|
|
118
|
+
fontSize: '1rem',
|
|
119
|
+
lineHeight: '1.4375rem',
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
Are you sure you want to Publish your changes?
|
|
123
|
+
</p>
|
|
124
|
+
}
|
|
125
|
+
onSubmit={{
|
|
126
|
+
onClick: () => {
|
|
127
|
+
formik.handleSubmit()
|
|
128
|
+
setIsPublishDialogOpen(false)
|
|
129
|
+
},
|
|
130
|
+
text: 'Publish',
|
|
131
|
+
color: 'warning',
|
|
132
|
+
fullWidth: true,
|
|
133
|
+
}}
|
|
134
|
+
onCancel={{
|
|
135
|
+
text: 'Cancel',
|
|
136
|
+
color: 'normal',
|
|
137
|
+
fullWidth: true,
|
|
138
|
+
}}
|
|
139
|
+
onClose={() => setIsPublishDialogOpen(false)}
|
|
140
|
+
open={isPublishDialogOpen}
|
|
141
|
+
/>
|
|
107
142
|
</div>
|
|
108
143
|
)
|
|
109
144
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import * as yup from
|
|
1
|
+
import * as yup from 'yup'
|
|
2
2
|
export const schemaValidation = yup.object({
|
|
3
3
|
openapi: yup.string().required(),
|
|
4
4
|
info: yup
|
|
5
5
|
.object({
|
|
6
|
-
title: yup.string().required(
|
|
7
|
-
description: yup.string().
|
|
8
|
-
version: yup.string().required(
|
|
6
|
+
title: yup.string().trim().required('API Name is required.'),
|
|
7
|
+
description: yup.string().required(),
|
|
8
|
+
version: yup.string().required('API Version is required'),
|
|
9
9
|
})
|
|
10
10
|
.required(),
|
|
11
11
|
servers: yup
|
|
@@ -32,8 +32,8 @@ export const schemaValidation = yup.object({
|
|
|
32
32
|
yup.object(
|
|
33
33
|
props
|
|
34
34
|
? Object.keys(props).reduce((acc, propKey) => {
|
|
35
|
-
acc[propKey] = yup.mixed()
|
|
36
|
-
return acc
|
|
35
|
+
acc[propKey] = yup.mixed()
|
|
36
|
+
return acc
|
|
37
37
|
}, {})
|
|
38
38
|
: {}
|
|
39
39
|
)
|
|
@@ -42,8 +42,8 @@ export const schemaValidation = yup.object({
|
|
|
42
42
|
items: yup.mixed().optional(),
|
|
43
43
|
enum: yup.array(yup.string()).optional(),
|
|
44
44
|
required: yup.array(yup.string()).optional(),
|
|
45
|
-
})
|
|
46
|
-
return acc
|
|
45
|
+
})
|
|
46
|
+
return acc
|
|
47
47
|
}, {})
|
|
48
48
|
: {}
|
|
49
49
|
)
|
|
@@ -67,4 +67,4 @@ export const schemaValidation = yup.object({
|
|
|
67
67
|
})
|
|
68
68
|
)
|
|
69
69
|
.optional(),
|
|
70
|
-
})
|
|
70
|
+
})
|