From e496e99265d6ab3ecdb23196a7108ccff27da40d Mon Sep 17 00:00:00 2001 From: Evgenii Fedoseev Date: Tue, 20 Feb 2024 00:39:02 +0300 Subject: [PATCH 1/4] feat: add form-data format with string, file and file Array --- src/includer/traverse/tables.ts | 2 + src/includer/ui/endpoint.ts | 4 +- src/runtime/components/BodyFormData.tsx | 129 ++++++++++++++++++ .../components/{Body.tsx => BodyJson.tsx} | 5 +- src/runtime/components/FileInputArray.tsx | 45 ++++++ src/runtime/components/index.ts | 3 +- src/runtime/sandbox.tsx | 7 +- src/runtime/types.ts | 2 + src/runtime/utils.ts | 7 +- 9 files changed, 195 insertions(+), 9 deletions(-) create mode 100644 src/runtime/components/BodyFormData.tsx rename src/runtime/components/{Body.tsx => BodyJson.tsx} (87%) create mode 100644 src/runtime/components/FileInputArray.tsx diff --git a/src/includer/traverse/tables.ts b/src/includer/traverse/tables.ts index e08aa94..46206b6 100644 --- a/src/includer/traverse/tables.ts +++ b/src/includer/traverse/tables.ts @@ -346,6 +346,8 @@ function prepareSampleElement( return 'c3073b9d-edd0-49f2-a28d-b7ded8ff9a8b'; case 'date-time': return '2022-12-29T18:02:01Z'; + case 'binary': + return null; default: return 'string'; } diff --git a/src/includer/ui/endpoint.ts b/src/includer/ui/endpoint.ts index a81eb78..db1bf75 100644 --- a/src/includer/ui/endpoint.ts +++ b/src/includer/ui/endpoint.ts @@ -110,7 +110,7 @@ function sandbox({ const searchParams = params?.filter((param: Parameter) => param.in === 'query'); const headers = params?.filter((param: Parameter) => param.in === 'header'); let bodyStr: null | string = null; - if (requestBody?.type === 'application/json') { + if (requestBody?.type === 'application/json' || requestBody?.type === 'multipart/form-data') { bodyStr = JSON.stringify(prepareSampleObject(requestBody?.schema ?? {}), null, 2); } @@ -119,6 +119,8 @@ function sandbox({ searchParams, headers, body: bodyStr, + schema: requestBody?.schema ?? {}, + bodyType: requestBody?.type, method, security, path: path, diff --git a/src/runtime/components/BodyFormData.tsx b/src/runtime/components/BodyFormData.tsx new file mode 100644 index 0000000..8723bc1 --- /dev/null +++ b/src/runtime/components/BodyFormData.tsx @@ -0,0 +1,129 @@ +import React from 'react'; +import {Text, TextArea} from '@gravity-ui/uikit'; + +import {Text as TextEnum} from '../../plugin/constants'; +import {OpenJSONSchema} from '../../includer/models'; + +import type {Field, Nullable} from '../types'; +import {Column} from './Column'; +import {FileInputArray} from './FileInputArray'; + +type Props = { + example: Nullable; + schema: OpenJSONSchema | undefined; + bodyType?: string; +}; + +type State = { + error: Nullable; +}; + +export class BodyFormData extends React.Component implements Field { + private formValue: FormData; + constructor(props: Props) { + super(props); + this.formValue = new FormData(); + + this.state = { + error: null, + }; + } + + render() { + const {properties, type} = this.props.schema ?? {}; + const example = JSON.parse(this.props.example ?? '{}'); + if (type !== 'object' || !properties || this.props.bodyType !== 'multipart/form-data') { + return null; + } + + return + {TextEnum.BODY_INPUT_LABEL} + { + Object.keys(properties).map(key => { + const property = properties[key]; + if (typeof property === 'object') { + if ( + property.type === 'string' + && property.format === 'binary' + ) { + return + {key}: + this.createOnChange(key)(event.target.files?.[0])} /> + + } + const {items} = property || {}; + + if (property.type === 'array' && typeof items === 'object' && !Array.isArray(items)) { + const {format, type} = items; + if (type === 'string' && format === 'binary') { + return + {key}: + + + } + // TODO: string array + } + + const exampleValue = property.type === 'string' + ? example[key] + : JSON.stringify(example[key], null, 2); + + const rows = property.type === 'string' + ? 1 + : 3; + + return + {key}: +