1+ import { withTheme } from '@rjsf/core' ;
2+ import { RJSFSchema , StrictRJSFSchema } from '@rjsf/utils' ;
3+ import validator from '@rjsf/validator-ajv8' ;
14import cls from 'classnames' ;
25import lodashGet from 'lodash/get' ;
36import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
@@ -12,18 +15,37 @@ import {
1215 ISchemaContributions ,
1316 IJSONSchema ,
1417 IJSONSchemaSnippet ,
18+ IJSONSchemaMap ,
19+ isUndefined ,
1520} from '@opensumi/ide-core-browser' ;
1621import { EDirection , SplitPanel } from '@opensumi/ide-core-browser/lib/components' ;
1722import { MenuActionList } from '@opensumi/ide-core-browser/lib/components/actions/index' ;
1823import { LabelMenuItemNode } from '@opensumi/ide-core-browser/lib/menu/next/menu.interface' ;
24+ import { acquireAjv } from '@opensumi/ide-core-browser/lib/utils/schema' ;
1925
2026import { launchExtensionSchemaUri } from '../../common/debug-schema' ;
2127
28+ import { SelectWidget } from './components/select-widget' ;
29+ import { TextWidget } from './components/text-widget' ;
2230import styles from './launch.module.less' ;
31+ import { ArrayFieldItemTemplate } from './templates/array-field-item-template' ;
32+ import { ArrayFieldTemplate } from './templates/array-field-template' ;
33+ import {
34+ MoveUpButton ,
35+ MoveDownButton ,
36+ RemoveButton ,
37+ SubmitButton ,
38+ AddButton ,
39+ CopyButton ,
40+ } from './templates/button-template' ;
41+ import { DescriptionFieldTemplate } from './templates/description-field-template' ;
42+ import { FieldTemplate } from './templates/field-template' ;
43+ import { ObjectFieldTemplate } from './templates/object-field-template' ;
2344
2445export const LaunchViewContainer = ( ) => {
2546 const schemaRegistry = useInjectable < IJSONSchemaRegistry > ( IJSONSchemaRegistry ) ;
26- const [ snippetItems , setSnippetItems ] = useState < IJSONSchemaSnippet [ ] > ( [ ] ) ;
47+ const [ schemaContributions , setSchemaContributions ] = useState < IJSONSchema > ( ) ;
48+ const [ currentSnippetItem , setCurrentSnippetItem ] = useState < IJSONSchemaSnippet > ( ) ;
2749
2850 useEffect ( ( ) => {
2951 const disposed = schemaRegistry . onDidChangeSchema ( ( uri : string ) => {
@@ -37,23 +59,41 @@ export const LaunchViewContainer = () => {
3759 return ( ) => disposed . dispose ( ) ;
3860 } , [ ] ) ;
3961
40- const handleSchemaSnippets = ( contributions : ISchemaContributions ) => {
41- const launchExtension = contributions . schemas [ launchExtensionSchemaUri ] ;
62+ const handleSchemaSnippets = useCallback (
63+ ( contributions : ISchemaContributions ) => {
64+ const launchExtension = contributions . schemas [ launchExtensionSchemaUri ] ;
4265
43- if ( ! launchExtension ) {
44- return ;
66+ if ( ! launchExtension ) {
67+ return ;
68+ }
69+
70+ setSchemaContributions ( launchExtension ) ;
71+ } ,
72+ [ schemaContributions ] ,
73+ ) ;
74+
75+ const snippetItems = useMemo ( ( ) => {
76+ if ( ! schemaContributions ) {
77+ return [ ] ;
4578 }
4679
47- const snippets : IJSONSchemaSnippet [ ] = lodashGet ( launchExtension , [
80+ const snippets : IJSONSchemaSnippet [ ] = lodashGet ( schemaContributions , [
4881 'properties' ,
4982 'configurations' ,
5083 'items' ,
5184 'defaultSnippets' ,
5285 ] as ( keyof IJSONSchema ) [ ] ) ;
53- setSnippetItems ( snippets . filter ( ( s ) => s . label ) ) ;
54- } ;
86+ return snippets . filter ( ( s ) => s . label ) ;
87+ } , [ schemaContributions ] ) ;
5588
56- const onSelectedConfiguration = ( current : string ) => { } ;
89+ const onSelectedConfiguration = ( current : string ) => {
90+ const findItems = snippetItems . find ( ( { label } ) => label === current ) ;
91+ if ( ! findItems ) {
92+ return ;
93+ }
94+
95+ setCurrentSnippetItem ( findItems ) ;
96+ } ;
5797
5898 return (
5999 < ComponentContextProvider value = { { getIcon, localize } } >
@@ -70,7 +110,7 @@ export const LaunchViewContainer = () => {
70110 snippetItems = { snippetItems }
71111 onSelectedConfiguration = { onSelectedConfiguration }
72112 />
73- < LaunchBody data-sp-flex = { 1 } />
113+ < LaunchBody data-sp-flex = { 1 } snippetItem = { currentSnippetItem } schemaContributions = { schemaContributions } />
74114 </ SplitPanel >
75115 </ div >
76116 </ ComponentContextProvider >
@@ -152,4 +192,97 @@ const LaunchIndexs = ({
152192 ) ;
153193} ;
154194
155- const LaunchBody = ( ) => < div > body</ div > ;
195+ const Form = withTheme ( {
196+ widgets : {
197+ TextWidget,
198+ SelectWidget,
199+ } ,
200+ } ) ;
201+
202+ const LaunchBody = ( {
203+ snippetItem,
204+ schemaContributions,
205+ } : {
206+ snippetItem ?: IJSONSchemaSnippet ;
207+ schemaContributions ?: IJSONSchema ;
208+ } ) => {
209+ if ( ! snippetItem ) {
210+ return < div > { localize ( 'debug.action.no.configuration' ) } </ div > ;
211+ }
212+
213+ const [ schemaProperties , setSchemaProperties ] = useState < IJSONSchema > ( ) ;
214+
215+ useEffect ( ( ) => {
216+ const ajv = acquireAjv ( ) ;
217+ // 1. 先从 schema 中找出 oneOf 池
218+ const oneOfPool : IJSONSchema [ ] =
219+ lodashGet ( schemaContributions , [ 'properties' , 'configurations' , 'items' , 'oneOf' ] as ( keyof IJSONSchema ) [ ] ) || [ ] ;
220+
221+ // 2. 再从 snippetItem body 中找出符合条件的 oneOf(可能存在多个,如果有多个就只取第一个)
222+ const findOneOf = oneOfPool . find ( ( oneOf ) => {
223+ const { body } = snippetItem ;
224+ return ajv ! . validate ( oneOf , body ) ;
225+ } ) ;
226+
227+ if ( findOneOf ) {
228+ setSchemaProperties ( findOneOf ) ;
229+ }
230+ } , [ snippetItem , schemaContributions ] ) ;
231+
232+ const schema : RJSFSchema | undefined = useMemo ( ( ) => {
233+ if ( ! ( schemaProperties && schemaProperties . properties ) ) {
234+ return ;
235+ }
236+
237+ const { label, body, description } = snippetItem ;
238+ const { properties } = schemaProperties ;
239+
240+ const snippetProperties = Object . keys ( body ) . reduce ( ( pre : IJSONSchemaMap , cur : string ) => {
241+ if ( properties ! [ cur ] ?. type === 'array' && isUndefined ( properties ! [ cur ] . items ) ) {
242+ properties ! [ cur ] . items = { type : 'string' } ;
243+ }
244+
245+ // 如果 type 是数组,则取第一个
246+ if ( Array . isArray ( properties ! [ cur ] ?. type ) ) {
247+ properties ! [ cur ] . type = properties ! [ cur ] ?. type ! [ 0 ] || 'string' ;
248+ }
249+
250+ pre [ cur ] = properties ! [ cur ] ;
251+ return pre ;
252+ } , { } ) ;
253+
254+ return {
255+ title : label ,
256+ type : 'object' ,
257+ description,
258+ properties : snippetProperties ,
259+ } as StrictRJSFSchema ;
260+ } , [ snippetItem , schemaProperties ] ) ;
261+
262+ return (
263+ < div className = { styles . launch_schema_body_container } >
264+ { schema && (
265+ < Form
266+ formData = { snippetItem . body }
267+ schema = { schema }
268+ validator = { validator }
269+ templates = { {
270+ ArrayFieldTemplate,
271+ ArrayFieldItemTemplate,
272+ DescriptionFieldTemplate,
273+ FieldTemplate,
274+ ObjectFieldTemplate,
275+ ButtonTemplates : {
276+ MoveUpButton,
277+ MoveDownButton,
278+ RemoveButton,
279+ SubmitButton,
280+ AddButton,
281+ CopyButton,
282+ } ,
283+ } }
284+ />
285+ ) }
286+ </ div >
287+ ) ;
288+ } ;
0 commit comments