From ce2bc21223ecfecba23a7f0a99feb7a9f85c7250 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Wed, 22 Nov 2023 19:00:39 +0530 Subject: [PATCH 01/29] Initialised new playground file from old playground --- .../components/playground/NewPlayground.tsx | 492 ++++++++++++++++++ modelina-website/src/pages/playground.tsx | 4 +- 2 files changed, 495 insertions(+), 1 deletion(-) create mode 100644 modelina-website/src/components/playground/NewPlayground.tsx diff --git a/modelina-website/src/components/playground/NewPlayground.tsx b/modelina-website/src/components/playground/NewPlayground.tsx new file mode 100644 index 0000000000..e08e5e2972 --- /dev/null +++ b/modelina-website/src/components/playground/NewPlayground.tsx @@ -0,0 +1,492 @@ +import React from 'react'; +import MonacoEditorWrapper from '../MonacoEditorWrapper'; +import { + defaultAsyncapiDocument, + ModelinaOptions, + ModelinaQueryOptions, + GenerateMessage, + UpdateMessage +} from '@/types'; +import Router, { withRouter, NextRouter } from 'next/router'; +import { encode } from 'js-base64'; +import GeneratedModelsComponent from './GeneratedModels'; +import PlaygroundOptions from './PlaygroundOptions'; +import Heading from '../typography/Heading'; +import Paragraph from '../typography/Paragraph'; +import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; +import { + PlaygroundTypeScriptConfigContext, + PlaygroundCSharpConfigContext, + PlaygroundDartConfigContext, + PlaygroundGoConfigContext, + PlaygroundJavaConfigContext, + PlaygroundJavaScriptConfigContext, + PlaygroundKotlinConfigContext, + PlaygroundPythonConfigContext, + PlaygroundRustConfigContext, + PlaygroundCplusplusConfigContext, + PlaygroundGeneralConfigContext, + PlaygroundPhpConfigContext +} from '../contexts/PlaygroundConfigContext'; +import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; +import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; +import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; +import { getGoGeneratorCode } from '@/helpers/GeneratorCode/GoGenerator'; +import { getCSharpGeneratorCode } from '@/helpers/GeneratorCode/CSharpGenerator'; +import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; +import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; +import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; +import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; +import CustomError from '../CustomError'; +import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; +import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; + +interface WithRouterProps { + router: NextRouter; +} + +interface ModelsGeneratorProps { + code: string; + name: string; +} +interface ModelinaPlaygroundProps extends WithRouterProps { + maxInputSize?: number; +} + +type ModelinaPlaygroundState = { + input: string; + models: ModelsGeneratorProps[]; + generatorCode: string; + loaded: { + editorLoaded: boolean; + hasReceivedCode: boolean; + }; + showGeneratorCode: boolean; + error: boolean; + statusCode: number; + errorMessage: string; +}; + +class Playground extends React.Component< + ModelinaPlaygroundProps, + ModelinaPlaygroundState +> { + config: ModelinaOptions = { + language: 'typescript', + propertyNamingFormat: 'default', + modelNamingFormat: 'default', + enumKeyNamingFormat: 'default', + indentationType: 'spaces', + showTypeMappingExample: false, + tsMarshalling: false, + tsModelType: 'class', + tsEnumType: 'enum', + tsModuleSystem: 'CJS', + tsIncludeDescriptions: false, + tsIncludeExampleFunction: false, + tsIncludeJsonBinPack: false, + csharpArrayType: 'Array', + csharpAutoImplemented: false, + csharpOverwriteHashcode: false, + csharpIncludeJson: false, + csharpOverwriteEqual: false, + csharpIncludeNewtonsoft: false, + csharpNamespace: 'asyncapi.models', + csharpNullable: false, + phpIncludeDescriptions: false, + phpNamespace: 'AsyncAPI/Models', + cplusplusNamespace: 'AsyncapiModels', + javaPackageName: 'asyncapi.models', + javaIncludeJackson: false, + javaIncludeMarshaling: false, + javaArrayType: 'Array', + javaOverwriteHashcode: false, + javaOverwriteEqual: false, + javaOverwriteToString: false, + javaJavaDocs: false, + javaJavaxAnnotation: false, + goPackageName: 'asyncapi.models', + kotlinPackageName: 'asyncapi.models' + }; + hasLoadedQuery: boolean = false; + constructor(props: ModelinaPlaygroundProps) { + super(props); + this.state = { + input: JSON.stringify(defaultAsyncapiDocument, null, 4), + models: [], + generatorCode: '', + loaded: { + editorLoaded: false, + hasReceivedCode: false + }, + showGeneratorCode: false, + error: false, + statusCode: 400, + errorMessage: 'Bad Request', + }; + this.setNewConfig = this.setNewConfig.bind(this); + this.setNewQuery = this.setNewQuery.bind(this); + this.generateNewCode = this.generateNewCode.bind(this); + } + + setNewConfig(config: string, configValue: any, updateCode?: boolean) { + this.setNewQuery(config, configValue); + /* eslint-disable-next-line security/detect-object-injection */ + (this.config as any)[config] = configValue; + if (updateCode === true || updateCode === undefined) { + this.generateNewCode(this.state.input); + } + } + + /** + * Set a query key and value + */ + setNewQuery(queryKey: string, queryValue: any) { + const newQuery = { + query: { ...this.props.router.query } + }; + if (queryValue === false) { + delete newQuery.query[queryKey]; + } else { + /* eslint-disable-next-line security/detect-object-injection */ + newQuery.query[queryKey] = String(queryValue); + } + Router.push(newQuery, undefined, { scroll: false }); + } + + /** + * Tell the socket io server that we want some code + */ + generateNewCode(input: string) { + try { + const message: GenerateMessage = { + ...this.config, + input: encode(JSON.stringify(JSON.parse(input))) + }; + if (message.input.length > (this.props.maxInputSize || 30000)) { + console.error('Input too large, use smaller example'); + this.setState({ ...this.state, error: true, errorMessage: 'Input too large, use smaller example', statusCode: 400 }); + } else { + const generators: { [key: string]: Function } = { + typescript: getTypeScriptGeneratorCode, + javascript: getJavaScriptGeneratorCode, + java: getJavaGeneratorCode, + go: getGoGeneratorCode, + csharp: getCSharpGeneratorCode, + rust: getRustGeneratorCode, + python: getPythonGeneratorCode, + dart: getDartGeneratorCode, + cplusplus: getCplusplusGeneratorCode, + kotlin: getKotlinGeneratorCode, + php: getPhpGeneratorCode + } + const generatorCode = generators[this.config.language](message); + fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { + body: JSON.stringify(message), + method: 'POST' + }).then(async (res) => { + if (!res.ok) { + throw new Error(res.statusText); + } + const response: UpdateMessage = await res.json(); + this.setState({ + ...this.state, + generatorCode, + models: response.models, + loaded: { + ...this.state.loaded, + hasReceivedCode: true + }, + error: false, + statusCode: 200, + errorMessage: '', + }); + }).catch(error => { + console.error(error); + this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 500 }); + }); + } + } catch (e: any) { + console.error(e); + this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 400 }); + } + } + + render() { + const { loaded } = this.state; + const isHardLoaded = loaded.hasReceivedCode; + const isSoftLoaded = loaded.editorLoaded; + const isLoaded = isHardLoaded && isSoftLoaded; + + const query = this.props.router.query as ModelinaQueryOptions; + if (query.language !== undefined) { + this.config.language = query.language as any; + } + if (query.enumKeyNamingFormat !== undefined) { + this.config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; + } + if (query.propertyNamingFormat !== undefined) { + this.config.propertyNamingFormat = query.propertyNamingFormat as any; + } + if (query.modelNamingFormat !== undefined) { + this.config.modelNamingFormat = query.modelNamingFormat as any; + } + if (query.showTypeMappingExample !== undefined) { + this.config.showTypeMappingExample = query.showTypeMappingExample === 'true'; + } + if (query.indentationType !== undefined) { + this.config.indentationType = query.indentationType as any; + } + if (query.tsMarshalling !== undefined) { + this.config.tsMarshalling = query.tsMarshalling === 'true'; + } + if (query.tsModelType !== undefined) { + this.config.tsModelType = query.tsModelType as any; + } + if (query.tsEnumType !== undefined) { + this.config.tsEnumType = query.tsEnumType as any; + } + if (query.tsIncludeDescriptions !== undefined) { + this.config.tsIncludeDescriptions = + query.tsIncludeDescriptions === 'true'; + } + if (query.tsIncludeJsonBinPack !== undefined) { + this.config.tsIncludeJsonBinPack = + query.tsIncludeJsonBinPack === 'true'; + } + if (query.tsIncludeExampleFunction !== undefined) { + this.config.tsIncludeExampleFunction = + query.tsIncludeExampleFunction === 'true'; + } + if (query.csharpArrayType !== undefined) { + this.config.csharpArrayType = query.csharpArrayType as any; + } + if (query.csharpAutoImplemented !== undefined) { + this.config.csharpAutoImplemented = + query.csharpAutoImplemented === 'true'; + } + if (query.csharpOverwriteHashcode !== undefined) { + this.config.csharpOverwriteHashcode = + query.csharpOverwriteHashcode === 'true'; + } + if (query.phpIncludeDescriptions !== undefined) { + this.config.phpIncludeDescriptions = + query.phpIncludeDescriptions === 'true'; + } + if (query.phpNamespace !== undefined) { + this.config.phpNamespace = query.phpNamespace; + } + if (query.csharpIncludeJson !== undefined) { + this.config.csharpIncludeJson = + query.csharpIncludeJson === 'true'; + } + if (query.csharpOverwriteEqual !== undefined) { + this.config.csharpOverwriteEqual = + query.csharpOverwriteEqual === 'true'; + } + if (query.csharpIncludeNewtonsoft !== undefined) { + this.config.csharpIncludeNewtonsoft = + query.csharpIncludeNewtonsoft === 'true'; + } + if (query.csharpNamespace !== undefined) { + this.config.csharpNamespace = query.csharpNamespace; + } + if (query.csharpNullable !== undefined) { + this.config.csharpNullable = query.csharpNullable === 'true'; + } + if (query.cplusplusNamespace !== undefined) { + this.config.cplusplusNamespace = query.cplusplusNamespace; + } + if (query.javaPackageName !== undefined) { + this.config.javaPackageName = query.javaPackageName; + } + if (query.javaIncludeJackson !== undefined) { + this.config.javaIncludeJackson = + query.javaIncludeJackson === 'true'; + } + if (query.javaIncludeMarshaling !== undefined) { + this.config.javaIncludeMarshaling = + query.javaIncludeMarshaling === 'true'; + } + if (query.javaArrayType !== undefined) { + this.config.javaArrayType = query.javaArrayType as any; + } + if (query.javaOverwriteHashcode !== undefined) { + this.config.javaOverwriteHashcode = + query.javaOverwriteHashcode === 'true'; + } + if (query.javaOverwriteEqual !== undefined) { + this.config.javaOverwriteEqual = + query.javaOverwriteEqual === 'true'; + } + if (query.javaOverwriteToString !== undefined) { + this.config.javaOverwriteToString = + query.javaOverwriteToString === 'true'; + } + if (query.javaJavaDocs !== undefined) { + this.config.javaJavaDocs = + query.javaJavaDocs === 'true'; + } + if (query.javaJavaxAnnotation !== undefined) { + this.config.javaJavaxAnnotation = + query.javaJavaxAnnotation === 'true'; + } + if (query.goPackageName !== undefined) { + this.config.goPackageName = query.goPackageName; + } + if (query.kotlinPackageName !== undefined) { + this.config.kotlinPackageName = query.kotlinPackageName; + } + if (this.props.router.isReady && !this.hasLoadedQuery) { + this.hasLoadedQuery = true; + this.generateNewCode(this.state.input); + } + + let loader; + if (!isHardLoaded) { + loader = ( +
+ Loading Modelina Playground. Connecting to playground server... +
+ ); + } else if (!isSoftLoaded) { + loader = ( +
+ Loading Modelina Playground. Rendering playground components... +
+ ); + } + return ( +
+
+ + Modelina Playground + + + Try out Modelina and see a small fraction of what it can do. Use it + to play around, with small examples, otherwise turn to the CLI or + library instead. + +
+ {loader} +
+
+
+
+

+ Modelina Options +

+

+ Change the generation options, or see the Modelina + configuration you can use directly in your library +

+
+ +
{ + this.setState({ ...this.state, showGeneratorCode: false }); + }} + className={`${!this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' + } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} + > +

+ Options +

+
+
{ + this.setState({ ...this.state, showGeneratorCode: true }); + }} + className={`${this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' + } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} + > +

+ Generator code +

+
+
+ {this.state.showGeneratorCode ? ( +
+ +
+ ) : ( + + + + + + + + + + + + + + + + + + + + + + + + + + )} +
+
+
+ { + this.setState({ ...this.state, input: change }); + this.generateNewCode(change); + }} + editorDidMount={() => { + this.setState({ + loaded: { ...this.state.loaded, editorLoaded: true } + }); + }} + language="json" + /> +
+
+
+ {this.state.error ? ( + + ) : ( + + + + )} +
+
+
+ ); + } +} +export default withRouter(Playground); \ No newline at end of file diff --git a/modelina-website/src/pages/playground.tsx b/modelina-website/src/pages/playground.tsx index b3ef10d982..525ebc9493 100644 --- a/modelina-website/src/pages/playground.tsx +++ b/modelina-website/src/pages/playground.tsx @@ -1,4 +1,5 @@ import Playground from '@/components/playground/Playground'; +import NewPlayground from '@/components/playground/NewPlayground'; import GenericLayout from '@/components/layouts/GenericLayout'; export default function PlaygroundPage() { @@ -13,7 +14,8 @@ export default function PlaygroundPage() { wide full > - + {/* */} + ); } From 83a2b6626d463940b710018b396b2791240636d8 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Wed, 22 Nov 2023 20:15:19 +0530 Subject: [PATCH 02/29] created tooltip component for sidebar --- modelina-website/package-lock.json | 51 +++++++ modelina-website/package.json | 1 + .../components/playground/NewPlayground.tsx | 131 +----------------- .../src/components/playground/Sidebar.tsx | 0 .../src/components/playground/Tooltip.tsx | 17 +++ 5 files changed, 72 insertions(+), 128 deletions(-) create mode 100644 modelina-website/src/components/playground/Sidebar.tsx create mode 100644 modelina-website/src/components/playground/Tooltip.tsx diff --git a/modelina-website/package-lock.json b/modelina-website/package-lock.json index 5b679dcfec..3931642016 100644 --- a/modelina-website/package-lock.json +++ b/modelina-website/package-lock.json @@ -12,6 +12,7 @@ "@tailwindcss/forms": "^0.5.2", "@tailwindcss/line-clamp": "^0.4.0", "@tailwindcss/typography": "^0.5.9", + "@tippyjs/react": "^4.2.6", "cssnano": "^5.1.14", "js-base64": "^3.7.4", "lodash": "^4.17.21", @@ -389,6 +390,15 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rushstack/eslint-patch": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", @@ -444,6 +454,18 @@ "tailwindcss": ">=3.0.0 || insiders" } }, + "node_modules/@tippyjs/react": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@tippyjs/react/-/react-4.2.6.tgz", + "integrity": "sha512-91RicDR+H7oDSyPycI13q3b7o4O60wa2oRbjlz2fyRLmHImc4vyDwuUP8NtZaN0VARJY5hybvDYrFzhY9+Lbyw==", + "dependencies": { + "tippy.js": "^6.3.1" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -6318,6 +6340,14 @@ "node": ">=0.8" } }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7064,6 +7094,11 @@ "fastq": "^1.6.0" } }, + "@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" + }, "@rushstack/eslint-patch": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", @@ -7109,6 +7144,14 @@ "postcss-selector-parser": "6.0.10" } }, + "@tippyjs/react": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@tippyjs/react/-/react-4.2.6.tgz", + "integrity": "sha512-91RicDR+H7oDSyPycI13q3b7o4O60wa2oRbjlz2fyRLmHImc4vyDwuUP8NtZaN0VARJY5hybvDYrFzhY9+Lbyw==", + "requires": { + "tippy.js": "^6.3.1" + } + }, "@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -11124,6 +11167,14 @@ "thenify": ">= 3.1.0 < 4" } }, + "tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "requires": { + "@popperjs/core": "^2.9.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/modelina-website/package.json b/modelina-website/package.json index f098125689..5ccfa5455c 100644 --- a/modelina-website/package.json +++ b/modelina-website/package.json @@ -20,6 +20,7 @@ "@tailwindcss/forms": "^0.5.2", "@tailwindcss/line-clamp": "^0.4.0", "@tailwindcss/typography": "^0.5.9", + "@tippyjs/react": "^4.2.6", "cssnano": "^5.1.14", "js-base64": "^3.7.4", "lodash": "^4.17.21", diff --git a/modelina-website/src/components/playground/NewPlayground.tsx b/modelina-website/src/components/playground/NewPlayground.tsx index e08e5e2972..c97ca7cbf5 100644 --- a/modelina-website/src/components/playground/NewPlayground.tsx +++ b/modelina-website/src/components/playground/NewPlayground.tsx @@ -11,6 +11,7 @@ import Router, { withRouter, NextRouter } from 'next/router'; import { encode } from 'js-base64'; import GeneratedModelsComponent from './GeneratedModels'; import PlaygroundOptions from './PlaygroundOptions'; +import { Sidebar } from './Sidebar'; import Heading from '../typography/Heading'; import Paragraph from '../typography/Paragraph'; import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; @@ -357,134 +358,8 @@ class Playground extends React.Component< ); } return ( -
-
- - Modelina Playground - - - Try out Modelina and see a small fraction of what it can do. Use it - to play around, with small examples, otherwise turn to the CLI or - library instead. - -
- {loader} -
-
-
-
-

- Modelina Options -

-

- Change the generation options, or see the Modelina - configuration you can use directly in your library -

-
- -
{ - this.setState({ ...this.state, showGeneratorCode: false }); - }} - className={`${!this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' - } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - > -

- Options -

-
-
{ - this.setState({ ...this.state, showGeneratorCode: true }); - }} - className={`${this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' - } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - > -

- Generator code -

-
-
- {this.state.showGeneratorCode ? ( -
- -
- ) : ( - - - - - - - - - - - - - - - - - - - - - - - - - - )} -
-
-
- { - this.setState({ ...this.state, input: change }); - this.generateNewCode(change); - }} - editorDidMount={() => { - this.setState({ - loaded: { ...this.state.loaded, editorLoaded: true } - }); - }} - language="json" - /> -
-
-
- {this.state.error ? ( - - ) : ( - - - - )} -
-
+
+
); } diff --git a/modelina-website/src/components/playground/Sidebar.tsx b/modelina-website/src/components/playground/Sidebar.tsx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modelina-website/src/components/playground/Tooltip.tsx b/modelina-website/src/components/playground/Tooltip.tsx new file mode 100644 index 0000000000..e80b172f52 --- /dev/null +++ b/modelina-website/src/components/playground/Tooltip.tsx @@ -0,0 +1,17 @@ +import Tippy, { TippyProps } from '@tippyjs/react'; + +export const Tooltip: React.FunctionComponent = ({ + placement = 'bottom', + arrow = true, + animation = 'shift-away', + className = 'text-xs bg-gray-900 text-center', + hideOnClick = false, + children, + ...rest +}) => { + return ( + + {children} + + ) +} \ No newline at end of file From 0b17766135536b792e1aa1ebbee2322d0c41befb Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Wed, 22 Nov 2023 21:48:00 +0530 Subject: [PATCH 03/29] added basic navigation layout --- modelina-website/package-lock.json | 15 +++++ modelina-website/package.json | 1 + .../components/playground/NewPlayground.tsx | 2 +- .../src/components/playground/Sidebar.tsx | 57 +++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/modelina-website/package-lock.json b/modelina-website/package-lock.json index 3931642016..343dfd77d8 100644 --- a/modelina-website/package-lock.json +++ b/modelina-website/package-lock.json @@ -21,6 +21,7 @@ "postcss": "^8.4.31", "react": "18.2.0", "react-dom": "18.2.0", + "react-icons": "^4.12.0", "react-markdown": "^8.0.7", "react-syntax-highlighter": "15.5.0", "rehype-raw": "^6.1.1", @@ -5498,6 +5499,14 @@ "react": "^18.2.0" } }, + "node_modules/react-icons": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", + "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -10574,6 +10583,12 @@ "scheduler": "^0.23.0" } }, + "react-icons": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", + "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", + "requires": {} + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/modelina-website/package.json b/modelina-website/package.json index 5ccfa5455c..4806ccb794 100644 --- a/modelina-website/package.json +++ b/modelina-website/package.json @@ -29,6 +29,7 @@ "postcss": "^8.4.31", "react": "18.2.0", "react-dom": "18.2.0", + "react-icons": "^4.12.0", "react-markdown": "^8.0.7", "react-syntax-highlighter": "15.5.0", "rehype-raw": "^6.1.1", diff --git a/modelina-website/src/components/playground/NewPlayground.tsx b/modelina-website/src/components/playground/NewPlayground.tsx index c97ca7cbf5..a41a6286b5 100644 --- a/modelina-website/src/components/playground/NewPlayground.tsx +++ b/modelina-website/src/components/playground/NewPlayground.tsx @@ -358,7 +358,7 @@ class Playground extends React.Component< ); } return ( -
+
); diff --git a/modelina-website/src/components/playground/Sidebar.tsx b/modelina-website/src/components/playground/Sidebar.tsx index e69de29bb2..c917098e1d 100644 --- a/modelina-website/src/components/playground/Sidebar.tsx +++ b/modelina-website/src/components/playground/Sidebar.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { IoOptionsOutline } from "react-icons/io5"; +import { VscListSelection } from "react-icons/vsc"; +import { Tooltip } from './Tooltip'; + +interface SidebarItem { + name: string; + title: string; + isActive: boolean; + onClick: () => void; + icon: React.ReactNode; + tooltip: React.ReactNode; +} + +interface SidebarProps { } + +export const Sidebar: React.FunctionComponent = () => { + + const sidebarItems: SidebarItem[] = [ + // Options + { + name: 'options', + title: 'Options', + isActive: false, + onClick: () => { }, + icon: , + tooltip: 'Option' + }, + // Output Navigation + { + name: 'outputNavigation', + title: 'Output', + isActive: false, + onClick: () => { }, + icon: , + tooltip: 'Output' + }, + ] + + return ( +
+
+ { + sidebarItems.map((item) => ( + + + + )) + } +
+
+ ) +} \ No newline at end of file From 2b3f6ca1b00425fbf605d376ac1f5c74b26af85c Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Sat, 25 Nov 2023 11:26:32 +0530 Subject: [PATCH 04/29] added code for splitpane --- .../components/playground/SplitPane/Pane.tsx | 34 ++ .../components/playground/SplitPane/Readme.md | 9 + .../playground/SplitPane/Resizer.tsx | 54 +++ .../playground/SplitPane/SplitPane.tsx | 322 ++++++++++++++++++ .../components/playground/SplitPane/index.tsx | 7 + .../src/components/playground/Tooltip.tsx | 2 +- 6 files changed, 427 insertions(+), 1 deletion(-) create mode 100644 modelina-website/src/components/playground/SplitPane/Pane.tsx create mode 100644 modelina-website/src/components/playground/SplitPane/Readme.md create mode 100644 modelina-website/src/components/playground/SplitPane/Resizer.tsx create mode 100644 modelina-website/src/components/playground/SplitPane/SplitPane.tsx create mode 100644 modelina-website/src/components/playground/SplitPane/index.tsx diff --git a/modelina-website/src/components/playground/SplitPane/Pane.tsx b/modelina-website/src/components/playground/SplitPane/Pane.tsx new file mode 100644 index 0000000000..7b6bbf14e4 --- /dev/null +++ b/modelina-website/src/components/playground/SplitPane/Pane.tsx @@ -0,0 +1,34 @@ +/* eslint-disable */ +// @ts-nocheck + +function Pane(props) { + const { children, className, split, style: styleProps, size, eleRef } = props; + + const classes = ['Pane', split, className]; + + let style = { + flex: 1, + position: 'relative', + outline: 'none', + }; + + if (size !== undefined) { + if (split === 'vertical') { + style.width = size; + } else { + style.height = size; + style.display = 'flex'; + } + style.flex = 'none'; + } + + style = Object.assign({}, style, styleProps || {}); + + return ( +
+ {children} +
+ ); +} + +export default Pane; \ No newline at end of file diff --git a/modelina-website/src/components/playground/SplitPane/Readme.md b/modelina-website/src/components/playground/SplitPane/Readme.md new file mode 100644 index 0000000000..bef5d6984a --- /dev/null +++ b/modelina-website/src/components/playground/SplitPane/Readme.md @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2022 Jeremy Grieshop + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/modelina-website/src/components/playground/SplitPane/Resizer.tsx b/modelina-website/src/components/playground/SplitPane/Resizer.tsx new file mode 100644 index 0000000000..3a4f766aa2 --- /dev/null +++ b/modelina-website/src/components/playground/SplitPane/Resizer.tsx @@ -0,0 +1,54 @@ +/* eslint-disable */ +// @ts-nocheck + +export const RESIZER_DEFAULT_CLASSNAME = 'Resizer'; + +function Resizer(props) { + const { + className, + onClick, + onDoubleClick, + onMouseDown, + onTouchEnd, + onTouchStart, + resizerClassName, + split, + style, + } = props; + const classes = [resizerClassName, split, className]; + + return ( + onMouseDown(event)} + onTouchStart={event => { + event.preventDefault(); + onTouchStart(event); + }} + onTouchEnd={event => { + event.preventDefault(); + onTouchEnd(event); + }} + onClick={event => { + if (onClick) { + event.preventDefault(); + onClick(event); + } + }} + onDoubleClick={event => { + if (onDoubleClick) { + event.preventDefault(); + onDoubleClick(event); + } + }} + /> + ); +} + +Resizer.defaultProps = { + resizerClassName: RESIZER_DEFAULT_CLASSNAME, +}; + +export default Resizer; \ No newline at end of file diff --git a/modelina-website/src/components/playground/SplitPane/SplitPane.tsx b/modelina-website/src/components/playground/SplitPane/SplitPane.tsx new file mode 100644 index 0000000000..526a80686f --- /dev/null +++ b/modelina-website/src/components/playground/SplitPane/SplitPane.tsx @@ -0,0 +1,322 @@ +/* eslint-disable */ +// @ts-nocheck + +import React, { useEffect, useState, useCallback, useRef } from 'react'; + +import Pane from './Pane'; +import Resizer, { RESIZER_DEFAULT_CLASSNAME } from './Resizer'; + +function unFocus(document, window) { + if (document.selection) { + document.selection.empty(); + } else { + try { + window.getSelection().removeAllRanges(); + // eslint-disable-next-line no-empty + } catch (e) {} + } +} + +function getDefaultSize(defaultSize, minSize, maxSize, draggedSize) { + if (typeof draggedSize === 'number') { + const min = typeof minSize === 'number' ? minSize : 0; + const max = typeof maxSize === 'number' && maxSize >= 0 ? maxSize : Infinity; + return Math.max(min, Math.min(max, draggedSize)); + } + if (defaultSize !== undefined) { + return defaultSize; + } + return minSize; +} + +function removeNullChildren(children) { + return React.Children.toArray(children).filter(c => c); +} + +function SplitPane(props) { + const { + allowResize = true, + children, + className, + defaultSize, + minSize = 50, + maxSize, + onChange, + onDragFinished, + onDragStarted, + onResizerClick, + onResizerDoubleClick, + paneClassName = '', + pane1ClassName = '', + pane2ClassName = '', + paneStyle, + primary = 'first', + pane1Style: pane1StyleProps, + pane2Style: pane2StyleProps, + resizerClassName, + resizerStyle, + size, + split = 'vertical', + step, + style: styleProps, + } = props; + + const initialSize = + size !== undefined ? size : getDefaultSize(defaultSize, minSize, maxSize, null); + + const [active, setActive] = useState(false); + const [, setResized] = useState(false); + const [pane1Size, setPane1Size] = useState(primary === 'first' ? initialSize : undefined); + const [pane2Size, setPane2Size] = useState(primary === 'second' ? initialSize : undefined); + const [draggedSize, setDraggedSize] = useState(); + const [position, setPosition] = useState(); + + const splitPane = useRef(); + const pane1 = useRef(); + const pane2 = useRef(); + const instanceProps = useRef({ size }); + + const getSizeUpdate = useCallback(() => { + if (instanceProps.current.size === size && size !== undefined) { + return undefined; + } + + const newSize = + size !== undefined ? size : getDefaultSize(defaultSize, minSize, maxSize, draggedSize); + + if (size !== undefined) { + setDraggedSize(newSize); + } + + const isPanel1Primary = primary === 'first'; + if (isPanel1Primary) { + setPane1Size(newSize); + setPane2Size(undefined); + } else { + setPane2Size(newSize); + setPane1Size(undefined); + } + + instanceProps.current.size = newSize; + }, [defaultSize, draggedSize, maxSize, minSize, primary, size]); + + const onMouseUp = useCallback(() => { + if (allowResize && active) { + if (typeof onDragFinished === 'function') { + onDragFinished(draggedSize); + } + setActive(false); + } + }, [active, allowResize, draggedSize, onDragFinished]); + + const onTouchMove = useCallback( + event => { + if (allowResize && active) { + unFocus(document, window); + const isPrimaryFirst = primary === 'first'; + const ref = isPrimaryFirst ? pane1.current : pane2.current; + const ref2 = isPrimaryFirst ? pane2.current : pane1.current; + if (ref) { + const node = ref; + const node2 = ref2; + + if (node.getBoundingClientRect) { + const width = node.getBoundingClientRect().width; + const height = node.getBoundingClientRect().height; + const current = + split === 'vertical' ? event.touches[0].clientX : event.touches[0].clientY; + const size = split === 'vertical' ? width : height; + let positionDelta = position - current; + if (step) { + if (Math.abs(positionDelta) < step) { + return; + } + // Integer division + // eslint-disable-next-line no-bitwise + positionDelta = ~~(positionDelta / step) * step; + } + let sizeDelta = isPrimaryFirst ? positionDelta : -positionDelta; + + const pane1Order = parseInt(window.getComputedStyle(node).order); + const pane2Order = parseInt(window.getComputedStyle(node2).order); + if (pane1Order > pane2Order) { + sizeDelta = -sizeDelta; + } + + let newMaxSize = maxSize; + if (maxSize !== undefined && maxSize <= 0) { + if (split === 'vertical') { + newMaxSize = splitPane.current.getBoundingClientRect().width + maxSize; + } else { + newMaxSize = splitPane.current.getBoundingClientRect().height + maxSize; + } + } + + let newSize = size - sizeDelta; + const newPosition = position - positionDelta; + + if (newSize < minSize) { + newSize = minSize; + } else if (maxSize !== undefined && newSize > newMaxSize) { + newSize = newMaxSize; + } else { + setPosition(newPosition); + setResized(true); + } + + if (onChange) onChange(newSize); + + setDraggedSize(newSize); + if (isPrimaryFirst) setPane1Size(newSize); + else setPane2Size(newSize); + } + } + } + }, + [active, allowResize, maxSize, minSize, onChange, position, primary, split, step], + ); + + const onMouseMove = useCallback( + event => { + const eventWithTouches = Object.assign({}, event, { + touches: [{ clientX: event.clientX, clientY: event.clientY }], + }); + onTouchMove(eventWithTouches); + }, + [onTouchMove], + ); + + const onTouchStart = useCallback( + event => { + if (allowResize) { + unFocus(document, window); + const position = split === 'vertical' ? event.touches[0].clientX : event.touches[0].clientY; + + if (typeof onDragStarted === 'function') { + onDragStarted(); + } + setActive(true); + setPosition(position); + } + }, + [allowResize, onDragStarted, split], + ); + + const onMouseDown = useCallback( + event => { + const eventWithTouches = Object.assign({}, event, { + touches: [{ clientX: event.clientX, clientY: event.clientY }], + }); + onTouchStart(eventWithTouches); + }, + [onTouchStart], + ); + + useEffect(() => { + document.addEventListener('mouseup', onMouseUp); + document.addEventListener('mousemove', onMouseMove); + document.addEventListener('touchmove', onTouchMove); + + getSizeUpdate(); + + return () => { + document.removeEventListener('mouseup', onMouseUp); + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('touchmove', onTouchMove); + }; + }, [onMouseUp, onMouseMove, onTouchMove, getSizeUpdate]); + + const disabledClass = allowResize ? '' : 'disabled'; + const resizerClassNamesIncludingDefault = resizerClassName + ? `${resizerClassName} ${RESIZER_DEFAULT_CLASSNAME}` + : resizerClassName; + + const notNullChildren = removeNullChildren(children); + + const style = { + display: 'flex', + flex: 1, + height: '100%', + position: 'absolute', + outline: 'none', + overflow: 'hidden', + MozUserSelect: 'text', + WebkitUserSelect: 'text', + msUserSelect: 'text', + userSelect: 'text', + ...styleProps, + }; + + if (split === 'vertical') { + Object.assign(style, { + flexDirection: 'row', + left: 0, + right: 0, + }); + } else { + Object.assign(style, { + bottom: 0, + flexDirection: 'column', + minHeight: '100%', + top: 0, + width: '100%', + }); + } + + const classes = ['SplitPane', className, split, disabledClass]; + + const pane1Style = { ...paneStyle, ...pane1StyleProps }; + const pane2Style = { ...paneStyle, ...pane2StyleProps }; + + const pane1Classes = ['Pane1', paneClassName, pane1ClassName].join(' '); + const pane2Classes = ['Pane2', paneClassName, pane2ClassName].join(' '); + + return ( +
{ + splitPane.current = node; + }} + style={style} + > + { + pane1.current = node; + }} + size={pane1Size} + split={split} + style={pane1Style} + > + {notNullChildren[0]} + + + { + pane2.current = node; + }} + size={pane2Size} + split={split} + style={pane2Style} + > + {notNullChildren[1]} + +
+ ); +} + +export default SplitPane; \ No newline at end of file diff --git a/modelina-website/src/components/playground/SplitPane/index.tsx b/modelina-website/src/components/playground/SplitPane/index.tsx new file mode 100644 index 0000000000..18bcb3786a --- /dev/null +++ b/modelina-website/src/components/playground/SplitPane/index.tsx @@ -0,0 +1,7 @@ +import ReactSplitPane from './SplitPane'; +import Pane from './Pane'; +/** + * Implementation from https://github.com/JeremyGrieshop/react-split-pane/blob/main/SplitPane.js + */ +export default ReactSplitPane; +export { Pane }; \ No newline at end of file diff --git a/modelina-website/src/components/playground/Tooltip.tsx b/modelina-website/src/components/playground/Tooltip.tsx index e80b172f52..d3e06c0e76 100644 --- a/modelina-website/src/components/playground/Tooltip.tsx +++ b/modelina-website/src/components/playground/Tooltip.tsx @@ -4,7 +4,7 @@ export const Tooltip: React.FunctionComponent = ({ placement = 'bottom', arrow = true, animation = 'shift-away', - className = 'text-xs bg-gray-900 text-center', + className = 'text-xs text-white bg-gray-900 text-center p-[2px]', hideOnClick = false, children, ...rest From 09c4e9917e90fe25c56fba9693ff05a13d839faf Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Sat, 25 Nov 2023 13:48:28 +0530 Subject: [PATCH 05/29] added basic editor-output-explorer layout --- .../src/components/playground/Content.tsx | 71 +++++++++++++++++++ .../components/playground/NewPlayground.tsx | 8 ++- .../src/components/playground/Sidebar.tsx | 67 ++++++++++------- modelina-website/src/helpers/debounce.ts | 29 ++++++++ 4 files changed, 146 insertions(+), 29 deletions(-) create mode 100644 modelina-website/src/components/playground/Content.tsx create mode 100644 modelina-website/src/helpers/debounce.ts diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx new file mode 100644 index 0000000000..3ee7e51b3b --- /dev/null +++ b/modelina-website/src/components/playground/Content.tsx @@ -0,0 +1,71 @@ +import { FunctionComponent } from 'react'; +import SplitPane from './SplitPane'; +import { debounce } from '@/helpers/debounce'; + +interface ContentProps {} + +export const Content: FunctionComponent = () => { + const explorerEnabled = true; + const optionEnabled = true; + const navigationEnabled = explorerEnabled || optionEnabled; + const editorViewEnabled = true; + const outputViewEnabled = true; + + const splitPosLeft = 'splitPos:left'; + const splitPosRight = 'splitPos:right'; + + const localStorageLeftPaneSize = + parseInt(localStorage.getItem(splitPosLeft) || '0', 10) || 220; + const localStorageRightPaneSize = + parseInt(localStorage.getItem(splitPosRight) || '0', 10) || '55%'; + + const secondPaneSize = + navigationEnabled && !editorViewEnabled + ? localStorageLeftPaneSize + : localStorageRightPaneSize; + const secondPaneMaxSize = + navigationEnabled && !editorViewEnabled ? 360 : '100%'; + + const navigationAndEditor = ( + { + localStorage.setItem(splitPosLeft, String(size)); + }, 100)} + > +
Navigation
+
Editor
+
+ ); + return ( +
+
+ { + localStorage.setItem(splitPosRight, String(size)); + }, 100)} + > + {navigationAndEditor} +
Output
+
+
+
+ ); +}; diff --git a/modelina-website/src/components/playground/NewPlayground.tsx b/modelina-website/src/components/playground/NewPlayground.tsx index a41a6286b5..a109f7fbf7 100644 --- a/modelina-website/src/components/playground/NewPlayground.tsx +++ b/modelina-website/src/components/playground/NewPlayground.tsx @@ -41,6 +41,7 @@ import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGene import CustomError from '../CustomError'; import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; +import { Content } from './Content'; interface WithRouterProps { router: NextRouter; @@ -358,8 +359,11 @@ class Playground extends React.Component< ); } return ( -
- +
+
+ + +
); } diff --git a/modelina-website/src/components/playground/Sidebar.tsx b/modelina-website/src/components/playground/Sidebar.tsx index c917098e1d..3fad8e956a 100644 --- a/modelina-website/src/components/playground/Sidebar.tsx +++ b/modelina-website/src/components/playground/Sidebar.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { IoOptionsOutline } from "react-icons/io5"; -import { VscListSelection } from "react-icons/vsc"; +import { IoOptionsOutline } from 'react-icons/io5'; +import { VscListSelection } from 'react-icons/vsc'; import { Tooltip } from './Tooltip'; interface SidebarItem { @@ -12,46 +12,59 @@ interface SidebarItem { tooltip: React.ReactNode; } -interface SidebarProps { } +interface SidebarProps {} export const Sidebar: React.FunctionComponent = () => { - const sidebarItems: SidebarItem[] = [ // Options { name: 'options', title: 'Options', isActive: false, - onClick: () => { }, - icon: , + onClick: () => {}, + icon: , tooltip: 'Option' }, - // Output Navigation + // Output Explorer { - name: 'outputNavigation', + name: 'outputExplorer', title: 'Output', isActive: false, - onClick: () => { }, - icon: , + onClick: () => {}, + icon: , tooltip: 'Output' - }, - ] + } + ]; return ( -
-
- { - sidebarItems.map((item) => ( - - - - )) - } +
+
+ {sidebarItems.map((item) => ( + + + + ))}
- ) -} \ No newline at end of file + ); +}; diff --git a/modelina-website/src/helpers/debounce.ts b/modelina-website/src/helpers/debounce.ts new file mode 100644 index 0000000000..9677e07783 --- /dev/null +++ b/modelina-website/src/helpers/debounce.ts @@ -0,0 +1,29 @@ +export function debounce( + func: (...args: any[]) => any, + wait: number, + immediate?: boolean +): (...args: any[]) => any { + let timeout: number | null; + + return function executedFunction(this: any, ...args: any[]) { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const context = this; + + const later = function () { + timeout = null; + if (!immediate) { + func.apply(context, args); + } + }; + + const callNow = immediate && !timeout; + + // eslint-disable-next-line no-unused-expressions + timeout && clearTimeout(timeout); + timeout = setTimeout(later, wait) as unknown as number; + + if (callNow) { + func.apply(context, args); + } + }; +} From d3241776c415544037ca90fc813e6df43a23d264 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Sun, 26 Nov 2023 18:00:31 +0530 Subject: [PATCH 06/29] added context and functionality for opening and closing of options and output menu --- .../contexts/PlaygroundPanelContext.tsx | 37 +++++++++ .../src/components/playground/Content.tsx | 81 +++++++++++-------- .../components/playground/NewPlayground.tsx | 9 ++- .../src/components/playground/Sidebar.tsx | 10 ++- 4 files changed, 97 insertions(+), 40 deletions(-) create mode 100644 modelina-website/src/components/contexts/PlaygroundPanelContext.tsx diff --git a/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx b/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx new file mode 100644 index 0000000000..d59af2e3a7 --- /dev/null +++ b/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx @@ -0,0 +1,37 @@ +'use client'; +import React, { + createContext, + useContext, + Dispatch, + SetStateAction, + useState +} from 'react'; + +interface PanelContextProps { + panel: string; + setPanel: Dispatch>; +} + +const PanelContext = createContext({ + panel: '' || 'options' || 'output', + setPanel: (): string => '' +}); + +export const PanelContextProvider: React.FC<{ + children: React.ReactNode; +}> = ({ children }) => { + const [panel, setPanel] = useState(''); + return ( + + {children} + + ); +}; + +export const usePanelContext = (): PanelContextProps => + useContext(PanelContext); diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index 3ee7e51b3b..1fbed96d07 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -1,46 +1,61 @@ +'use client'; + import { FunctionComponent } from 'react'; import SplitPane from './SplitPane'; import { debounce } from '@/helpers/debounce'; - +import { usePanelContext } from '../contexts/PlaygroundPanelContext'; interface ContentProps {} export const Content: FunctionComponent = () => { - const explorerEnabled = true; - const optionEnabled = true; - const navigationEnabled = explorerEnabled || optionEnabled; - const editorViewEnabled = true; - const outputViewEnabled = true; - const splitPosLeft = 'splitPos:left'; const splitPosRight = 'splitPos:right'; - const localStorageLeftPaneSize = - parseInt(localStorage.getItem(splitPosLeft) || '0', 10) || 220; - const localStorageRightPaneSize = - parseInt(localStorage.getItem(splitPosRight) || '0', 10) || '55%'; + // const localStorageLeftPaneSize = + // parseInt(localStorage.getItem(splitPosLeft) || '0', 10) || 220; + // const localStorageRightPaneSize = + // parseInt(localStorage.getItem(splitPosRight) || '0', 10) || '55%'; + + const localStorageLeftPaneSize = 220; + const localStorageRightPaneSize = '55%'; + + const { panel } = usePanelContext(); + + const panelEnabled = panel !== ''; + const editorViewEnabled = true; + const outputViewEnabled = true; const secondPaneSize = - navigationEnabled && !editorViewEnabled + panelEnabled && !editorViewEnabled ? localStorageLeftPaneSize : localStorageRightPaneSize; - const secondPaneMaxSize = - navigationEnabled && !editorViewEnabled ? 360 : '100%'; + const secondPaneMaxSize = panelEnabled && !editorViewEnabled ? 360 : '100%'; - const navigationAndEditor = ( - { - localStorage.setItem(splitPosLeft, String(size)); - }, 100)} - > -
Navigation
-
Editor
-
- ); + const handleLeftPaneChange = debounce((size: string) => { + localStorage.setItem(splitPosLeft, String(size)); + }, 100); + + const handleRightPaneChange = debounce((size: string) => { + localStorage.setItem(splitPosRight, String(size)); + }, 100); + + const navigationAndEditor = + panel === '' ? ( +
Editor
+ ) : ( + + {panel !== '' ? ( +
Navigation
+ ) : null} +
Editor
+
+ ); return (
@@ -49,18 +64,14 @@ export const Content: FunctionComponent = () => { minSize={0} maxSize={secondPaneMaxSize} pane1Style={ - navigationEnabled || editorViewEnabled - ? undefined - : { width: '0px' } + panelEnabled || editorViewEnabled ? undefined : { width: '0px' } } pane2Style={ outputViewEnabled ? { overflow: 'auto' } : { width: '0px' } } primary={outputViewEnabled ? 'first' : 'second'} defaultSize={localStorageRightPaneSize} - onChange={debounce((size: string) => { - localStorage.setItem(splitPosRight, String(size)); - }, 100)} + onChange={handleRightPaneChange} > {navigationAndEditor}
Output
diff --git a/modelina-website/src/components/playground/NewPlayground.tsx b/modelina-website/src/components/playground/NewPlayground.tsx index a109f7fbf7..0972fd0322 100644 --- a/modelina-website/src/components/playground/NewPlayground.tsx +++ b/modelina-website/src/components/playground/NewPlayground.tsx @@ -29,6 +29,7 @@ import { PlaygroundGeneralConfigContext, PlaygroundPhpConfigContext } from '../contexts/PlaygroundConfigContext'; +import { PanelContextProvider } from '../contexts/PlaygroundPanelContext'; import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; @@ -361,11 +362,13 @@ class Playground extends React.Component< return (
- - + + + +
); } } -export default withRouter(Playground); \ No newline at end of file +export default withRouter(Playground); diff --git a/modelina-website/src/components/playground/Sidebar.tsx b/modelina-website/src/components/playground/Sidebar.tsx index 3fad8e956a..7408a431b2 100644 --- a/modelina-website/src/components/playground/Sidebar.tsx +++ b/modelina-website/src/components/playground/Sidebar.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { IoOptionsOutline } from 'react-icons/io5'; import { VscListSelection } from 'react-icons/vsc'; import { Tooltip } from './Tooltip'; +import { usePanelContext } from '../contexts/PlaygroundPanelContext'; interface SidebarItem { name: string; @@ -15,13 +16,16 @@ interface SidebarItem { interface SidebarProps {} export const Sidebar: React.FunctionComponent = () => { + const { panel, setPanel } = usePanelContext(); const sidebarItems: SidebarItem[] = [ // Options { name: 'options', title: 'Options', isActive: false, - onClick: () => {}, + onClick: () => { + setPanel(panel !== 'options' ? 'options' : ''); + }, icon: , tooltip: 'Option' }, @@ -30,7 +34,9 @@ export const Sidebar: React.FunctionComponent = () => { name: 'outputExplorer', title: 'Output', isActive: false, - onClick: () => {}, + onClick: () => { + setPanel(panel !== 'output' ? 'output' : ''); + }, icon: , tooltip: 'Output' } From 6f64b35c224c27836028412903aea4550639dd8a Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Thu, 30 Nov 2023 12:37:47 +0530 Subject: [PATCH 07/29] removed split-pane and created mobile responsive layout --- .../src/components/playground/Content.tsx | 80 +---- .../components/playground/SplitPane/Pane.tsx | 34 -- .../components/playground/SplitPane/Readme.md | 9 - .../playground/SplitPane/Resizer.tsx | 54 --- .../playground/SplitPane/SplitPane.tsx | 322 ------------------ .../components/playground/SplitPane/index.tsx | 7 - .../src/components/playground/Tooltip.tsx | 14 +- modelina-website/src/helpers/debounce.ts | 29 -- 8 files changed, 25 insertions(+), 524 deletions(-) delete mode 100644 modelina-website/src/components/playground/SplitPane/Pane.tsx delete mode 100644 modelina-website/src/components/playground/SplitPane/Readme.md delete mode 100644 modelina-website/src/components/playground/SplitPane/Resizer.tsx delete mode 100644 modelina-website/src/components/playground/SplitPane/SplitPane.tsx delete mode 100644 modelina-website/src/components/playground/SplitPane/index.tsx delete mode 100644 modelina-website/src/helpers/debounce.ts diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index 1fbed96d07..c8078c2c90 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -1,81 +1,29 @@ 'use client'; import { FunctionComponent } from 'react'; -import SplitPane from './SplitPane'; -import { debounce } from '@/helpers/debounce'; import { usePanelContext } from '../contexts/PlaygroundPanelContext'; interface ContentProps {} export const Content: FunctionComponent = () => { - const splitPosLeft = 'splitPos:left'; - const splitPosRight = 'splitPos:right'; - - // const localStorageLeftPaneSize = - // parseInt(localStorage.getItem(splitPosLeft) || '0', 10) || 220; - // const localStorageRightPaneSize = - // parseInt(localStorage.getItem(splitPosRight) || '0', 10) || '55%'; - - const localStorageLeftPaneSize = 220; - const localStorageRightPaneSize = '55%'; - const { panel } = usePanelContext(); const panelEnabled = panel !== ''; - const editorViewEnabled = true; - const outputViewEnabled = true; - - const secondPaneSize = - panelEnabled && !editorViewEnabled - ? localStorageLeftPaneSize - : localStorageRightPaneSize; - const secondPaneMaxSize = panelEnabled && !editorViewEnabled ? 360 : '100%'; - - const handleLeftPaneChange = debounce((size: string) => { - localStorage.setItem(splitPosLeft, String(size)); - }, 100); - - const handleRightPaneChange = debounce((size: string) => { - localStorage.setItem(splitPosRight, String(size)); - }, 100); - - const navigationAndEditor = - panel === '' ? ( -
Editor
- ) : ( - - {panel !== '' ? ( -
Navigation
- ) : null} -
Editor
-
- ); return ( -
-
- +
+ {panelEnabled ? ( +
+ Navigation +
+ ) : null} +
- {navigationAndEditor} -
Output
- +
Editor
+
Output
+
); diff --git a/modelina-website/src/components/playground/SplitPane/Pane.tsx b/modelina-website/src/components/playground/SplitPane/Pane.tsx deleted file mode 100644 index 7b6bbf14e4..0000000000 --- a/modelina-website/src/components/playground/SplitPane/Pane.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck - -function Pane(props) { - const { children, className, split, style: styleProps, size, eleRef } = props; - - const classes = ['Pane', split, className]; - - let style = { - flex: 1, - position: 'relative', - outline: 'none', - }; - - if (size !== undefined) { - if (split === 'vertical') { - style.width = size; - } else { - style.height = size; - style.display = 'flex'; - } - style.flex = 'none'; - } - - style = Object.assign({}, style, styleProps || {}); - - return ( -
- {children} -
- ); -} - -export default Pane; \ No newline at end of file diff --git a/modelina-website/src/components/playground/SplitPane/Readme.md b/modelina-website/src/components/playground/SplitPane/Readme.md deleted file mode 100644 index bef5d6984a..0000000000 --- a/modelina-website/src/components/playground/SplitPane/Readme.md +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) 2022 Jeremy Grieshop - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/modelina-website/src/components/playground/SplitPane/Resizer.tsx b/modelina-website/src/components/playground/SplitPane/Resizer.tsx deleted file mode 100644 index 3a4f766aa2..0000000000 --- a/modelina-website/src/components/playground/SplitPane/Resizer.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck - -export const RESIZER_DEFAULT_CLASSNAME = 'Resizer'; - -function Resizer(props) { - const { - className, - onClick, - onDoubleClick, - onMouseDown, - onTouchEnd, - onTouchStart, - resizerClassName, - split, - style, - } = props; - const classes = [resizerClassName, split, className]; - - return ( - onMouseDown(event)} - onTouchStart={event => { - event.preventDefault(); - onTouchStart(event); - }} - onTouchEnd={event => { - event.preventDefault(); - onTouchEnd(event); - }} - onClick={event => { - if (onClick) { - event.preventDefault(); - onClick(event); - } - }} - onDoubleClick={event => { - if (onDoubleClick) { - event.preventDefault(); - onDoubleClick(event); - } - }} - /> - ); -} - -Resizer.defaultProps = { - resizerClassName: RESIZER_DEFAULT_CLASSNAME, -}; - -export default Resizer; \ No newline at end of file diff --git a/modelina-website/src/components/playground/SplitPane/SplitPane.tsx b/modelina-website/src/components/playground/SplitPane/SplitPane.tsx deleted file mode 100644 index 526a80686f..0000000000 --- a/modelina-website/src/components/playground/SplitPane/SplitPane.tsx +++ /dev/null @@ -1,322 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck - -import React, { useEffect, useState, useCallback, useRef } from 'react'; - -import Pane from './Pane'; -import Resizer, { RESIZER_DEFAULT_CLASSNAME } from './Resizer'; - -function unFocus(document, window) { - if (document.selection) { - document.selection.empty(); - } else { - try { - window.getSelection().removeAllRanges(); - // eslint-disable-next-line no-empty - } catch (e) {} - } -} - -function getDefaultSize(defaultSize, minSize, maxSize, draggedSize) { - if (typeof draggedSize === 'number') { - const min = typeof minSize === 'number' ? minSize : 0; - const max = typeof maxSize === 'number' && maxSize >= 0 ? maxSize : Infinity; - return Math.max(min, Math.min(max, draggedSize)); - } - if (defaultSize !== undefined) { - return defaultSize; - } - return minSize; -} - -function removeNullChildren(children) { - return React.Children.toArray(children).filter(c => c); -} - -function SplitPane(props) { - const { - allowResize = true, - children, - className, - defaultSize, - minSize = 50, - maxSize, - onChange, - onDragFinished, - onDragStarted, - onResizerClick, - onResizerDoubleClick, - paneClassName = '', - pane1ClassName = '', - pane2ClassName = '', - paneStyle, - primary = 'first', - pane1Style: pane1StyleProps, - pane2Style: pane2StyleProps, - resizerClassName, - resizerStyle, - size, - split = 'vertical', - step, - style: styleProps, - } = props; - - const initialSize = - size !== undefined ? size : getDefaultSize(defaultSize, minSize, maxSize, null); - - const [active, setActive] = useState(false); - const [, setResized] = useState(false); - const [pane1Size, setPane1Size] = useState(primary === 'first' ? initialSize : undefined); - const [pane2Size, setPane2Size] = useState(primary === 'second' ? initialSize : undefined); - const [draggedSize, setDraggedSize] = useState(); - const [position, setPosition] = useState(); - - const splitPane = useRef(); - const pane1 = useRef(); - const pane2 = useRef(); - const instanceProps = useRef({ size }); - - const getSizeUpdate = useCallback(() => { - if (instanceProps.current.size === size && size !== undefined) { - return undefined; - } - - const newSize = - size !== undefined ? size : getDefaultSize(defaultSize, minSize, maxSize, draggedSize); - - if (size !== undefined) { - setDraggedSize(newSize); - } - - const isPanel1Primary = primary === 'first'; - if (isPanel1Primary) { - setPane1Size(newSize); - setPane2Size(undefined); - } else { - setPane2Size(newSize); - setPane1Size(undefined); - } - - instanceProps.current.size = newSize; - }, [defaultSize, draggedSize, maxSize, minSize, primary, size]); - - const onMouseUp = useCallback(() => { - if (allowResize && active) { - if (typeof onDragFinished === 'function') { - onDragFinished(draggedSize); - } - setActive(false); - } - }, [active, allowResize, draggedSize, onDragFinished]); - - const onTouchMove = useCallback( - event => { - if (allowResize && active) { - unFocus(document, window); - const isPrimaryFirst = primary === 'first'; - const ref = isPrimaryFirst ? pane1.current : pane2.current; - const ref2 = isPrimaryFirst ? pane2.current : pane1.current; - if (ref) { - const node = ref; - const node2 = ref2; - - if (node.getBoundingClientRect) { - const width = node.getBoundingClientRect().width; - const height = node.getBoundingClientRect().height; - const current = - split === 'vertical' ? event.touches[0].clientX : event.touches[0].clientY; - const size = split === 'vertical' ? width : height; - let positionDelta = position - current; - if (step) { - if (Math.abs(positionDelta) < step) { - return; - } - // Integer division - // eslint-disable-next-line no-bitwise - positionDelta = ~~(positionDelta / step) * step; - } - let sizeDelta = isPrimaryFirst ? positionDelta : -positionDelta; - - const pane1Order = parseInt(window.getComputedStyle(node).order); - const pane2Order = parseInt(window.getComputedStyle(node2).order); - if (pane1Order > pane2Order) { - sizeDelta = -sizeDelta; - } - - let newMaxSize = maxSize; - if (maxSize !== undefined && maxSize <= 0) { - if (split === 'vertical') { - newMaxSize = splitPane.current.getBoundingClientRect().width + maxSize; - } else { - newMaxSize = splitPane.current.getBoundingClientRect().height + maxSize; - } - } - - let newSize = size - sizeDelta; - const newPosition = position - positionDelta; - - if (newSize < minSize) { - newSize = minSize; - } else if (maxSize !== undefined && newSize > newMaxSize) { - newSize = newMaxSize; - } else { - setPosition(newPosition); - setResized(true); - } - - if (onChange) onChange(newSize); - - setDraggedSize(newSize); - if (isPrimaryFirst) setPane1Size(newSize); - else setPane2Size(newSize); - } - } - } - }, - [active, allowResize, maxSize, minSize, onChange, position, primary, split, step], - ); - - const onMouseMove = useCallback( - event => { - const eventWithTouches = Object.assign({}, event, { - touches: [{ clientX: event.clientX, clientY: event.clientY }], - }); - onTouchMove(eventWithTouches); - }, - [onTouchMove], - ); - - const onTouchStart = useCallback( - event => { - if (allowResize) { - unFocus(document, window); - const position = split === 'vertical' ? event.touches[0].clientX : event.touches[0].clientY; - - if (typeof onDragStarted === 'function') { - onDragStarted(); - } - setActive(true); - setPosition(position); - } - }, - [allowResize, onDragStarted, split], - ); - - const onMouseDown = useCallback( - event => { - const eventWithTouches = Object.assign({}, event, { - touches: [{ clientX: event.clientX, clientY: event.clientY }], - }); - onTouchStart(eventWithTouches); - }, - [onTouchStart], - ); - - useEffect(() => { - document.addEventListener('mouseup', onMouseUp); - document.addEventListener('mousemove', onMouseMove); - document.addEventListener('touchmove', onTouchMove); - - getSizeUpdate(); - - return () => { - document.removeEventListener('mouseup', onMouseUp); - document.removeEventListener('mousemove', onMouseMove); - document.removeEventListener('touchmove', onTouchMove); - }; - }, [onMouseUp, onMouseMove, onTouchMove, getSizeUpdate]); - - const disabledClass = allowResize ? '' : 'disabled'; - const resizerClassNamesIncludingDefault = resizerClassName - ? `${resizerClassName} ${RESIZER_DEFAULT_CLASSNAME}` - : resizerClassName; - - const notNullChildren = removeNullChildren(children); - - const style = { - display: 'flex', - flex: 1, - height: '100%', - position: 'absolute', - outline: 'none', - overflow: 'hidden', - MozUserSelect: 'text', - WebkitUserSelect: 'text', - msUserSelect: 'text', - userSelect: 'text', - ...styleProps, - }; - - if (split === 'vertical') { - Object.assign(style, { - flexDirection: 'row', - left: 0, - right: 0, - }); - } else { - Object.assign(style, { - bottom: 0, - flexDirection: 'column', - minHeight: '100%', - top: 0, - width: '100%', - }); - } - - const classes = ['SplitPane', className, split, disabledClass]; - - const pane1Style = { ...paneStyle, ...pane1StyleProps }; - const pane2Style = { ...paneStyle, ...pane2StyleProps }; - - const pane1Classes = ['Pane1', paneClassName, pane1ClassName].join(' '); - const pane2Classes = ['Pane2', paneClassName, pane2ClassName].join(' '); - - return ( -
{ - splitPane.current = node; - }} - style={style} - > - { - pane1.current = node; - }} - size={pane1Size} - split={split} - style={pane1Style} - > - {notNullChildren[0]} - - - { - pane2.current = node; - }} - size={pane2Size} - split={split} - style={pane2Style} - > - {notNullChildren[1]} - -
- ); -} - -export default SplitPane; \ No newline at end of file diff --git a/modelina-website/src/components/playground/SplitPane/index.tsx b/modelina-website/src/components/playground/SplitPane/index.tsx deleted file mode 100644 index 18bcb3786a..0000000000 --- a/modelina-website/src/components/playground/SplitPane/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import ReactSplitPane from './SplitPane'; -import Pane from './Pane'; -/** - * Implementation from https://github.com/JeremyGrieshop/react-split-pane/blob/main/SplitPane.js - */ -export default ReactSplitPane; -export { Pane }; \ No newline at end of file diff --git a/modelina-website/src/components/playground/Tooltip.tsx b/modelina-website/src/components/playground/Tooltip.tsx index d3e06c0e76..d8e7d6e9e0 100644 --- a/modelina-website/src/components/playground/Tooltip.tsx +++ b/modelina-website/src/components/playground/Tooltip.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import Tippy, { TippyProps } from '@tippyjs/react'; export const Tooltip: React.FunctionComponent = ({ @@ -10,8 +11,15 @@ export const Tooltip: React.FunctionComponent = ({ ...rest }) => { return ( - + {children} - ) -} \ No newline at end of file + ); +}; diff --git a/modelina-website/src/helpers/debounce.ts b/modelina-website/src/helpers/debounce.ts deleted file mode 100644 index 9677e07783..0000000000 --- a/modelina-website/src/helpers/debounce.ts +++ /dev/null @@ -1,29 +0,0 @@ -export function debounce( - func: (...args: any[]) => any, - wait: number, - immediate?: boolean -): (...args: any[]) => any { - let timeout: number | null; - - return function executedFunction(this: any, ...args: any[]) { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const context = this; - - const later = function () { - timeout = null; - if (!immediate) { - func.apply(context, args); - } - }; - - const callNow = immediate && !timeout; - - // eslint-disable-next-line no-unused-expressions - timeout && clearTimeout(timeout); - timeout = setTimeout(later, wait) as unknown as number; - - if (callNow) { - func.apply(context, args); - } - }; -} From 8e9e8b3eccd04b8d0de617cd5b02e3473d6211b6 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Sun, 3 Dec 2023 16:13:20 +0530 Subject: [PATCH 08/29] added basic output file navigation layout --- .../src/components/playground/Content.tsx | 6 +- .../src/components/playground/Navigation.tsx | 143 ++++++++++++++++++ .../src/components/playground/Playground.tsx | 2 +- 3 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 modelina-website/src/components/playground/Navigation.tsx diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index c8078c2c90..a3ae17c43d 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -2,6 +2,8 @@ import { FunctionComponent } from 'react'; import { usePanelContext } from '../contexts/PlaygroundPanelContext'; +import { Navigation } from './Navigation'; + interface ContentProps {} export const Content: FunctionComponent = () => { @@ -12,8 +14,8 @@ export const Content: FunctionComponent = () => {
{panelEnabled ? ( -
- Navigation +
+
) : null}
= ({ title, disabled = false, cn = '' }) => { + return +} + +const Options: React.FunctionComponent = () => { + return ( + //
+ // {this.state.showGeneratorCode ? ( + //
+ // + //
+ // ) : ( + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // )} + //
+ +
+ Options +
+ ) +} + + +const Output: React.FunctionComponent = () => { + const config: ModelinaOptions = { + language: 'typescript', + propertyNamingFormat: 'default', + modelNamingFormat: 'default', + enumKeyNamingFormat: 'default', + indentationType: 'spaces', + showTypeMappingExample: false, + tsMarshalling: false, + tsModelType: 'class', + tsEnumType: 'enum', + tsModuleSystem: 'CJS', + tsIncludeDescriptions: false, + tsIncludeExampleFunction: false, + tsIncludeJsonBinPack: false, + csharpArrayType: 'Array', + csharpAutoImplemented: false, + csharpOverwriteHashcode: false, + csharpIncludeJson: false, + csharpOverwriteEqual: false, + csharpIncludeNewtonsoft: false, + csharpNamespace: 'asyncapi.models', + csharpNullable: false, + phpIncludeDescriptions: false, + phpNamespace: 'AsyncAPI/Models', + cplusplusNamespace: 'AsyncapiModels', + javaPackageName: 'asyncapi.models', + javaIncludeJackson: false, + javaIncludeMarshaling: false, + javaArrayType: 'Array', + javaOverwriteHashcode: false, + javaOverwriteEqual: false, + javaOverwriteToString: false, + javaJavaDocs: false, + javaJavaxAnnotation: false, + goPackageName: 'asyncapi.models', + kotlinPackageName: 'asyncapi.models' + }; + + return ( +
+ + + + +
+ ) +} + +export const Navigation: React.FunctionComponent = () => { + const { panel } = usePanelContext(); + + return ( +
+ {panel !== 'options' && } + {panel !== 'output' && } +
+ ) +} diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 6c75009929..b7cfd7388f 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -380,7 +380,7 @@ class Playground extends React.Component< Modelina Options

- Change the generation options, or see the Modelina + , or see the Modelina configuration you can use directly in your library

From 81621752d51809e7f0c58190398d8d0aa09c33d1 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Mon, 4 Dec 2023 05:26:45 +0530 Subject: [PATCH 09/29] converted Playground Code from React Class to React Functional Component --- .../src/components/playground/Navigation.tsx | 249 +++++++--- .../src/components/playground/Playground2.tsx | 444 ++++++++++++++++++ modelina-website/src/pages/playground.tsx | 4 +- 3 files changed, 633 insertions(+), 64 deletions(-) create mode 100644 modelina-website/src/components/playground/Playground2.tsx diff --git a/modelina-website/src/components/playground/Navigation.tsx b/modelina-website/src/components/playground/Navigation.tsx index 3301b63908..d95d3f9800 100644 --- a/modelina-website/src/components/playground/Navigation.tsx +++ b/modelina-website/src/components/playground/Navigation.tsx @@ -1,6 +1,8 @@ import React from "react"; +import Router, { withRouter, NextRouter } from 'next/router'; import { usePanelContext } from "../contexts/PlaygroundPanelContext"; import PlaygroundOptions from './PlaygroundOptions'; +import MonacoEditorWrapper from '../MonacoEditorWrapper'; import { PlaygroundTypeScriptConfigContext, PlaygroundCSharpConfigContext, @@ -15,13 +17,36 @@ import { PlaygroundGeneralConfigContext, PlaygroundPhpConfigContext } from '../contexts/PlaygroundConfigContext'; +import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; +import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; +import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; +import { getGoGeneratorCode } from '@/helpers/GeneratorCode/GoGenerator'; +import { getCSharpGeneratorCode } from '@/helpers/GeneratorCode/CSharpGenerator'; +import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; +import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; +import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; +import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; +import CustomError from '../CustomError'; +import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; +import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; +import { encode } from 'js-base64'; +import GeneratedModelsComponent from './GeneratedModels'; +import Heading from '../typography/Heading'; +import Paragraph from '../typography/Paragraph'; +import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; import { - ModelinaOptions + defaultAsyncapiDocument, + ModelinaOptions, + ModelinaQueryOptions, + GenerateMessage, + UpdateMessage } from '@/types'; -interface NavigationProps { } interface OptionsProps { } interface OutputProps { } +interface NavigationProps { + // router: NextRouter; +} interface ButtonProps { title: string; disabled?: boolean; @@ -32,57 +57,9 @@ const CustomButton: React.FunctionComponent = ({ title, disabled = return } -const Options: React.FunctionComponent = () => { - return ( - //
- // {this.state.showGeneratorCode ? ( - //
- // - //
- // ) : ( - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // )} - //
- -
- Options -
- ) -} - +export const Navigation: React.FunctionComponent = () => { + const { panel, setPanel } = usePanelContext(); -const Output: React.FunctionComponent = () => { const config: ModelinaOptions = { language: 'typescript', propertyNamingFormat: 'default', @@ -120,19 +97,165 @@ const Output: React.FunctionComponent = () => { goPackageName: 'asyncapi.models', kotlinPackageName: 'asyncapi.models' }; + + // const setNewConfig = (config: string, configValue: any, updateCode?: boolean) => { + // setNewQuery(config, configValue); + // /* eslint-disable-next-line security/detect-object-injection */ + // (config as any)[config] = configValue; + // if (updateCode === true || updateCode === undefined) { + // generateNewCode(input); + // } + // }; + + // const setNewQuery = (queryKey: string, queryValue: any) => { + // // Create a new object representing the updated query + // const newQuery = { + // query: { ...router.query } + // }; + + // // Check if the queryValue is false, and remove the queryKey if necessary + // if (queryValue === false) { + // delete newQuery.query[queryKey]; + // } else { + // // Set the queryKey and queryValue in the new query object + // newQuery.query[queryKey] = String(queryValue); + // } + + // // Use the Next.js Router to update the query in the URL + // Router.push(newQuery, undefined, { scroll: false }); + // }; + + // const generateNewCode = (input: string) => { + // try { + // const message: GenerateMessage = { + // ...config, + // input: encode(JSON.stringify(JSON.parse(input))) + // }; + + // // Check if the input size is within limits + // if (message.input.length > (maxInputSize || 30000)) { + // console.error('Input too large, use a smaller example'); + // setError(true); + // setErrorMessage('Input too large, use a smaller example'); + // setStatusCode(400); + // } else { + // const generators: { [key: string]: Function } = { + // typescript: getTypeScriptGeneratorCode, + // javascript: getJavaScriptGeneratorCode, + // java: getJavaGeneratorCode, + // go: getGoGeneratorCode, + // csharp: getCSharpGeneratorCode, + // rust: getRustGeneratorCode, + // python: getPythonGeneratorCode, + // dart: getDartGeneratorCode, + // cplusplus: getCplusplusGeneratorCode, + // kotlin: getKotlinGeneratorCode, + // php: getPhpGeneratorCode + // }; + + // // Call the appropriate generator based on the selected language + // const generatorCode = generators[config.language](message); + + // // Make a POST request to the API endpoint to generate code + // fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { + // body: JSON.stringify(message), + // method: 'POST' + // }).then(async (res) => { + // // Check if the response is successful + // if (!res.ok) { + // throw new Error(res.statusText); + // } + + // // Parse the response as JSON + // const response: UpdateMessage = await res.json(); + + // // Update state with the generated code and models + // setGeneratorCode(generatorCode); + // setModels(response.models); + // setLoaded({ + // ...loaded, + // hasReceivedCode: true + // }); + // setError(false); + // setStatusCode(200); + // setErrorMessage(''); + // }).catch(error => { + // console.error(error); + // setError(true); + // setErrorMessage('Input is not a correct AsyncAPI document, so it cannot be processed.'); + // setStatusCode(500); + // }); + // } + // } catch (e: any) { + // console.error(e); + // setError(true); + // setErrorMessage('Input is not a correct AsyncAPI document, so it cannot be processed.'); + // setStatusCode(400); + // } + // }; - return ( -
- - - - -
- ) -} -export const Navigation: React.FunctionComponent = () => { - const { panel } = usePanelContext(); + + const Output: React.FunctionComponent = () => { + + return ( +
+ + + + +
+ ) + } + + const Options: React.FunctionComponent = () => { + return ( + //
+ // {this.state.showGeneratorCode ? ( + //
+ // + //
+ // ) : ( + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // )} + //
+ +
+ Options +
+ ) + } return (
diff --git a/modelina-website/src/components/playground/Playground2.tsx b/modelina-website/src/components/playground/Playground2.tsx new file mode 100644 index 0000000000..033acc874a --- /dev/null +++ b/modelina-website/src/components/playground/Playground2.tsx @@ -0,0 +1,444 @@ +import React, { useState, useEffect } from 'react'; +import MonacoEditorWrapper from '../MonacoEditorWrapper'; +import { + defaultAsyncapiDocument, + ModelinaOptions, + ModelinaQueryOptions, + GenerateMessage, + UpdateMessage +} from '@/types'; +import Router, { withRouter, NextRouter } from 'next/router'; +import { encode } from 'js-base64'; +import GeneratedModelsComponent from './GeneratedModels'; +import PlaygroundOptions from './PlaygroundOptions'; +import Heading from '../typography/Heading'; +import Paragraph from '../typography/Paragraph'; +import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; +import { + PlaygroundTypeScriptConfigContext, + PlaygroundCSharpConfigContext, + PlaygroundDartConfigContext, + PlaygroundGoConfigContext, + PlaygroundJavaConfigContext, + PlaygroundJavaScriptConfigContext, + PlaygroundKotlinConfigContext, + PlaygroundPythonConfigContext, + PlaygroundRustConfigContext, + PlaygroundCplusplusConfigContext, + PlaygroundGeneralConfigContext, + PlaygroundPhpConfigContext +} from '../contexts/PlaygroundConfigContext'; +import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; +import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; +import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; +import { getGoGeneratorCode } from '@/helpers/GeneratorCode/GoGenerator'; +import { getCSharpGeneratorCode } from '@/helpers/GeneratorCode/CSharpGenerator'; +import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; +import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; +import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; +import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; +import CustomError from '../CustomError'; +import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; +import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; + +interface WithRouterProps { + router: NextRouter; +} + +interface ModelsGeneratorProps { + code: string; + name: string; +} +interface ModelinaPlaygroundProps extends WithRouterProps { + maxInputSize?: number; +} + +const Playground: React.FC = (props) => { + const [input, setInput] = useState(JSON.stringify(defaultAsyncapiDocument, null, 4)); + const [models, setModels] = useState([]); + const [generatorCode, setGeneratorCode] = useState(''); + const [loaded, setLoaded] = useState({ + editorLoaded: false, + hasReceivedCode: false, + }); + const [showGeneratorCode, setShowGeneratorCode] = useState(false); + const [error, setError] = useState(false); + const [statusCode, setStatusCode] = useState(400); + const [errorMessage, setErrorMessage] = useState('Bad Request'); + const [isLoaded, setIsLoaded] = useState(false); + const [hasLoadedQuery, setHasLoadedQuery] = useState(false); + + const config: ModelinaOptions = { + language: 'typescript', + propertyNamingFormat: 'default', + modelNamingFormat: 'default', + enumKeyNamingFormat: 'default', + indentationType: 'spaces', + showTypeMappingExample: false, + tsMarshalling: false, + tsModelType: 'class', + tsEnumType: 'enum', + tsModuleSystem: 'CJS', + tsIncludeDescriptions: false, + tsIncludeExampleFunction: false, + tsIncludeJsonBinPack: false, + csharpArrayType: 'Array', + csharpAutoImplemented: false, + csharpOverwriteHashcode: false, + csharpIncludeJson: false, + csharpOverwriteEqual: false, + csharpIncludeNewtonsoft: false, + csharpNamespace: 'asyncapi.models', + csharpNullable: false, + phpIncludeDescriptions: false, + phpNamespace: 'AsyncAPI/Models', + cplusplusNamespace: 'AsyncapiModels', + javaPackageName: 'asyncapi.models', + javaIncludeJackson: false, + javaIncludeMarshaling: false, + javaArrayType: 'Array', + javaOverwriteHashcode: false, + javaOverwriteEqual: false, + javaOverwriteToString: false, + javaJavaDocs: false, + javaJavaxAnnotation: false, + goPackageName: 'asyncapi.models', + kotlinPackageName: 'asyncapi.models' + }; + + useEffect(() => { + const isHardLoaded = loaded.hasReceivedCode; + const isSoftLoaded = loaded.editorLoaded; + setIsLoaded(isHardLoaded && isSoftLoaded); + + const query = props.router.query as ModelinaQueryOptions; + if (query.language !== undefined) { + config.language = query.language as any; + } + if (query.enumKeyNamingFormat !== undefined) { + config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; + } + if (query.propertyNamingFormat !== undefined) { + config.propertyNamingFormat = query.propertyNamingFormat as any; + } + if (query.modelNamingFormat !== undefined) { + config.modelNamingFormat = query.modelNamingFormat as any; + } + if (query.showTypeMappingExample !== undefined) { + config.showTypeMappingExample = query.showTypeMappingExample === 'true'; + } + if (query.indentationType !== undefined) { + config.indentationType = query.indentationType as any; + } + if (query.tsMarshalling !== undefined) { + config.tsMarshalling = query.tsMarshalling === 'true'; + } + if (query.tsModelType !== undefined) { + config.tsModelType = query.tsModelType as any; + } + if (query.tsEnumType !== undefined) { + config.tsEnumType = query.tsEnumType as any; + } + if (query.tsIncludeDescriptions !== undefined) { + config.tsIncludeDescriptions = query.tsIncludeDescriptions === 'true'; + } + if (query.tsIncludeJsonBinPack !== undefined) { + config.tsIncludeJsonBinPack = query.tsIncludeJsonBinPack === 'true'; + } + if (query.tsIncludeExampleFunction !== undefined) { + config.tsIncludeExampleFunction = query.tsIncludeExampleFunction === 'true'; + } + if (query.csharpArrayType !== undefined) { + config.csharpArrayType = query.csharpArrayType as any; + } + if (query.csharpAutoImplemented !== undefined) { + config.csharpAutoImplemented = query.csharpAutoImplemented === 'true'; + } + if (query.csharpOverwriteHashcode !== undefined) { + config.csharpOverwriteHashcode = query.csharpOverwriteHashcode === 'true'; + } + if (query.phpIncludeDescriptions !== undefined) { + config.phpIncludeDescriptions = query.phpIncludeDescriptions === 'true'; + } + if (query.phpNamespace !== undefined) { + config.phpNamespace = query.phpNamespace; + } + if (query.csharpIncludeJson !== undefined) { + config.csharpIncludeJson = query.csharpIncludeJson === 'true'; + } + if (query.csharpOverwriteEqual !== undefined) { + config.csharpOverwriteEqual = query.csharpOverwriteEqual === 'true'; + } + if (query.csharpIncludeNewtonsoft !== undefined) { + config.csharpIncludeNewtonsoft = query.csharpIncludeNewtonsoft === 'true'; + } + if (query.csharpNamespace !== undefined) { + config.csharpNamespace = query.csharpNamespace; + } + if (query.csharpNullable !== undefined) { + config.csharpNullable = query.csharpNullable === 'true'; + } + if (query.cplusplusNamespace !== undefined) { + config.cplusplusNamespace = query.cplusplusNamespace; + } + if (query.javaPackageName !== undefined) { + config.javaPackageName = query.javaPackageName; + } + if (query.javaIncludeJackson !== undefined) { + config.javaIncludeJackson = query.javaIncludeJackson === 'true'; + } + if (query.javaIncludeMarshaling !== undefined) { + config.javaIncludeMarshaling = query.javaIncludeMarshaling === 'true'; + } + if (query.javaArrayType !== undefined) { + config.javaArrayType = query.javaArrayType as any; + } + if (query.javaOverwriteHashcode !== undefined) { + config.javaOverwriteHashcode = query.javaOverwriteHashcode === 'true'; + } + if (query.javaOverwriteEqual !== undefined) { + config.javaOverwriteEqual = query.javaOverwriteEqual === 'true'; + } + if (query.javaOverwriteToString !== undefined) { + config.javaOverwriteToString = query.javaOverwriteToString === 'true'; + } + if (query.javaJavaDocs !== undefined) { + config.javaJavaDocs = query.javaJavaDocs === 'true'; + } + if (query.javaJavaxAnnotation !== undefined) { + config.javaJavaxAnnotation = query.javaJavaxAnnotation === 'true'; + } + if (query.goPackageName !== undefined) { + config.goPackageName = query.goPackageName; + } + if (query.kotlinPackageName !== undefined) { + config.kotlinPackageName = query.kotlinPackageName; + } + + if (props.router.isReady && !hasLoadedQuery) { + setHasLoadedQuery(true); + generateNewCode(input); + } + }, [props.router.isReady, hasLoadedQuery]); + + const setNewConfig = (config: string, configValue: any, updateCode?: boolean) => { + setNewQuery(config, configValue); + /* eslint-disable-next-line security/detect-object-injection */ + (config as any)[config] = configValue; + if (updateCode === true || updateCode === undefined) { + generateNewCode(input); + } + }; + + /** + * Set a query key and value + */ + const setNewQuery = (queryKey: string, queryValue: any) => { + const newQuery = { + query: { ...props.router.query } + }; + + if (queryValue === false) { + delete newQuery.query[queryKey]; + } else { + /* eslint-disable-next-line security/detect-object-injection */ + newQuery.query[queryKey] = String(queryValue); + } + + Router.push(newQuery, undefined, { scroll: false }); + }; + + /** + * Tell the socket io server that we want some code + */ + const generateNewCode = (input: string) => { + try { + const message: GenerateMessage = { + ...config, + input: encode(JSON.stringify(JSON.parse(input))) + }; + + if (message.input.length > (props.maxInputSize || 30000)) { + console.error('Input too large, use a smaller example'); + setError(true); + setErrorMessage('Input too large, use a smaller example'); + setStatusCode(400); + } else { + const generators: { [key: string]: Function } = { + typescript: getTypeScriptGeneratorCode, + javascript: getJavaScriptGeneratorCode, + java: getJavaGeneratorCode, + go: getGoGeneratorCode, + csharp: getCSharpGeneratorCode, + rust: getRustGeneratorCode, + python: getPythonGeneratorCode, + dart: getDartGeneratorCode, + cplusplus: getCplusplusGeneratorCode, + kotlin: getKotlinGeneratorCode, + php: getPhpGeneratorCode + }; + + const generatorCode = generators[config.language](message); + + fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { + body: JSON.stringify(message), + method: 'POST' + }).then(async (res) => { + if (!res.ok) { + throw new Error(res.statusText); + } + + const response: UpdateMessage = await res.json(); + setGeneratorCode(generatorCode); + setModels(response.models); + setLoaded({ + ...loaded, + hasReceivedCode: true + }); + setError(false); + setStatusCode(200); + setErrorMessage(''); + }).catch(error => { + console.error(error); + setError(true); + setErrorMessage("Input is not a correct AsyncAPI document, so it cannot be processed."); + setStatusCode(500); + }); + } + } catch (e: any) { + console.error(e); + setError(true); + setErrorMessage("Input is not a correct AsyncAPI document, so it cannot be processed."); + setStatusCode(400); + } + }; + + + // ... (remaining code) + + return ( +
+ { + isLoaded + ? +
+ Loading Modelina Playground. Rendering playground components... +
+ : +
+
+
+
+

+ Modelina Options +

+

+ , or see the Modelina + configuration you can use directly in your library +

+
+ +
{ + setShowGeneratorCode(false); + }} + className={`${!showGeneratorCode ? 'bg-blue-100' : 'bg-white' + } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} + > +

+ Options +

+
+
{ + setShowGeneratorCode(true); + }} + className={`${showGeneratorCode ? 'bg-blue-100' : 'bg-white' + } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} + > +

+ Generator code +

+
+
+ {showGeneratorCode ? ( +
+ +
+ ) : ( + + + + + + + + + + + + + + + + + + + + + + + + + + )} +
+
+
+ { + setInput(change); + generateNewCode(change); + }} + editorDidMount={() => { + setLoaded({ ...loaded, editorLoaded: true }); + }} + language="json" + /> +
+
+
+ {error ? ( + + ) : ( + + + + )} +
+
+ } +
+ ); +}; + +export default withRouter(Playground); diff --git a/modelina-website/src/pages/playground.tsx b/modelina-website/src/pages/playground.tsx index 525ebc9493..dc3ff28768 100644 --- a/modelina-website/src/pages/playground.tsx +++ b/modelina-website/src/pages/playground.tsx @@ -1,4 +1,5 @@ import Playground from '@/components/playground/Playground'; +import Playground2 from '@/components/playground/Playground2'; import NewPlayground from '@/components/playground/NewPlayground'; import GenericLayout from '@/components/layouts/GenericLayout'; @@ -15,7 +16,8 @@ export default function PlaygroundPage() { full > {/* */} - + {/* */} + ); } From 9f7d6e872c0d2dc7cae18630af68b6fc1ee81492 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Mon, 4 Dec 2023 06:16:04 +0530 Subject: [PATCH 10/29] created playground context and integrated it with playground and content --- .../components/contexts/PlaygroundContext.tsx | 95 +++++++++++++++++++ .../src/components/playground/Content.tsx | 78 +++++++++++++-- .../src/components/playground/Playground2.tsx | 79 +++++---------- modelina-website/src/pages/playground.tsx | 9 +- 4 files changed, 197 insertions(+), 64 deletions(-) create mode 100644 modelina-website/src/components/contexts/PlaygroundContext.tsx diff --git a/modelina-website/src/components/contexts/PlaygroundContext.tsx b/modelina-website/src/components/contexts/PlaygroundContext.tsx new file mode 100644 index 0000000000..bada104655 --- /dev/null +++ b/modelina-website/src/components/contexts/PlaygroundContext.tsx @@ -0,0 +1,95 @@ +'use client'; +import React, { + createContext, + useContext, + Dispatch, + SetStateAction, + useState +} from 'react'; +import { defaultAsyncapiDocument } from '@/types'; + +interface ModelsGeneratorProps { + code: string; + name: string; +} + +interface LoadedState { + editorLoaded: boolean; + hasReceivedCode: boolean; +} + +interface PlaygroundContextProps { + input: string; + setInput: Dispatch>; + models: ModelsGeneratorProps[]; + setModels: Dispatch>; + generatorCode: string; + setGeneratorCode: Dispatch>; + loaded: LoadedState; + setLoaded: Dispatch>; + showGeneratorCode: boolean; + setShowGeneratorCode: Dispatch>; + error: boolean; + setError: Dispatch>; + statusCode: number; + setStatusCode: Dispatch>; + errorMessage: string; + setErrorMessage: Dispatch>; + isLoaded: boolean; + setIsLoaded: Dispatch>; + hasLoadedQuery: boolean; + setHasLoadedQuery: Dispatch>; +} + +const PlaygroundContext = createContext(undefined); + +export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { + const [input, setInput] = useState(JSON.stringify(defaultAsyncapiDocument, null, 4)); + const [models, setModels] = useState([]); + const [generatorCode, setGeneratorCode] = useState(''); + const [loaded, setLoaded] = useState({ + editorLoaded: false, + hasReceivedCode: false, + }); + const [showGeneratorCode, setShowGeneratorCode] = useState(false); + const [error, setError] = useState(false); + const [statusCode, setStatusCode] = useState(400); + const [errorMessage, setErrorMessage] = useState('Bad Request'); + const [isLoaded, setIsLoaded] = useState(false); + const [hasLoadedQuery, setHasLoadedQuery] = useState(false); + + return ( + + {children} + + ); +} + +export const usePlaygroundContext = () => { + const context = useContext(PlaygroundContext); + if (!context) { + throw new Error('usePlaygroundContext must be used within a PlaygroundContextProvider'); + } + return context; +}; \ No newline at end of file diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index a3ae17c43d..42a9b9ed23 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -2,12 +2,44 @@ import { FunctionComponent } from 'react'; import { usePanelContext } from '../contexts/PlaygroundPanelContext'; +import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; +import { usePlaygroundContext } from '../contexts/PlaygroundContext'; import { Navigation } from './Navigation'; +import GeneratedModelsComponent from './GeneratedModels'; +import MonacoEditorWrapper from '../MonacoEditorWrapper'; +import CustomError from '../CustomError'; +import { ModelinaOptions } from '@/types'; -interface ContentProps {} +interface ContentProps { + config: ModelinaOptions; + setNewQuery: (queryKey: string, queryValue: any) => void; + generateNewCode: (input: string) => void; +} -export const Content: FunctionComponent = () => { +export const Content: FunctionComponent = ({ config, setNewQuery, generateNewCode }) => { const { panel } = usePanelContext(); + const { + input, + setInput, + models, + setModels, + generatorCode, + setGeneratorCode, + loaded, + setLoaded, + showGeneratorCode, + setShowGeneratorCode, + error, + setError, + statusCode, + setStatusCode, + errorMessage, + setErrorMessage, + isLoaded, + setIsLoaded, + hasLoadedQuery, + setHasLoadedQuery, + } = usePlaygroundContext(); const panelEnabled = panel !== ''; return ( @@ -19,12 +51,44 @@ export const Content: FunctionComponent = () => {
) : null}
-
Editor
-
Output
+
+
+ { + setInput(change); + generateNewCode(change); + }} + editorDidMount={() => { + setLoaded({ ...loaded, editorLoaded: true }); + }} + language="json" + /> +
+
+
+ {error ? ( + + ) : ( + + + + )} +
diff --git a/modelina-website/src/components/playground/Playground2.tsx b/modelina-website/src/components/playground/Playground2.tsx index 033acc874a..a44cb4f366 100644 --- a/modelina-website/src/components/playground/Playground2.tsx +++ b/modelina-website/src/components/playground/Playground2.tsx @@ -9,11 +9,9 @@ import { } from '@/types'; import Router, { withRouter, NextRouter } from 'next/router'; import { encode } from 'js-base64'; -import GeneratedModelsComponent from './GeneratedModels'; import PlaygroundOptions from './PlaygroundOptions'; import Heading from '../typography/Heading'; import Paragraph from '../typography/Paragraph'; -import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; import { PlaygroundTypeScriptConfigContext, PlaygroundCSharpConfigContext, @@ -28,6 +26,7 @@ import { PlaygroundGeneralConfigContext, PlaygroundPhpConfigContext } from '../contexts/PlaygroundConfigContext'; +import { usePlaygroundContext } from '../contexts/PlaygroundContext'; import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; @@ -37,9 +36,9 @@ import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; -import CustomError from '../CustomError'; import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; +import { Content } from './Content'; interface WithRouterProps { router: NextRouter; @@ -54,19 +53,28 @@ interface ModelinaPlaygroundProps extends WithRouterProps { } const Playground: React.FC = (props) => { - const [input, setInput] = useState(JSON.stringify(defaultAsyncapiDocument, null, 4)); - const [models, setModels] = useState([]); - const [generatorCode, setGeneratorCode] = useState(''); - const [loaded, setLoaded] = useState({ - editorLoaded: false, - hasReceivedCode: false, - }); - const [showGeneratorCode, setShowGeneratorCode] = useState(false); - const [error, setError] = useState(false); - const [statusCode, setStatusCode] = useState(400); - const [errorMessage, setErrorMessage] = useState('Bad Request'); - const [isLoaded, setIsLoaded] = useState(false); - const [hasLoadedQuery, setHasLoadedQuery] = useState(false); + const { + input, + setInput, + models, + setModels, + generatorCode, + setGeneratorCode, + loaded, + setLoaded, + showGeneratorCode, + setShowGeneratorCode, + error, + setError, + statusCode, + setStatusCode, + errorMessage, + setErrorMessage, + isLoaded, + setIsLoaded, + hasLoadedQuery, + setHasLoadedQuery, + } = usePlaygroundContext(); const config: ModelinaOptions = { language: 'typescript', @@ -313,9 +321,6 @@ const Playground: React.FC = (props) => { } }; - - // ... (remaining code) - return (
{ @@ -400,41 +405,7 @@ const Playground: React.FC = (props) => { )}
-
-
- { - setInput(change); - generateNewCode(change); - }} - editorDidMount={() => { - setLoaded({ ...loaded, editorLoaded: true }); - }} - language="json" - /> -
-
-
- {error ? ( - - ) : ( - - - - )} -
+
}
diff --git a/modelina-website/src/pages/playground.tsx b/modelina-website/src/pages/playground.tsx index dc3ff28768..33687bd3ee 100644 --- a/modelina-website/src/pages/playground.tsx +++ b/modelina-website/src/pages/playground.tsx @@ -2,6 +2,7 @@ import Playground from '@/components/playground/Playground'; import Playground2 from '@/components/playground/Playground2'; import NewPlayground from '@/components/playground/NewPlayground'; import GenericLayout from '@/components/layouts/GenericLayout'; +import { PlaygroundContextProvider } from '@/components/contexts/PlaygroundContext'; export default function PlaygroundPage() { const description = 'Try out Modelina and see a fraction of what it can do.'; @@ -15,9 +16,11 @@ export default function PlaygroundPage() { wide full > - {/* */} - {/* */} - + + {/* */} + {/* */} + + ); } From 7d927bf1a3fcacaf5662ef9416d181318a5bfaab Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Mon, 4 Dec 2023 08:08:16 +0530 Subject: [PATCH 11/29] added all options --- .../src/components/playground/Content.tsx | 72 ++-- .../src/components/playground/Navigation.tsx | 325 +++++++----------- .../src/components/playground/Playground.tsx | 4 +- .../src/components/playground/Playground2.tsx | 83 +---- .../playground/PlaygroundOptions.tsx | 2 +- .../playground/options/GeneralOptions.tsx | 2 +- .../options/TypeScriptGeneratorOptions.tsx | 2 +- modelina-website/src/styles/globals.css | 21 ++ 8 files changed, 203 insertions(+), 308 deletions(-) diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index 42a9b9ed23..d175899b09 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -12,11 +12,12 @@ import { ModelinaOptions } from '@/types'; interface ContentProps { config: ModelinaOptions; + setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; setNewQuery: (queryKey: string, queryValue: any) => void; generateNewCode: (input: string) => void; } -export const Content: FunctionComponent = ({ config, setNewQuery, generateNewCode }) => { +export const Content: FunctionComponent = ({ config, setNewConfig, setNewQuery, generateNewCode }) => { const { panel } = usePanelContext(); const { input, @@ -47,48 +48,55 @@ export const Content: FunctionComponent = ({ config, setNewQuery,
{panelEnabled ? (
- +
) : null}
-
+ {/* EDITOR */} +
+
+
+ { + setInput(change); + generateNewCode(change); + }} + editorDidMount={() => { + setLoaded({ ...loaded, editorLoaded: true }); + }} + language="json" + /> +
+
+
+ + {/* OUTPUT */} +
- { - setInput(change); - generateNewCode(change); - }} - editorDidMount={() => { - setLoaded({ ...loaded, editorLoaded: true }); - }} - language="json" - /> + {error ? ( + + ) : ( + + + + )}
-
- {error ? ( - - ) : ( - - - - )} -
diff --git a/modelina-website/src/components/playground/Navigation.tsx b/modelina-website/src/components/playground/Navigation.tsx index d95d3f9800..b03f90d712 100644 --- a/modelina-website/src/components/playground/Navigation.tsx +++ b/modelina-website/src/components/playground/Navigation.tsx @@ -41,11 +41,16 @@ import { GenerateMessage, UpdateMessage } from '@/types'; +import { usePlaygroundContext } from "../contexts/PlaygroundContext"; -interface OptionsProps { } +interface OptionsProps { + config: ModelinaOptions; + setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; +} interface OutputProps { } interface NavigationProps { - // router: NextRouter; + config: ModelinaOptions; + setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; } interface ButtonProps { title: string; @@ -57,209 +62,137 @@ const CustomButton: React.FunctionComponent = ({ title, disabled = return } -export const Navigation: React.FunctionComponent = () => { - const { panel, setPanel } = usePanelContext(); +const Output: React.FunctionComponent = () => { - const config: ModelinaOptions = { - language: 'typescript', - propertyNamingFormat: 'default', - modelNamingFormat: 'default', - enumKeyNamingFormat: 'default', - indentationType: 'spaces', - showTypeMappingExample: false, - tsMarshalling: false, - tsModelType: 'class', - tsEnumType: 'enum', - tsModuleSystem: 'CJS', - tsIncludeDescriptions: false, - tsIncludeExampleFunction: false, - tsIncludeJsonBinPack: false, - csharpArrayType: 'Array', - csharpAutoImplemented: false, - csharpOverwriteHashcode: false, - csharpIncludeJson: false, - csharpOverwriteEqual: false, - csharpIncludeNewtonsoft: false, - csharpNamespace: 'asyncapi.models', - csharpNullable: false, - phpIncludeDescriptions: false, - phpNamespace: 'AsyncAPI/Models', - cplusplusNamespace: 'AsyncapiModels', - javaPackageName: 'asyncapi.models', - javaIncludeJackson: false, - javaIncludeMarshaling: false, - javaArrayType: 'Array', - javaOverwriteHashcode: false, - javaOverwriteEqual: false, - javaOverwriteToString: false, - javaJavaDocs: false, - javaJavaxAnnotation: false, - goPackageName: 'asyncapi.models', - kotlinPackageName: 'asyncapi.models' - }; + return ( +
+ + + + +
+ ) +} - // const setNewConfig = (config: string, configValue: any, updateCode?: boolean) => { - // setNewQuery(config, configValue); - // /* eslint-disable-next-line security/detect-object-injection */ - // (config as any)[config] = configValue; - // if (updateCode === true || updateCode === undefined) { - // generateNewCode(input); - // } - // }; +const Options: React.FunctionComponent = ({ config, setNewConfig }) => { + const { + generatorCode, + showGeneratorCode, + setShowGeneratorCode, + } = usePlaygroundContext(); + return ( + //
+ //
+ //
+ //

+ // Modelina Options + //

+ //

+ // , or see the Modelina + // configuration you can use directly in your library + //

+ //
- // const setNewQuery = (queryKey: string, queryValue: any) => { - // // Create a new object representing the updated query - // const newQuery = { - // query: { ...router.query } - // }; - - // // Check if the queryValue is false, and remove the queryKey if necessary - // if (queryValue === false) { - // delete newQuery.query[queryKey]; - // } else { - // // Set the queryKey and queryValue in the new query object - // newQuery.query[queryKey] = String(queryValue); - // } - - // // Use the Next.js Router to update the query in the URL - // Router.push(newQuery, undefined, { scroll: false }); - // }; - - // const generateNewCode = (input: string) => { - // try { - // const message: GenerateMessage = { - // ...config, - // input: encode(JSON.stringify(JSON.parse(input))) - // }; - - // // Check if the input size is within limits - // if (message.input.length > (maxInputSize || 30000)) { - // console.error('Input too large, use a smaller example'); - // setError(true); - // setErrorMessage('Input too large, use a smaller example'); - // setStatusCode(400); - // } else { - // const generators: { [key: string]: Function } = { - // typescript: getTypeScriptGeneratorCode, - // javascript: getJavaScriptGeneratorCode, - // java: getJavaGeneratorCode, - // go: getGoGeneratorCode, - // csharp: getCSharpGeneratorCode, - // rust: getRustGeneratorCode, - // python: getPythonGeneratorCode, - // dart: getDartGeneratorCode, - // cplusplus: getCplusplusGeneratorCode, - // kotlin: getKotlinGeneratorCode, - // php: getPhpGeneratorCode - // }; - - // // Call the appropriate generator based on the selected language - // const generatorCode = generators[config.language](message); - - // // Make a POST request to the API endpoint to generate code - // fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { - // body: JSON.stringify(message), - // method: 'POST' - // }).then(async (res) => { - // // Check if the response is successful - // if (!res.ok) { - // throw new Error(res.statusText); - // } - - // // Parse the response as JSON - // const response: UpdateMessage = await res.json(); - - // // Update state with the generated code and models - // setGeneratorCode(generatorCode); - // setModels(response.models); - // setLoaded({ - // ...loaded, - // hasReceivedCode: true - // }); - // setError(false); - // setStatusCode(200); - // setErrorMessage(''); - // }).catch(error => { - // console.error(error); - // setError(true); - // setErrorMessage('Input is not a correct AsyncAPI document, so it cannot be processed.'); - // setStatusCode(500); - // }); - // } - // } catch (e: any) { - // console.error(e); - // setError(true); - // setErrorMessage('Input is not a correct AsyncAPI document, so it cannot be processed.'); - // setStatusCode(400); - // } - // }; - + //
{ + // setShowGeneratorCode(false); + // }} + // className={`${!showGeneratorCode ? 'bg-blue-100' : 'bg-white' + // } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} + // > + //

+ // Options + //

+ //
+ //
{ + // setShowGeneratorCode(true); + // }} + // className={`${showGeneratorCode ? 'bg-blue-100' : 'bg-white' + // } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} + // > + //

+ // Generator code + //

+ //
+ //
+ // {showGeneratorCode ? ( + //
+ // + //
+ // ) : ( + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // )} + //
- const Output: React.FunctionComponent = () => { - - return ( -
- - - - -
- ) - } +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ ) +} - const Options: React.FunctionComponent = () => { - return ( - //
- // {this.state.showGeneratorCode ? ( - //
- // - //
- // ) : ( - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // )} - //
- -
- Options -
- ) - } +export const Navigation: React.FunctionComponent = ({ config, setNewConfig }) => { + const { panel } = usePanelContext(); return (
- {panel !== 'options' && } + {panel !== 'options' && } {panel !== 'output' && }
) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index b7cfd7388f..278fe5a73e 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -373,7 +373,7 @@ class Playground extends React.Component< className={`grid grid-cols-2 gap-4 mt-4 ${isLoaded ? '' : 'invisible' }`} > -
+ {/*

@@ -446,7 +446,7 @@ class Playground extends React.Component< )} -

+
*/}
= (props) => { Loading Modelina Playground. Rendering playground components...
: -
-
-
-
-

- Modelina Options -

-

- , or see the Modelina - configuration you can use directly in your library -

-
- -
{ - setShowGeneratorCode(false); - }} - className={`${!showGeneratorCode ? 'bg-blue-100' : 'bg-white' - } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - > -

- Options -

-
-
{ - setShowGeneratorCode(true); - }} - className={`${showGeneratorCode ? 'bg-blue-100' : 'bg-white' - } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - > -

- Generator code -

-
-
- {showGeneratorCode ? ( -
- -
- ) : ( - - - - - - - - - - - - - - - - - - - - - - - - - - )} +
+
+ + + +
-
}
diff --git a/modelina-website/src/components/playground/PlaygroundOptions.tsx b/modelina-website/src/components/playground/PlaygroundOptions.tsx index 85ec5a1de3..58a8ed8381 100644 --- a/modelina-website/src/components/playground/PlaygroundOptions.tsx +++ b/modelina-website/src/components/playground/PlaygroundOptions.tsx @@ -79,7 +79,7 @@ class PlaygroundOptions extends React.Component< ); } return ( -
+
{generatorOptions}
diff --git a/modelina-website/src/components/playground/options/GeneralOptions.tsx b/modelina-website/src/components/playground/options/GeneralOptions.tsx index 852ad9b1c3..e63abfe473 100644 --- a/modelina-website/src/components/playground/options/GeneralOptions.tsx +++ b/modelina-website/src/components/playground/options/GeneralOptions.tsx @@ -72,7 +72,7 @@ class GeneralOptions extends React.Component< render() { return (
    -

    +

    General options

  • diff --git a/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx b/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx index 780acdf4ea..06500fe931 100644 --- a/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx @@ -80,7 +80,7 @@ class TypeScriptGeneratorOptions extends React.Component< render() { return (
      -

      +

      TypeScript Specific options

    • diff --git a/modelina-website/src/styles/globals.css b/modelina-website/src/styles/globals.css index 91343a9b38..1faeb27206 100644 --- a/modelina-website/src/styles/globals.css +++ b/modelina-website/src/styles/globals.css @@ -32,6 +32,27 @@ abbr[title] { text-decoration: none; } +/* width */ +.options::-webkit-scrollbar { + width: 4px; +} + +/* Track */ +.options::-webkit-scrollbar-track { + background: #f1f1f1; +} + +/* Handle */ +.options::-webkit-scrollbar-thumb { + background: #888; + border-radius: 5px; +} + +/* Handle on hover */ +.options::-webkit-scrollbar-thumb:hover { + background: #555; +} + @keyframes GradientAnimation { 0% { background-position: 0% 50% From f584a8405c422ca5734e221dbe74198c7308fe23 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Mon, 4 Dec 2023 08:21:29 +0530 Subject: [PATCH 12/29] rectified sidebar css and overall pading --- .../src/components/playground/Content.tsx | 4 +- .../components/playground/OldPlayground.tsx | 492 +++++++++++++++++ .../src/components/playground/Playground.tsx | 514 +++++++----------- .../src/components/playground/Playground2.tsx | 348 ------------ .../src/components/playground/Sidebar.tsx | 4 +- modelina-website/src/pages/playground.tsx | 8 +- 6 files changed, 686 insertions(+), 684 deletions(-) create mode 100644 modelina-website/src/components/playground/OldPlayground.tsx delete mode 100644 modelina-website/src/components/playground/Playground2.tsx diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index d175899b09..e85ad675e0 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -44,7 +44,7 @@ export const Content: FunctionComponent = ({ config, setNewConfig, const panelEnabled = panel !== ''; return ( -
      +
      {panelEnabled ? (
      @@ -56,7 +56,7 @@ export const Content: FunctionComponent = ({ config, setNewConfig, }`} > {/* EDITOR */} -
      +
      { + config: ModelinaOptions = { + language: 'typescript', + propertyNamingFormat: 'default', + modelNamingFormat: 'default', + enumKeyNamingFormat: 'default', + indentationType: 'spaces', + showTypeMappingExample: false, + tsMarshalling: false, + tsModelType: 'class', + tsEnumType: 'enum', + tsModuleSystem: 'CJS', + tsIncludeDescriptions: false, + tsIncludeExampleFunction: false, + tsIncludeJsonBinPack: false, + csharpArrayType: 'Array', + csharpAutoImplemented: false, + csharpOverwriteHashcode: false, + csharpIncludeJson: false, + csharpOverwriteEqual: false, + csharpIncludeNewtonsoft: false, + csharpNamespace: 'asyncapi.models', + csharpNullable: false, + phpIncludeDescriptions: false, + phpNamespace: 'AsyncAPI/Models', + cplusplusNamespace: 'AsyncapiModels', + javaPackageName: 'asyncapi.models', + javaIncludeJackson: false, + javaIncludeMarshaling: false, + javaArrayType: 'Array', + javaOverwriteHashcode: false, + javaOverwriteEqual: false, + javaOverwriteToString: false, + javaJavaDocs: false, + javaJavaxAnnotation: false, + goPackageName: 'asyncapi.models', + kotlinPackageName: 'asyncapi.models' + }; + hasLoadedQuery: boolean = false; + constructor(props: ModelinaPlaygroundProps) { + super(props); + this.state = { + input: JSON.stringify(defaultAsyncapiDocument, null, 4), + models: [], + generatorCode: '', + loaded: { + editorLoaded: false, + hasReceivedCode: false + }, + showGeneratorCode: false, + error: false, + statusCode: 400, + errorMessage: 'Bad Request', + }; + this.setNewConfig = this.setNewConfig.bind(this); + this.setNewQuery = this.setNewQuery.bind(this); + this.generateNewCode = this.generateNewCode.bind(this); + } + + setNewConfig(config: string, configValue: any, updateCode?: boolean) { + this.setNewQuery(config, configValue); + /* eslint-disable-next-line security/detect-object-injection */ + (this.config as any)[config] = configValue; + if(updateCode === true || updateCode === undefined) { + this.generateNewCode(this.state.input); + } + } + + /** + * Set a query key and value + */ + setNewQuery(queryKey: string, queryValue: any) { + const newQuery = { + query: { ...this.props.router.query } + }; + if(queryValue === false) { + delete newQuery.query[queryKey]; + } else { + /* eslint-disable-next-line security/detect-object-injection */ + newQuery.query[queryKey] = String(queryValue); + } + Router.push(newQuery, undefined, { scroll: false }); + } + + /** + * Tell the socket io server that we want some code + */ + generateNewCode(input: string) { + try { + const message: GenerateMessage = { + ...this.config, + input: encode(JSON.stringify(JSON.parse(input))) + }; + if (message.input.length > (this.props.maxInputSize || 30000)) { + console.error('Input too large, use smaller example'); + this.setState({ ...this.state, error: true, errorMessage: 'Input too large, use smaller example', statusCode: 400 }); + } else { + const generators: { [key: string]: Function } = { + typescript: getTypeScriptGeneratorCode, + javascript: getJavaScriptGeneratorCode, + java: getJavaGeneratorCode, + go: getGoGeneratorCode, + csharp: getCSharpGeneratorCode, + rust: getRustGeneratorCode, + python: getPythonGeneratorCode, + dart: getDartGeneratorCode, + cplusplus: getCplusplusGeneratorCode, + kotlin: getKotlinGeneratorCode, + php: getPhpGeneratorCode + } + const generatorCode = generators[this.config.language](message); + fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { + body: JSON.stringify(message), + method: 'POST' + }).then(async (res) => { + if (!res.ok) { + throw new Error(res.statusText); + } + const response: UpdateMessage = await res.json(); + this.setState({ + ...this.state, + generatorCode, + models: response.models, + loaded: { + ...this.state.loaded, + hasReceivedCode: true + }, + error: false, + statusCode: 200, + errorMessage: '', + }); + }).catch(error => { + console.error(error); + this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 500 }); + }); + } + } catch (e: any) { + console.error(e); + this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 400 }); + } + } + + render() { + const { loaded } = this.state; + const isHardLoaded = loaded.hasReceivedCode; + const isSoftLoaded = loaded.editorLoaded; + const isLoaded = isHardLoaded && isSoftLoaded; + + const query = this.props.router.query as ModelinaQueryOptions; + if (query.language !== undefined) { + this.config.language = query.language as any; + } + if (query.enumKeyNamingFormat !== undefined) { + this.config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; + } + if (query.propertyNamingFormat !== undefined) { + this.config.propertyNamingFormat = query.propertyNamingFormat as any; + } + if (query.modelNamingFormat !== undefined) { + this.config.modelNamingFormat = query.modelNamingFormat as any; + } + if (query.showTypeMappingExample !== undefined) { + this.config.showTypeMappingExample = query.showTypeMappingExample === 'true'; + } + if (query.indentationType !== undefined) { + this.config.indentationType = query.indentationType as any; + } + if (query.tsMarshalling !== undefined) { + this.config.tsMarshalling = query.tsMarshalling === 'true'; + } + if (query.tsModelType !== undefined) { + this.config.tsModelType = query.tsModelType as any; + } + if (query.tsEnumType !== undefined) { + this.config.tsEnumType = query.tsEnumType as any; + } + if (query.tsIncludeDescriptions !== undefined) { + this.config.tsIncludeDescriptions = + query.tsIncludeDescriptions === 'true'; + } + if (query.tsIncludeJsonBinPack !== undefined) { + this.config.tsIncludeJsonBinPack = + query.tsIncludeJsonBinPack === 'true'; + } + if (query.tsIncludeExampleFunction !== undefined) { + this.config.tsIncludeExampleFunction = + query.tsIncludeExampleFunction === 'true'; + } + if (query.csharpArrayType !== undefined) { + this.config.csharpArrayType = query.csharpArrayType as any; + } + if (query.csharpAutoImplemented !== undefined) { + this.config.csharpAutoImplemented = + query.csharpAutoImplemented === 'true'; + } + if (query.csharpOverwriteHashcode !== undefined) { + this.config.csharpOverwriteHashcode = + query.csharpOverwriteHashcode === 'true'; + } + if (query.phpIncludeDescriptions !== undefined) { + this.config.phpIncludeDescriptions = + query.phpIncludeDescriptions === 'true'; + } + if (query.phpNamespace !== undefined) { + this.config.phpNamespace = query.phpNamespace; + } + if (query.csharpIncludeJson !== undefined) { + this.config.csharpIncludeJson = + query.csharpIncludeJson === 'true'; + } + if (query.csharpOverwriteEqual !== undefined) { + this.config.csharpOverwriteEqual = + query.csharpOverwriteEqual === 'true'; + } + if (query.csharpIncludeNewtonsoft !== undefined) { + this.config.csharpIncludeNewtonsoft = + query.csharpIncludeNewtonsoft === 'true'; + } + if (query.csharpNamespace !== undefined) { + this.config.csharpNamespace = query.csharpNamespace; + } + if (query.csharpNullable !== undefined) { + this.config.csharpNullable = query.csharpNullable === 'true'; + } + if(query.cplusplusNamespace !== undefined) { + this.config.cplusplusNamespace = query.cplusplusNamespace; + } + if (query.javaPackageName !== undefined) { + this.config.javaPackageName = query.javaPackageName; + } + if (query.javaIncludeJackson !== undefined) { + this.config.javaIncludeJackson = + query.javaIncludeJackson === 'true'; + } + if (query.javaIncludeMarshaling !== undefined) { + this.config.javaIncludeMarshaling = + query.javaIncludeMarshaling === 'true'; + } + if (query.javaArrayType !== undefined) { + this.config.javaArrayType = query.javaArrayType as any; + } + if (query.javaOverwriteHashcode !== undefined) { + this.config.javaOverwriteHashcode = + query.javaOverwriteHashcode === 'true'; + } + if (query.javaOverwriteEqual !== undefined) { + this.config.javaOverwriteEqual = + query.javaOverwriteEqual === 'true'; + } + if (query.javaOverwriteToString !== undefined) { + this.config.javaOverwriteToString = + query.javaOverwriteToString === 'true'; + } + if (query.javaJavaDocs !== undefined) { + this.config.javaJavaDocs = + query.javaJavaDocs === 'true'; + } + if (query.javaJavaxAnnotation !== undefined) { + this.config.javaJavaxAnnotation = + query.javaJavaxAnnotation === 'true'; + } + if(query.goPackageName !== undefined) { + this.config.goPackageName = query.goPackageName; + } + if (query.kotlinPackageName !== undefined) { + this.config.kotlinPackageName = query.kotlinPackageName; + } + if (this.props.router.isReady && !this.hasLoadedQuery) { + this.hasLoadedQuery = true; + this.generateNewCode(this.state.input); + } + + let loader; + if (!isHardLoaded) { + loader = ( +
      + Loading Modelina Playground. Connecting to playground server... +
      + ); + } else if (!isSoftLoaded) { + loader = ( +
      + Loading Modelina Playground. Rendering playground components... +
      + ); + } + return ( +
      +
      + + Modelina Playground + + + Try out Modelina and see a small fraction of what it can do. Use it + to play around, with small examples, otherwise turn to the CLI or + library instead. + +
      + {loader} +
      +
      +
      +
      +

      + Modelina Options +

      +

      + , or see the Modelina + configuration you can use directly in your library +

      +
      + +
      { + this.setState({ ...this.state, showGeneratorCode: false }); + }} + className={`${!this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' + } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} + > +

      + Options +

      +
      +
      { + this.setState({ ...this.state, showGeneratorCode: true }); + }} + className={`${this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' + } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} + > +

      + Generator code +

      +
      +
      + {this.state.showGeneratorCode ? ( +
      + +
      + ) : ( + + + + + + + + + + + + + + + + + + + + + + + + + + )} +
      +
      +
      + { + this.setState({ ...this.state, input: change }); + this.generateNewCode(change); + }} + editorDidMount={() => { + this.setState({ + loaded: { ...this.state.loaded, editorLoaded: true } + }); + }} + language="json" + /> +
      +
      +
      + {this.state.error ? ( + + ) : ( + + + + )} +
      +
      +
      + ); + } +} +export default withRouter(Playground); \ No newline at end of file diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 278fe5a73e..b9d9782bc6 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import MonacoEditorWrapper from '../MonacoEditorWrapper'; import { defaultAsyncapiDocument, @@ -9,11 +9,9 @@ import { } from '@/types'; import Router, { withRouter, NextRouter } from 'next/router'; import { encode } from 'js-base64'; -import GeneratedModelsComponent from './GeneratedModels'; import PlaygroundOptions from './PlaygroundOptions'; import Heading from '../typography/Heading'; import Paragraph from '../typography/Paragraph'; -import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; import { PlaygroundTypeScriptConfigContext, PlaygroundCSharpConfigContext, @@ -28,6 +26,8 @@ import { PlaygroundGeneralConfigContext, PlaygroundPhpConfigContext } from '../contexts/PlaygroundConfigContext'; +import { PanelContextProvider } from '../contexts/PlaygroundPanelContext'; +import { usePlaygroundContext } from '../contexts/PlaygroundContext'; import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; @@ -37,9 +37,10 @@ import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; -import CustomError from '../CustomError'; import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; +import { Sidebar } from './Sidebar'; +import { Content } from './Content'; interface WithRouterProps { router: NextRouter; @@ -53,25 +54,31 @@ interface ModelinaPlaygroundProps extends WithRouterProps { maxInputSize?: number; } -type ModelinaPlaygroundState = { - input: string; - models: ModelsGeneratorProps[]; - generatorCode: string; - loaded: { - editorLoaded: boolean; - hasReceivedCode: boolean; - }; - showGeneratorCode: boolean; - error: boolean; - statusCode: number; - errorMessage: string; -}; +const Playground: React.FC = (props) => { + const { + input, + setInput, + models, + setModels, + generatorCode, + setGeneratorCode, + loaded, + setLoaded, + showGeneratorCode, + setShowGeneratorCode, + error, + setError, + statusCode, + setStatusCode, + errorMessage, + setErrorMessage, + isLoaded, + setIsLoaded, + hasLoadedQuery, + setHasLoadedQuery, + } = usePlaygroundContext(); -class Playground extends React.Component< - ModelinaPlaygroundProps, - ModelinaPlaygroundState -> { - config: ModelinaOptions = { + const config: ModelinaOptions = { language: 'typescript', propertyNamingFormat: 'default', modelNamingFormat: 'default', @@ -108,385 +115,234 @@ class Playground extends React.Component< goPackageName: 'asyncapi.models', kotlinPackageName: 'asyncapi.models' }; - hasLoadedQuery: boolean = false; - constructor(props: ModelinaPlaygroundProps) { - super(props); - this.state = { - input: JSON.stringify(defaultAsyncapiDocument, null, 4), - models: [], - generatorCode: '', - loaded: { - editorLoaded: false, - hasReceivedCode: false - }, - showGeneratorCode: false, - error: false, - statusCode: 400, - errorMessage: 'Bad Request', - }; - this.setNewConfig = this.setNewConfig.bind(this); - this.setNewQuery = this.setNewQuery.bind(this); - this.generateNewCode = this.generateNewCode.bind(this); - } - - setNewConfig(config: string, configValue: any, updateCode?: boolean) { - this.setNewQuery(config, configValue); - /* eslint-disable-next-line security/detect-object-injection */ - (this.config as any)[config] = configValue; - if(updateCode === true || updateCode === undefined) { - this.generateNewCode(this.state.input); - } - } - - /** - * Set a query key and value - */ - setNewQuery(queryKey: string, queryValue: any) { - const newQuery = { - query: { ...this.props.router.query } - }; - if(queryValue === false) { - delete newQuery.query[queryKey]; - } else { - /* eslint-disable-next-line security/detect-object-injection */ - newQuery.query[queryKey] = String(queryValue); - } - Router.push(newQuery, undefined, { scroll: false }); - } - - /** - * Tell the socket io server that we want some code - */ - generateNewCode(input: string) { - try { - const message: GenerateMessage = { - ...this.config, - input: encode(JSON.stringify(JSON.parse(input))) - }; - if (message.input.length > (this.props.maxInputSize || 30000)) { - console.error('Input too large, use smaller example'); - this.setState({ ...this.state, error: true, errorMessage: 'Input too large, use smaller example', statusCode: 400 }); - } else { - const generators: { [key: string]: Function } = { - typescript: getTypeScriptGeneratorCode, - javascript: getJavaScriptGeneratorCode, - java: getJavaGeneratorCode, - go: getGoGeneratorCode, - csharp: getCSharpGeneratorCode, - rust: getRustGeneratorCode, - python: getPythonGeneratorCode, - dart: getDartGeneratorCode, - cplusplus: getCplusplusGeneratorCode, - kotlin: getKotlinGeneratorCode, - php: getPhpGeneratorCode - } - const generatorCode = generators[this.config.language](message); - fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { - body: JSON.stringify(message), - method: 'POST' - }).then(async (res) => { - if (!res.ok) { - throw new Error(res.statusText); - } - const response: UpdateMessage = await res.json(); - this.setState({ - ...this.state, - generatorCode, - models: response.models, - loaded: { - ...this.state.loaded, - hasReceivedCode: true - }, - error: false, - statusCode: 200, - errorMessage: '', - }); - }).catch(error => { - console.error(error); - this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 500 }); - }); - } - } catch (e: any) { - console.error(e); - this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 400 }); - } - } - render() { - const { loaded } = this.state; + useEffect(() => { const isHardLoaded = loaded.hasReceivedCode; const isSoftLoaded = loaded.editorLoaded; - const isLoaded = isHardLoaded && isSoftLoaded; + setIsLoaded(isHardLoaded && isSoftLoaded); - const query = this.props.router.query as ModelinaQueryOptions; + const query = props.router.query as ModelinaQueryOptions; if (query.language !== undefined) { - this.config.language = query.language as any; + config.language = query.language as any; } if (query.enumKeyNamingFormat !== undefined) { - this.config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; + config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; } if (query.propertyNamingFormat !== undefined) { - this.config.propertyNamingFormat = query.propertyNamingFormat as any; + config.propertyNamingFormat = query.propertyNamingFormat as any; } if (query.modelNamingFormat !== undefined) { - this.config.modelNamingFormat = query.modelNamingFormat as any; + config.modelNamingFormat = query.modelNamingFormat as any; } if (query.showTypeMappingExample !== undefined) { - this.config.showTypeMappingExample = query.showTypeMappingExample === 'true'; + config.showTypeMappingExample = query.showTypeMappingExample === 'true'; } if (query.indentationType !== undefined) { - this.config.indentationType = query.indentationType as any; + config.indentationType = query.indentationType as any; } if (query.tsMarshalling !== undefined) { - this.config.tsMarshalling = query.tsMarshalling === 'true'; + config.tsMarshalling = query.tsMarshalling === 'true'; } if (query.tsModelType !== undefined) { - this.config.tsModelType = query.tsModelType as any; + config.tsModelType = query.tsModelType as any; } if (query.tsEnumType !== undefined) { - this.config.tsEnumType = query.tsEnumType as any; + config.tsEnumType = query.tsEnumType as any; } if (query.tsIncludeDescriptions !== undefined) { - this.config.tsIncludeDescriptions = - query.tsIncludeDescriptions === 'true'; + config.tsIncludeDescriptions = query.tsIncludeDescriptions === 'true'; } if (query.tsIncludeJsonBinPack !== undefined) { - this.config.tsIncludeJsonBinPack = - query.tsIncludeJsonBinPack === 'true'; + config.tsIncludeJsonBinPack = query.tsIncludeJsonBinPack === 'true'; } if (query.tsIncludeExampleFunction !== undefined) { - this.config.tsIncludeExampleFunction = - query.tsIncludeExampleFunction === 'true'; + config.tsIncludeExampleFunction = query.tsIncludeExampleFunction === 'true'; } if (query.csharpArrayType !== undefined) { - this.config.csharpArrayType = query.csharpArrayType as any; + config.csharpArrayType = query.csharpArrayType as any; } if (query.csharpAutoImplemented !== undefined) { - this.config.csharpAutoImplemented = - query.csharpAutoImplemented === 'true'; + config.csharpAutoImplemented = query.csharpAutoImplemented === 'true'; } if (query.csharpOverwriteHashcode !== undefined) { - this.config.csharpOverwriteHashcode = - query.csharpOverwriteHashcode === 'true'; + config.csharpOverwriteHashcode = query.csharpOverwriteHashcode === 'true'; } if (query.phpIncludeDescriptions !== undefined) { - this.config.phpIncludeDescriptions = - query.phpIncludeDescriptions === 'true'; + config.phpIncludeDescriptions = query.phpIncludeDescriptions === 'true'; } if (query.phpNamespace !== undefined) { - this.config.phpNamespace = query.phpNamespace; + config.phpNamespace = query.phpNamespace; } if (query.csharpIncludeJson !== undefined) { - this.config.csharpIncludeJson = - query.csharpIncludeJson === 'true'; + config.csharpIncludeJson = query.csharpIncludeJson === 'true'; } if (query.csharpOverwriteEqual !== undefined) { - this.config.csharpOverwriteEqual = - query.csharpOverwriteEqual === 'true'; + config.csharpOverwriteEqual = query.csharpOverwriteEqual === 'true'; } if (query.csharpIncludeNewtonsoft !== undefined) { - this.config.csharpIncludeNewtonsoft = - query.csharpIncludeNewtonsoft === 'true'; + config.csharpIncludeNewtonsoft = query.csharpIncludeNewtonsoft === 'true'; } if (query.csharpNamespace !== undefined) { - this.config.csharpNamespace = query.csharpNamespace; + config.csharpNamespace = query.csharpNamespace; } if (query.csharpNullable !== undefined) { - this.config.csharpNullable = query.csharpNullable === 'true'; + config.csharpNullable = query.csharpNullable === 'true'; } - if(query.cplusplusNamespace !== undefined) { - this.config.cplusplusNamespace = query.cplusplusNamespace; + if (query.cplusplusNamespace !== undefined) { + config.cplusplusNamespace = query.cplusplusNamespace; } if (query.javaPackageName !== undefined) { - this.config.javaPackageName = query.javaPackageName; + config.javaPackageName = query.javaPackageName; } if (query.javaIncludeJackson !== undefined) { - this.config.javaIncludeJackson = - query.javaIncludeJackson === 'true'; + config.javaIncludeJackson = query.javaIncludeJackson === 'true'; } if (query.javaIncludeMarshaling !== undefined) { - this.config.javaIncludeMarshaling = - query.javaIncludeMarshaling === 'true'; + config.javaIncludeMarshaling = query.javaIncludeMarshaling === 'true'; } if (query.javaArrayType !== undefined) { - this.config.javaArrayType = query.javaArrayType as any; + config.javaArrayType = query.javaArrayType as any; } if (query.javaOverwriteHashcode !== undefined) { - this.config.javaOverwriteHashcode = - query.javaOverwriteHashcode === 'true'; + config.javaOverwriteHashcode = query.javaOverwriteHashcode === 'true'; } if (query.javaOverwriteEqual !== undefined) { - this.config.javaOverwriteEqual = - query.javaOverwriteEqual === 'true'; + config.javaOverwriteEqual = query.javaOverwriteEqual === 'true'; } if (query.javaOverwriteToString !== undefined) { - this.config.javaOverwriteToString = - query.javaOverwriteToString === 'true'; + config.javaOverwriteToString = query.javaOverwriteToString === 'true'; } if (query.javaJavaDocs !== undefined) { - this.config.javaJavaDocs = - query.javaJavaDocs === 'true'; + config.javaJavaDocs = query.javaJavaDocs === 'true'; } if (query.javaJavaxAnnotation !== undefined) { - this.config.javaJavaxAnnotation = - query.javaJavaxAnnotation === 'true'; + config.javaJavaxAnnotation = query.javaJavaxAnnotation === 'true'; } - if(query.goPackageName !== undefined) { - this.config.goPackageName = query.goPackageName; + if (query.goPackageName !== undefined) { + config.goPackageName = query.goPackageName; } if (query.kotlinPackageName !== undefined) { - this.config.kotlinPackageName = query.kotlinPackageName; + config.kotlinPackageName = query.kotlinPackageName; } - if (this.props.router.isReady && !this.hasLoadedQuery) { - this.hasLoadedQuery = true; - this.generateNewCode(this.state.input); + + if (props.router.isReady && !hasLoadedQuery) { + setHasLoadedQuery(true); + generateNewCode(input); } + }, [props.router.isReady, hasLoadedQuery]); - let loader; - if (!isHardLoaded) { - loader = ( -
      - Loading Modelina Playground. Connecting to playground server... -
      - ); - } else if (!isSoftLoaded) { - loader = ( -
      - Loading Modelina Playground. Rendering playground components... -
      - ); - } - return ( -
      -
      - - Modelina Playground - - - Try out Modelina and see a small fraction of what it can do. Use it - to play around, with small examples, otherwise turn to the CLI or - library instead. - -
      - {loader} -
      - {/*
      -
      -
      -

      - Modelina Options -

      -

      - , or see the Modelina - configuration you can use directly in your library -

      -
      + const setNewConfig = (config: string, configValue: any, updateCode?: boolean) => { + setNewQuery(config, configValue); + /* eslint-disable-next-line security/detect-object-injection */ + (config as any)[config] = configValue; + if (updateCode === true || updateCode === undefined) { + generateNewCode(input); + } + }; -
      { - this.setState({ ...this.state, showGeneratorCode: false }); - }} - className={`${!this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' - } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - > -

      - Options -

      -
      -
      { - this.setState({ ...this.state, showGeneratorCode: true }); - }} - className={`${this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' - } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - > -

      - Generator code -

      -
      -
      - {this.state.showGeneratorCode ? ( -
      - -
      - ) : ( - - - - - - - - - - - - - - - - - - - - - - - - - - )} -
      */} -
      -
      - { - this.setState({ ...this.state, input: change }); - this.generateNewCode(change); - }} - editorDidMount={() => { - this.setState({ - loaded: { ...this.state.loaded, editorLoaded: true } - }); - }} - language="json" - /> -
      + /** + * Set a query key and value + */ + const setNewQuery = (queryKey: string, queryValue: any) => { + const newQuery = { + query: { ...props.router.query } + }; + + if (queryValue === false) { + delete newQuery.query[queryKey]; + } else { + /* eslint-disable-next-line security/detect-object-injection */ + newQuery.query[queryKey] = String(queryValue); + } + + Router.push(newQuery, undefined, { scroll: false }); + }; + + /** + * Tell the socket io server that we want some code + */ + const generateNewCode = (input: string) => { + try { + const message: GenerateMessage = { + ...config, + input: encode(JSON.stringify(JSON.parse(input))) + }; + + if (message.input.length > (props.maxInputSize || 30000)) { + console.error('Input too large, use a smaller example'); + setError(true); + setErrorMessage('Input too large, use a smaller example'); + setStatusCode(400); + } else { + const generators: { [key: string]: Function } = { + typescript: getTypeScriptGeneratorCode, + javascript: getJavaScriptGeneratorCode, + java: getJavaGeneratorCode, + go: getGoGeneratorCode, + csharp: getCSharpGeneratorCode, + rust: getRustGeneratorCode, + python: getPythonGeneratorCode, + dart: getDartGeneratorCode, + cplusplus: getCplusplusGeneratorCode, + kotlin: getKotlinGeneratorCode, + php: getPhpGeneratorCode + }; + + const generatorCode = generators[config.language](message); + + fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { + body: JSON.stringify(message), + method: 'POST' + }).then(async (res) => { + if (!res.ok) { + throw new Error(res.statusText); + } + + const response: UpdateMessage = await res.json(); + setGeneratorCode(generatorCode); + setModels(response.models); + setLoaded({ + ...loaded, + hasReceivedCode: true + }); + setError(false); + setStatusCode(200); + setErrorMessage(''); + }).catch(error => { + console.error(error); + setError(true); + setErrorMessage("Input is not a correct AsyncAPI document, so it cannot be processed."); + setStatusCode(500); + }); + } + } catch (e: any) { + console.error(e); + setError(true); + setErrorMessage("Input is not a correct AsyncAPI document, so it cannot be processed."); + setStatusCode(400); + } + }; + + return ( +
      + { + !isLoaded + ? +
      + Loading Modelina Playground. Rendering playground components...
      -
      - {this.state.error ? ( - - ) : ( - - - - )} + : +
      +
      + + + + +
      -
      -
      - ); - } -} -export default withRouter(Playground); \ No newline at end of file + } +
      + ); +}; + +export default withRouter(Playground); diff --git a/modelina-website/src/components/playground/Playground2.tsx b/modelina-website/src/components/playground/Playground2.tsx deleted file mode 100644 index 1525f658a0..0000000000 --- a/modelina-website/src/components/playground/Playground2.tsx +++ /dev/null @@ -1,348 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import MonacoEditorWrapper from '../MonacoEditorWrapper'; -import { - defaultAsyncapiDocument, - ModelinaOptions, - ModelinaQueryOptions, - GenerateMessage, - UpdateMessage -} from '@/types'; -import Router, { withRouter, NextRouter } from 'next/router'; -import { encode } from 'js-base64'; -import PlaygroundOptions from './PlaygroundOptions'; -import Heading from '../typography/Heading'; -import Paragraph from '../typography/Paragraph'; -import { - PlaygroundTypeScriptConfigContext, - PlaygroundCSharpConfigContext, - PlaygroundDartConfigContext, - PlaygroundGoConfigContext, - PlaygroundJavaConfigContext, - PlaygroundJavaScriptConfigContext, - PlaygroundKotlinConfigContext, - PlaygroundPythonConfigContext, - PlaygroundRustConfigContext, - PlaygroundCplusplusConfigContext, - PlaygroundGeneralConfigContext, - PlaygroundPhpConfigContext -} from '../contexts/PlaygroundConfigContext'; -import { PanelContextProvider } from '../contexts/PlaygroundPanelContext'; -import { usePlaygroundContext } from '../contexts/PlaygroundContext'; -import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; -import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; -import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; -import { getGoGeneratorCode } from '@/helpers/GeneratorCode/GoGenerator'; -import { getCSharpGeneratorCode } from '@/helpers/GeneratorCode/CSharpGenerator'; -import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; -import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; -import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; -import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; -import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; -import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; -import { Sidebar } from './Sidebar'; -import { Content } from './Content'; - -interface WithRouterProps { - router: NextRouter; -} - -interface ModelsGeneratorProps { - code: string; - name: string; -} -interface ModelinaPlaygroundProps extends WithRouterProps { - maxInputSize?: number; -} - -const Playground: React.FC = (props) => { - const { - input, - setInput, - models, - setModels, - generatorCode, - setGeneratorCode, - loaded, - setLoaded, - showGeneratorCode, - setShowGeneratorCode, - error, - setError, - statusCode, - setStatusCode, - errorMessage, - setErrorMessage, - isLoaded, - setIsLoaded, - hasLoadedQuery, - setHasLoadedQuery, - } = usePlaygroundContext(); - - const config: ModelinaOptions = { - language: 'typescript', - propertyNamingFormat: 'default', - modelNamingFormat: 'default', - enumKeyNamingFormat: 'default', - indentationType: 'spaces', - showTypeMappingExample: false, - tsMarshalling: false, - tsModelType: 'class', - tsEnumType: 'enum', - tsModuleSystem: 'CJS', - tsIncludeDescriptions: false, - tsIncludeExampleFunction: false, - tsIncludeJsonBinPack: false, - csharpArrayType: 'Array', - csharpAutoImplemented: false, - csharpOverwriteHashcode: false, - csharpIncludeJson: false, - csharpOverwriteEqual: false, - csharpIncludeNewtonsoft: false, - csharpNamespace: 'asyncapi.models', - csharpNullable: false, - phpIncludeDescriptions: false, - phpNamespace: 'AsyncAPI/Models', - cplusplusNamespace: 'AsyncapiModels', - javaPackageName: 'asyncapi.models', - javaIncludeJackson: false, - javaIncludeMarshaling: false, - javaArrayType: 'Array', - javaOverwriteHashcode: false, - javaOverwriteEqual: false, - javaOverwriteToString: false, - javaJavaDocs: false, - javaJavaxAnnotation: false, - goPackageName: 'asyncapi.models', - kotlinPackageName: 'asyncapi.models' - }; - - useEffect(() => { - const isHardLoaded = loaded.hasReceivedCode; - const isSoftLoaded = loaded.editorLoaded; - setIsLoaded(isHardLoaded && isSoftLoaded); - - const query = props.router.query as ModelinaQueryOptions; - if (query.language !== undefined) { - config.language = query.language as any; - } - if (query.enumKeyNamingFormat !== undefined) { - config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; - } - if (query.propertyNamingFormat !== undefined) { - config.propertyNamingFormat = query.propertyNamingFormat as any; - } - if (query.modelNamingFormat !== undefined) { - config.modelNamingFormat = query.modelNamingFormat as any; - } - if (query.showTypeMappingExample !== undefined) { - config.showTypeMappingExample = query.showTypeMappingExample === 'true'; - } - if (query.indentationType !== undefined) { - config.indentationType = query.indentationType as any; - } - if (query.tsMarshalling !== undefined) { - config.tsMarshalling = query.tsMarshalling === 'true'; - } - if (query.tsModelType !== undefined) { - config.tsModelType = query.tsModelType as any; - } - if (query.tsEnumType !== undefined) { - config.tsEnumType = query.tsEnumType as any; - } - if (query.tsIncludeDescriptions !== undefined) { - config.tsIncludeDescriptions = query.tsIncludeDescriptions === 'true'; - } - if (query.tsIncludeJsonBinPack !== undefined) { - config.tsIncludeJsonBinPack = query.tsIncludeJsonBinPack === 'true'; - } - if (query.tsIncludeExampleFunction !== undefined) { - config.tsIncludeExampleFunction = query.tsIncludeExampleFunction === 'true'; - } - if (query.csharpArrayType !== undefined) { - config.csharpArrayType = query.csharpArrayType as any; - } - if (query.csharpAutoImplemented !== undefined) { - config.csharpAutoImplemented = query.csharpAutoImplemented === 'true'; - } - if (query.csharpOverwriteHashcode !== undefined) { - config.csharpOverwriteHashcode = query.csharpOverwriteHashcode === 'true'; - } - if (query.phpIncludeDescriptions !== undefined) { - config.phpIncludeDescriptions = query.phpIncludeDescriptions === 'true'; - } - if (query.phpNamespace !== undefined) { - config.phpNamespace = query.phpNamespace; - } - if (query.csharpIncludeJson !== undefined) { - config.csharpIncludeJson = query.csharpIncludeJson === 'true'; - } - if (query.csharpOverwriteEqual !== undefined) { - config.csharpOverwriteEqual = query.csharpOverwriteEqual === 'true'; - } - if (query.csharpIncludeNewtonsoft !== undefined) { - config.csharpIncludeNewtonsoft = query.csharpIncludeNewtonsoft === 'true'; - } - if (query.csharpNamespace !== undefined) { - config.csharpNamespace = query.csharpNamespace; - } - if (query.csharpNullable !== undefined) { - config.csharpNullable = query.csharpNullable === 'true'; - } - if (query.cplusplusNamespace !== undefined) { - config.cplusplusNamespace = query.cplusplusNamespace; - } - if (query.javaPackageName !== undefined) { - config.javaPackageName = query.javaPackageName; - } - if (query.javaIncludeJackson !== undefined) { - config.javaIncludeJackson = query.javaIncludeJackson === 'true'; - } - if (query.javaIncludeMarshaling !== undefined) { - config.javaIncludeMarshaling = query.javaIncludeMarshaling === 'true'; - } - if (query.javaArrayType !== undefined) { - config.javaArrayType = query.javaArrayType as any; - } - if (query.javaOverwriteHashcode !== undefined) { - config.javaOverwriteHashcode = query.javaOverwriteHashcode === 'true'; - } - if (query.javaOverwriteEqual !== undefined) { - config.javaOverwriteEqual = query.javaOverwriteEqual === 'true'; - } - if (query.javaOverwriteToString !== undefined) { - config.javaOverwriteToString = query.javaOverwriteToString === 'true'; - } - if (query.javaJavaDocs !== undefined) { - config.javaJavaDocs = query.javaJavaDocs === 'true'; - } - if (query.javaJavaxAnnotation !== undefined) { - config.javaJavaxAnnotation = query.javaJavaxAnnotation === 'true'; - } - if (query.goPackageName !== undefined) { - config.goPackageName = query.goPackageName; - } - if (query.kotlinPackageName !== undefined) { - config.kotlinPackageName = query.kotlinPackageName; - } - - if (props.router.isReady && !hasLoadedQuery) { - setHasLoadedQuery(true); - generateNewCode(input); - } - }, [props.router.isReady, hasLoadedQuery]); - - const setNewConfig = (config: string, configValue: any, updateCode?: boolean) => { - setNewQuery(config, configValue); - /* eslint-disable-next-line security/detect-object-injection */ - (config as any)[config] = configValue; - if (updateCode === true || updateCode === undefined) { - generateNewCode(input); - } - }; - - /** - * Set a query key and value - */ - const setNewQuery = (queryKey: string, queryValue: any) => { - const newQuery = { - query: { ...props.router.query } - }; - - if (queryValue === false) { - delete newQuery.query[queryKey]; - } else { - /* eslint-disable-next-line security/detect-object-injection */ - newQuery.query[queryKey] = String(queryValue); - } - - Router.push(newQuery, undefined, { scroll: false }); - }; - - /** - * Tell the socket io server that we want some code - */ - const generateNewCode = (input: string) => { - try { - const message: GenerateMessage = { - ...config, - input: encode(JSON.stringify(JSON.parse(input))) - }; - - if (message.input.length > (props.maxInputSize || 30000)) { - console.error('Input too large, use a smaller example'); - setError(true); - setErrorMessage('Input too large, use a smaller example'); - setStatusCode(400); - } else { - const generators: { [key: string]: Function } = { - typescript: getTypeScriptGeneratorCode, - javascript: getJavaScriptGeneratorCode, - java: getJavaGeneratorCode, - go: getGoGeneratorCode, - csharp: getCSharpGeneratorCode, - rust: getRustGeneratorCode, - python: getPythonGeneratorCode, - dart: getDartGeneratorCode, - cplusplus: getCplusplusGeneratorCode, - kotlin: getKotlinGeneratorCode, - php: getPhpGeneratorCode - }; - - const generatorCode = generators[config.language](message); - - fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { - body: JSON.stringify(message), - method: 'POST' - }).then(async (res) => { - if (!res.ok) { - throw new Error(res.statusText); - } - - const response: UpdateMessage = await res.json(); - setGeneratorCode(generatorCode); - setModels(response.models); - setLoaded({ - ...loaded, - hasReceivedCode: true - }); - setError(false); - setStatusCode(200); - setErrorMessage(''); - }).catch(error => { - console.error(error); - setError(true); - setErrorMessage("Input is not a correct AsyncAPI document, so it cannot be processed."); - setStatusCode(500); - }); - } - } catch (e: any) { - console.error(e); - setError(true); - setErrorMessage("Input is not a correct AsyncAPI document, so it cannot be processed."); - setStatusCode(400); - } - }; - - return ( -
      - { - isLoaded - ? -
      - Loading Modelina Playground. Rendering playground components... -
      - : -
      -
      - - - - -
      -
      - } -
      - ); -}; - -export default withRouter(Playground); diff --git a/modelina-website/src/components/playground/Sidebar.tsx b/modelina-website/src/components/playground/Sidebar.tsx index 7408a431b2..a5994bc8d1 100644 --- a/modelina-website/src/components/playground/Sidebar.tsx +++ b/modelina-website/src/components/playground/Sidebar.tsx @@ -43,7 +43,7 @@ export const Sidebar: React.FunctionComponent = () => { ]; return ( -
      +
      {sidebarItems.map((item) => ( = () => { className={ item.isActive ? 'bg-gray-900 p-2 rounded text-white' - : 'p-2 text-gray-700 hover:text-gray-900' + : 'p-2 text-gray-700 hover:text-white' } > {item.icon} diff --git a/modelina-website/src/pages/playground.tsx b/modelina-website/src/pages/playground.tsx index 33687bd3ee..b1bd72e6e6 100644 --- a/modelina-website/src/pages/playground.tsx +++ b/modelina-website/src/pages/playground.tsx @@ -1,5 +1,5 @@ import Playground from '@/components/playground/Playground'; -import Playground2 from '@/components/playground/Playground2'; +import OldPlayground from '@/components/playground/OldPlayground'; import NewPlayground from '@/components/playground/NewPlayground'; import GenericLayout from '@/components/layouts/GenericLayout'; import { PlaygroundContextProvider } from '@/components/contexts/PlaygroundContext'; @@ -15,11 +15,13 @@ export default function PlaygroundPage() { image={image} wide full + padding = "" + footerPadding = "mb-0" > - {/* */} + {/* */} {/* */} - + ); From 1717d1f93131da4f92d1379edbde19f0035686bd Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Mon, 4 Dec 2023 08:49:43 +0530 Subject: [PATCH 13/29] rectified InfoModal paddings --- modelina-website/src/components/InfoModal.tsx | 4 +- .../src/components/playground/Navigation.tsx | 61 +++++++++++-------- .../playground/PlaygroundOptions.tsx | 2 +- .../playground/options/GeneralOptions.tsx | 16 +++-- .../options/TypeScriptGeneratorOptions.tsx | 46 +++++++------- 5 files changed, 71 insertions(+), 58 deletions(-) diff --git a/modelina-website/src/components/InfoModal.tsx b/modelina-website/src/components/InfoModal.tsx index 7b93ff2109..8564c3a5da 100644 --- a/modelina-website/src/components/InfoModal.tsx +++ b/modelina-website/src/components/InfoModal.tsx @@ -24,7 +24,7 @@ export default function InfoModal(props: InfoModalProps){ <>
      -
      +

      {props.text}

      {props.children} @@ -38,7 +38,7 @@ export default function InfoModal(props: InfoModalProps){ return( <> -} const Output: React.FunctionComponent = () => { - const { renderModels } = usePlaygroundContext(); - console.log(renderModels); + const { renderModels, showGeneratorCode, setShowGeneratorCode } = usePlaygroundContext(); return (
      - +
      setShowGeneratorCode(true)}>Generator Code
      -
      +

      This list contains all the generated models, select one to show their generated code.

      - +
      Generated Models
      + {renderModels}
      ) } const Options: React.FunctionComponent = ({ config, setNewConfig }) => { - const { - generatorCode, - showGeneratorCode, - setShowGeneratorCode, - } = usePlaygroundContext(); return ( - //
      - //
      - //
      - //

      - // Modelina Options - //

      - //

      - // , or see the Modelina - // configuration you can use directly in your library - //

      - //
      - - //
      { - // setShowGeneratorCode(false); - // }} - // className={`${!showGeneratorCode ? 'bg-blue-100' : 'bg-white' - // } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - // > - //

      - // Options - //

      - //
      - - //
      { - // setShowGeneratorCode(true); - // }} - // className={`${showGeneratorCode ? 'bg-blue-100' : 'bg-white' - // } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - // > - //

      - // Generator code - //

      - //
      - //
      - // {showGeneratorCode ? ( - //
      - // - //
      - // ) : ( - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // )} - //
      -
      From c8e44c42b77bb8708e7ecbb65560c8bafaea171b Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Mon, 4 Dec 2023 11:40:31 +0530 Subject: [PATCH 17/29] performed code cleanups --- .../src/components/playground/Content.tsx | 12 - .../src/components/playground/Navigation.tsx | 23 - .../components/playground/NewPlayground.tsx | 374 ------------- .../components/playground/OldPlayground.tsx | 492 ------------------ .../src/components/playground/Playground.tsx | 34 +- 5 files changed, 1 insertion(+), 934 deletions(-) delete mode 100644 modelina-website/src/components/playground/NewPlayground.tsx delete mode 100644 modelina-website/src/components/playground/OldPlayground.tsx diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index 0bc80de2df..40259b2f67 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -23,23 +23,11 @@ export const Content: FunctionComponent = ({ config, setNewConfig, input, setInput, models, - setModels, - generatorCode, - setGeneratorCode, loaded, setLoaded, - showGeneratorCode, - setShowGeneratorCode, error, - setError, statusCode, - setStatusCode, errorMessage, - setErrorMessage, - isLoaded, - setIsLoaded, - hasLoadedQuery, - setHasLoadedQuery, } = usePlaygroundContext(); const panelEnabled = panel !== ''; diff --git a/modelina-website/src/components/playground/Navigation.tsx b/modelina-website/src/components/playground/Navigation.tsx index 09c0582cba..448533a0d3 100644 --- a/modelina-website/src/components/playground/Navigation.tsx +++ b/modelina-website/src/components/playground/Navigation.tsx @@ -1,8 +1,6 @@ import React from "react"; -import Router, { withRouter, NextRouter } from 'next/router'; import { usePanelContext } from "../contexts/PlaygroundPanelContext"; import PlaygroundOptions from './PlaygroundOptions'; -import MonacoEditorWrapper from '../MonacoEditorWrapper'; import { PlaygroundTypeScriptConfigContext, PlaygroundCSharpConfigContext, @@ -17,29 +15,8 @@ import { PlaygroundGeneralConfigContext, PlaygroundPhpConfigContext } from '../contexts/PlaygroundConfigContext'; -import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; -import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; -import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; -import { getGoGeneratorCode } from '@/helpers/GeneratorCode/GoGenerator'; -import { getCSharpGeneratorCode } from '@/helpers/GeneratorCode/CSharpGenerator'; -import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; -import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; -import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; -import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; -import CustomError from '../CustomError'; -import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; -import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; -import { encode } from 'js-base64'; -import GeneratedModelsComponent from './GeneratedModels'; -import Heading from '../typography/Heading'; -import Paragraph from '../typography/Paragraph'; -import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; import { - defaultAsyncapiDocument, ModelinaOptions, - ModelinaQueryOptions, - GenerateMessage, - UpdateMessage } from '@/types'; import { usePlaygroundContext } from "../contexts/PlaygroundContext"; import InfoModal from "../InfoModal"; diff --git a/modelina-website/src/components/playground/NewPlayground.tsx b/modelina-website/src/components/playground/NewPlayground.tsx deleted file mode 100644 index 0972fd0322..0000000000 --- a/modelina-website/src/components/playground/NewPlayground.tsx +++ /dev/null @@ -1,374 +0,0 @@ -import React from 'react'; -import MonacoEditorWrapper from '../MonacoEditorWrapper'; -import { - defaultAsyncapiDocument, - ModelinaOptions, - ModelinaQueryOptions, - GenerateMessage, - UpdateMessage -} from '@/types'; -import Router, { withRouter, NextRouter } from 'next/router'; -import { encode } from 'js-base64'; -import GeneratedModelsComponent from './GeneratedModels'; -import PlaygroundOptions from './PlaygroundOptions'; -import { Sidebar } from './Sidebar'; -import Heading from '../typography/Heading'; -import Paragraph from '../typography/Paragraph'; -import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; -import { - PlaygroundTypeScriptConfigContext, - PlaygroundCSharpConfigContext, - PlaygroundDartConfigContext, - PlaygroundGoConfigContext, - PlaygroundJavaConfigContext, - PlaygroundJavaScriptConfigContext, - PlaygroundKotlinConfigContext, - PlaygroundPythonConfigContext, - PlaygroundRustConfigContext, - PlaygroundCplusplusConfigContext, - PlaygroundGeneralConfigContext, - PlaygroundPhpConfigContext -} from '../contexts/PlaygroundConfigContext'; -import { PanelContextProvider } from '../contexts/PlaygroundPanelContext'; -import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; -import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; -import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; -import { getGoGeneratorCode } from '@/helpers/GeneratorCode/GoGenerator'; -import { getCSharpGeneratorCode } from '@/helpers/GeneratorCode/CSharpGenerator'; -import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; -import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; -import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; -import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; -import CustomError from '../CustomError'; -import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; -import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; -import { Content } from './Content'; - -interface WithRouterProps { - router: NextRouter; -} - -interface ModelsGeneratorProps { - code: string; - name: string; -} -interface ModelinaPlaygroundProps extends WithRouterProps { - maxInputSize?: number; -} - -type ModelinaPlaygroundState = { - input: string; - models: ModelsGeneratorProps[]; - generatorCode: string; - loaded: { - editorLoaded: boolean; - hasReceivedCode: boolean; - }; - showGeneratorCode: boolean; - error: boolean; - statusCode: number; - errorMessage: string; -}; - -class Playground extends React.Component< - ModelinaPlaygroundProps, - ModelinaPlaygroundState -> { - config: ModelinaOptions = { - language: 'typescript', - propertyNamingFormat: 'default', - modelNamingFormat: 'default', - enumKeyNamingFormat: 'default', - indentationType: 'spaces', - showTypeMappingExample: false, - tsMarshalling: false, - tsModelType: 'class', - tsEnumType: 'enum', - tsModuleSystem: 'CJS', - tsIncludeDescriptions: false, - tsIncludeExampleFunction: false, - tsIncludeJsonBinPack: false, - csharpArrayType: 'Array', - csharpAutoImplemented: false, - csharpOverwriteHashcode: false, - csharpIncludeJson: false, - csharpOverwriteEqual: false, - csharpIncludeNewtonsoft: false, - csharpNamespace: 'asyncapi.models', - csharpNullable: false, - phpIncludeDescriptions: false, - phpNamespace: 'AsyncAPI/Models', - cplusplusNamespace: 'AsyncapiModels', - javaPackageName: 'asyncapi.models', - javaIncludeJackson: false, - javaIncludeMarshaling: false, - javaArrayType: 'Array', - javaOverwriteHashcode: false, - javaOverwriteEqual: false, - javaOverwriteToString: false, - javaJavaDocs: false, - javaJavaxAnnotation: false, - goPackageName: 'asyncapi.models', - kotlinPackageName: 'asyncapi.models' - }; - hasLoadedQuery: boolean = false; - constructor(props: ModelinaPlaygroundProps) { - super(props); - this.state = { - input: JSON.stringify(defaultAsyncapiDocument, null, 4), - models: [], - generatorCode: '', - loaded: { - editorLoaded: false, - hasReceivedCode: false - }, - showGeneratorCode: false, - error: false, - statusCode: 400, - errorMessage: 'Bad Request', - }; - this.setNewConfig = this.setNewConfig.bind(this); - this.setNewQuery = this.setNewQuery.bind(this); - this.generateNewCode = this.generateNewCode.bind(this); - } - - setNewConfig(config: string, configValue: any, updateCode?: boolean) { - this.setNewQuery(config, configValue); - /* eslint-disable-next-line security/detect-object-injection */ - (this.config as any)[config] = configValue; - if (updateCode === true || updateCode === undefined) { - this.generateNewCode(this.state.input); - } - } - - /** - * Set a query key and value - */ - setNewQuery(queryKey: string, queryValue: any) { - const newQuery = { - query: { ...this.props.router.query } - }; - if (queryValue === false) { - delete newQuery.query[queryKey]; - } else { - /* eslint-disable-next-line security/detect-object-injection */ - newQuery.query[queryKey] = String(queryValue); - } - Router.push(newQuery, undefined, { scroll: false }); - } - - /** - * Tell the socket io server that we want some code - */ - generateNewCode(input: string) { - try { - const message: GenerateMessage = { - ...this.config, - input: encode(JSON.stringify(JSON.parse(input))) - }; - if (message.input.length > (this.props.maxInputSize || 30000)) { - console.error('Input too large, use smaller example'); - this.setState({ ...this.state, error: true, errorMessage: 'Input too large, use smaller example', statusCode: 400 }); - } else { - const generators: { [key: string]: Function } = { - typescript: getTypeScriptGeneratorCode, - javascript: getJavaScriptGeneratorCode, - java: getJavaGeneratorCode, - go: getGoGeneratorCode, - csharp: getCSharpGeneratorCode, - rust: getRustGeneratorCode, - python: getPythonGeneratorCode, - dart: getDartGeneratorCode, - cplusplus: getCplusplusGeneratorCode, - kotlin: getKotlinGeneratorCode, - php: getPhpGeneratorCode - } - const generatorCode = generators[this.config.language](message); - fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { - body: JSON.stringify(message), - method: 'POST' - }).then(async (res) => { - if (!res.ok) { - throw new Error(res.statusText); - } - const response: UpdateMessage = await res.json(); - this.setState({ - ...this.state, - generatorCode, - models: response.models, - loaded: { - ...this.state.loaded, - hasReceivedCode: true - }, - error: false, - statusCode: 200, - errorMessage: '', - }); - }).catch(error => { - console.error(error); - this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 500 }); - }); - } - } catch (e: any) { - console.error(e); - this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 400 }); - } - } - - render() { - const { loaded } = this.state; - const isHardLoaded = loaded.hasReceivedCode; - const isSoftLoaded = loaded.editorLoaded; - const isLoaded = isHardLoaded && isSoftLoaded; - - const query = this.props.router.query as ModelinaQueryOptions; - if (query.language !== undefined) { - this.config.language = query.language as any; - } - if (query.enumKeyNamingFormat !== undefined) { - this.config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; - } - if (query.propertyNamingFormat !== undefined) { - this.config.propertyNamingFormat = query.propertyNamingFormat as any; - } - if (query.modelNamingFormat !== undefined) { - this.config.modelNamingFormat = query.modelNamingFormat as any; - } - if (query.showTypeMappingExample !== undefined) { - this.config.showTypeMappingExample = query.showTypeMappingExample === 'true'; - } - if (query.indentationType !== undefined) { - this.config.indentationType = query.indentationType as any; - } - if (query.tsMarshalling !== undefined) { - this.config.tsMarshalling = query.tsMarshalling === 'true'; - } - if (query.tsModelType !== undefined) { - this.config.tsModelType = query.tsModelType as any; - } - if (query.tsEnumType !== undefined) { - this.config.tsEnumType = query.tsEnumType as any; - } - if (query.tsIncludeDescriptions !== undefined) { - this.config.tsIncludeDescriptions = - query.tsIncludeDescriptions === 'true'; - } - if (query.tsIncludeJsonBinPack !== undefined) { - this.config.tsIncludeJsonBinPack = - query.tsIncludeJsonBinPack === 'true'; - } - if (query.tsIncludeExampleFunction !== undefined) { - this.config.tsIncludeExampleFunction = - query.tsIncludeExampleFunction === 'true'; - } - if (query.csharpArrayType !== undefined) { - this.config.csharpArrayType = query.csharpArrayType as any; - } - if (query.csharpAutoImplemented !== undefined) { - this.config.csharpAutoImplemented = - query.csharpAutoImplemented === 'true'; - } - if (query.csharpOverwriteHashcode !== undefined) { - this.config.csharpOverwriteHashcode = - query.csharpOverwriteHashcode === 'true'; - } - if (query.phpIncludeDescriptions !== undefined) { - this.config.phpIncludeDescriptions = - query.phpIncludeDescriptions === 'true'; - } - if (query.phpNamespace !== undefined) { - this.config.phpNamespace = query.phpNamespace; - } - if (query.csharpIncludeJson !== undefined) { - this.config.csharpIncludeJson = - query.csharpIncludeJson === 'true'; - } - if (query.csharpOverwriteEqual !== undefined) { - this.config.csharpOverwriteEqual = - query.csharpOverwriteEqual === 'true'; - } - if (query.csharpIncludeNewtonsoft !== undefined) { - this.config.csharpIncludeNewtonsoft = - query.csharpIncludeNewtonsoft === 'true'; - } - if (query.csharpNamespace !== undefined) { - this.config.csharpNamespace = query.csharpNamespace; - } - if (query.csharpNullable !== undefined) { - this.config.csharpNullable = query.csharpNullable === 'true'; - } - if (query.cplusplusNamespace !== undefined) { - this.config.cplusplusNamespace = query.cplusplusNamespace; - } - if (query.javaPackageName !== undefined) { - this.config.javaPackageName = query.javaPackageName; - } - if (query.javaIncludeJackson !== undefined) { - this.config.javaIncludeJackson = - query.javaIncludeJackson === 'true'; - } - if (query.javaIncludeMarshaling !== undefined) { - this.config.javaIncludeMarshaling = - query.javaIncludeMarshaling === 'true'; - } - if (query.javaArrayType !== undefined) { - this.config.javaArrayType = query.javaArrayType as any; - } - if (query.javaOverwriteHashcode !== undefined) { - this.config.javaOverwriteHashcode = - query.javaOverwriteHashcode === 'true'; - } - if (query.javaOverwriteEqual !== undefined) { - this.config.javaOverwriteEqual = - query.javaOverwriteEqual === 'true'; - } - if (query.javaOverwriteToString !== undefined) { - this.config.javaOverwriteToString = - query.javaOverwriteToString === 'true'; - } - if (query.javaJavaDocs !== undefined) { - this.config.javaJavaDocs = - query.javaJavaDocs === 'true'; - } - if (query.javaJavaxAnnotation !== undefined) { - this.config.javaJavaxAnnotation = - query.javaJavaxAnnotation === 'true'; - } - if (query.goPackageName !== undefined) { - this.config.goPackageName = query.goPackageName; - } - if (query.kotlinPackageName !== undefined) { - this.config.kotlinPackageName = query.kotlinPackageName; - } - if (this.props.router.isReady && !this.hasLoadedQuery) { - this.hasLoadedQuery = true; - this.generateNewCode(this.state.input); - } - - let loader; - if (!isHardLoaded) { - loader = ( -
      - Loading Modelina Playground. Connecting to playground server... -
      - ); - } else if (!isSoftLoaded) { - loader = ( -
      - Loading Modelina Playground. Rendering playground components... -
      - ); - } - return ( -
      -
      - - - - -
      -
      - ); - } -} -export default withRouter(Playground); diff --git a/modelina-website/src/components/playground/OldPlayground.tsx b/modelina-website/src/components/playground/OldPlayground.tsx deleted file mode 100644 index b7cfd7388f..0000000000 --- a/modelina-website/src/components/playground/OldPlayground.tsx +++ /dev/null @@ -1,492 +0,0 @@ -import React from 'react'; -import MonacoEditorWrapper from '../MonacoEditorWrapper'; -import { - defaultAsyncapiDocument, - ModelinaOptions, - ModelinaQueryOptions, - GenerateMessage, - UpdateMessage -} from '@/types'; -import Router, { withRouter, NextRouter } from 'next/router'; -import { encode } from 'js-base64'; -import GeneratedModelsComponent from './GeneratedModels'; -import PlaygroundOptions from './PlaygroundOptions'; -import Heading from '../typography/Heading'; -import Paragraph from '../typography/Paragraph'; -import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; -import { - PlaygroundTypeScriptConfigContext, - PlaygroundCSharpConfigContext, - PlaygroundDartConfigContext, - PlaygroundGoConfigContext, - PlaygroundJavaConfigContext, - PlaygroundJavaScriptConfigContext, - PlaygroundKotlinConfigContext, - PlaygroundPythonConfigContext, - PlaygroundRustConfigContext, - PlaygroundCplusplusConfigContext, - PlaygroundGeneralConfigContext, - PlaygroundPhpConfigContext -} from '../contexts/PlaygroundConfigContext'; -import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; -import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; -import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; -import { getGoGeneratorCode } from '@/helpers/GeneratorCode/GoGenerator'; -import { getCSharpGeneratorCode } from '@/helpers/GeneratorCode/CSharpGenerator'; -import { getRustGeneratorCode } from '@/helpers/GeneratorCode/RustGenerator'; -import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator'; -import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; -import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; -import CustomError from '../CustomError'; -import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; -import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; - -interface WithRouterProps { - router: NextRouter; -} - -interface ModelsGeneratorProps { - code: string; - name: string; -} -interface ModelinaPlaygroundProps extends WithRouterProps { - maxInputSize?: number; -} - -type ModelinaPlaygroundState = { - input: string; - models: ModelsGeneratorProps[]; - generatorCode: string; - loaded: { - editorLoaded: boolean; - hasReceivedCode: boolean; - }; - showGeneratorCode: boolean; - error: boolean; - statusCode: number; - errorMessage: string; -}; - -class Playground extends React.Component< - ModelinaPlaygroundProps, - ModelinaPlaygroundState -> { - config: ModelinaOptions = { - language: 'typescript', - propertyNamingFormat: 'default', - modelNamingFormat: 'default', - enumKeyNamingFormat: 'default', - indentationType: 'spaces', - showTypeMappingExample: false, - tsMarshalling: false, - tsModelType: 'class', - tsEnumType: 'enum', - tsModuleSystem: 'CJS', - tsIncludeDescriptions: false, - tsIncludeExampleFunction: false, - tsIncludeJsonBinPack: false, - csharpArrayType: 'Array', - csharpAutoImplemented: false, - csharpOverwriteHashcode: false, - csharpIncludeJson: false, - csharpOverwriteEqual: false, - csharpIncludeNewtonsoft: false, - csharpNamespace: 'asyncapi.models', - csharpNullable: false, - phpIncludeDescriptions: false, - phpNamespace: 'AsyncAPI/Models', - cplusplusNamespace: 'AsyncapiModels', - javaPackageName: 'asyncapi.models', - javaIncludeJackson: false, - javaIncludeMarshaling: false, - javaArrayType: 'Array', - javaOverwriteHashcode: false, - javaOverwriteEqual: false, - javaOverwriteToString: false, - javaJavaDocs: false, - javaJavaxAnnotation: false, - goPackageName: 'asyncapi.models', - kotlinPackageName: 'asyncapi.models' - }; - hasLoadedQuery: boolean = false; - constructor(props: ModelinaPlaygroundProps) { - super(props); - this.state = { - input: JSON.stringify(defaultAsyncapiDocument, null, 4), - models: [], - generatorCode: '', - loaded: { - editorLoaded: false, - hasReceivedCode: false - }, - showGeneratorCode: false, - error: false, - statusCode: 400, - errorMessage: 'Bad Request', - }; - this.setNewConfig = this.setNewConfig.bind(this); - this.setNewQuery = this.setNewQuery.bind(this); - this.generateNewCode = this.generateNewCode.bind(this); - } - - setNewConfig(config: string, configValue: any, updateCode?: boolean) { - this.setNewQuery(config, configValue); - /* eslint-disable-next-line security/detect-object-injection */ - (this.config as any)[config] = configValue; - if(updateCode === true || updateCode === undefined) { - this.generateNewCode(this.state.input); - } - } - - /** - * Set a query key and value - */ - setNewQuery(queryKey: string, queryValue: any) { - const newQuery = { - query: { ...this.props.router.query } - }; - if(queryValue === false) { - delete newQuery.query[queryKey]; - } else { - /* eslint-disable-next-line security/detect-object-injection */ - newQuery.query[queryKey] = String(queryValue); - } - Router.push(newQuery, undefined, { scroll: false }); - } - - /** - * Tell the socket io server that we want some code - */ - generateNewCode(input: string) { - try { - const message: GenerateMessage = { - ...this.config, - input: encode(JSON.stringify(JSON.parse(input))) - }; - if (message.input.length > (this.props.maxInputSize || 30000)) { - console.error('Input too large, use smaller example'); - this.setState({ ...this.state, error: true, errorMessage: 'Input too large, use smaller example', statusCode: 400 }); - } else { - const generators: { [key: string]: Function } = { - typescript: getTypeScriptGeneratorCode, - javascript: getJavaScriptGeneratorCode, - java: getJavaGeneratorCode, - go: getGoGeneratorCode, - csharp: getCSharpGeneratorCode, - rust: getRustGeneratorCode, - python: getPythonGeneratorCode, - dart: getDartGeneratorCode, - cplusplus: getCplusplusGeneratorCode, - kotlin: getKotlinGeneratorCode, - php: getPhpGeneratorCode - } - const generatorCode = generators[this.config.language](message); - fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { - body: JSON.stringify(message), - method: 'POST' - }).then(async (res) => { - if (!res.ok) { - throw new Error(res.statusText); - } - const response: UpdateMessage = await res.json(); - this.setState({ - ...this.state, - generatorCode, - models: response.models, - loaded: { - ...this.state.loaded, - hasReceivedCode: true - }, - error: false, - statusCode: 200, - errorMessage: '', - }); - }).catch(error => { - console.error(error); - this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 500 }); - }); - } - } catch (e: any) { - console.error(e); - this.setState({ ...this.state, error: true, errorMessage: "Input is not an correct AsyncAPI document so it cannot be processed.", statusCode: 400 }); - } - } - - render() { - const { loaded } = this.state; - const isHardLoaded = loaded.hasReceivedCode; - const isSoftLoaded = loaded.editorLoaded; - const isLoaded = isHardLoaded && isSoftLoaded; - - const query = this.props.router.query as ModelinaQueryOptions; - if (query.language !== undefined) { - this.config.language = query.language as any; - } - if (query.enumKeyNamingFormat !== undefined) { - this.config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; - } - if (query.propertyNamingFormat !== undefined) { - this.config.propertyNamingFormat = query.propertyNamingFormat as any; - } - if (query.modelNamingFormat !== undefined) { - this.config.modelNamingFormat = query.modelNamingFormat as any; - } - if (query.showTypeMappingExample !== undefined) { - this.config.showTypeMappingExample = query.showTypeMappingExample === 'true'; - } - if (query.indentationType !== undefined) { - this.config.indentationType = query.indentationType as any; - } - if (query.tsMarshalling !== undefined) { - this.config.tsMarshalling = query.tsMarshalling === 'true'; - } - if (query.tsModelType !== undefined) { - this.config.tsModelType = query.tsModelType as any; - } - if (query.tsEnumType !== undefined) { - this.config.tsEnumType = query.tsEnumType as any; - } - if (query.tsIncludeDescriptions !== undefined) { - this.config.tsIncludeDescriptions = - query.tsIncludeDescriptions === 'true'; - } - if (query.tsIncludeJsonBinPack !== undefined) { - this.config.tsIncludeJsonBinPack = - query.tsIncludeJsonBinPack === 'true'; - } - if (query.tsIncludeExampleFunction !== undefined) { - this.config.tsIncludeExampleFunction = - query.tsIncludeExampleFunction === 'true'; - } - if (query.csharpArrayType !== undefined) { - this.config.csharpArrayType = query.csharpArrayType as any; - } - if (query.csharpAutoImplemented !== undefined) { - this.config.csharpAutoImplemented = - query.csharpAutoImplemented === 'true'; - } - if (query.csharpOverwriteHashcode !== undefined) { - this.config.csharpOverwriteHashcode = - query.csharpOverwriteHashcode === 'true'; - } - if (query.phpIncludeDescriptions !== undefined) { - this.config.phpIncludeDescriptions = - query.phpIncludeDescriptions === 'true'; - } - if (query.phpNamespace !== undefined) { - this.config.phpNamespace = query.phpNamespace; - } - if (query.csharpIncludeJson !== undefined) { - this.config.csharpIncludeJson = - query.csharpIncludeJson === 'true'; - } - if (query.csharpOverwriteEqual !== undefined) { - this.config.csharpOverwriteEqual = - query.csharpOverwriteEqual === 'true'; - } - if (query.csharpIncludeNewtonsoft !== undefined) { - this.config.csharpIncludeNewtonsoft = - query.csharpIncludeNewtonsoft === 'true'; - } - if (query.csharpNamespace !== undefined) { - this.config.csharpNamespace = query.csharpNamespace; - } - if (query.csharpNullable !== undefined) { - this.config.csharpNullable = query.csharpNullable === 'true'; - } - if(query.cplusplusNamespace !== undefined) { - this.config.cplusplusNamespace = query.cplusplusNamespace; - } - if (query.javaPackageName !== undefined) { - this.config.javaPackageName = query.javaPackageName; - } - if (query.javaIncludeJackson !== undefined) { - this.config.javaIncludeJackson = - query.javaIncludeJackson === 'true'; - } - if (query.javaIncludeMarshaling !== undefined) { - this.config.javaIncludeMarshaling = - query.javaIncludeMarshaling === 'true'; - } - if (query.javaArrayType !== undefined) { - this.config.javaArrayType = query.javaArrayType as any; - } - if (query.javaOverwriteHashcode !== undefined) { - this.config.javaOverwriteHashcode = - query.javaOverwriteHashcode === 'true'; - } - if (query.javaOverwriteEqual !== undefined) { - this.config.javaOverwriteEqual = - query.javaOverwriteEqual === 'true'; - } - if (query.javaOverwriteToString !== undefined) { - this.config.javaOverwriteToString = - query.javaOverwriteToString === 'true'; - } - if (query.javaJavaDocs !== undefined) { - this.config.javaJavaDocs = - query.javaJavaDocs === 'true'; - } - if (query.javaJavaxAnnotation !== undefined) { - this.config.javaJavaxAnnotation = - query.javaJavaxAnnotation === 'true'; - } - if(query.goPackageName !== undefined) { - this.config.goPackageName = query.goPackageName; - } - if (query.kotlinPackageName !== undefined) { - this.config.kotlinPackageName = query.kotlinPackageName; - } - if (this.props.router.isReady && !this.hasLoadedQuery) { - this.hasLoadedQuery = true; - this.generateNewCode(this.state.input); - } - - let loader; - if (!isHardLoaded) { - loader = ( -
      - Loading Modelina Playground. Connecting to playground server... -
      - ); - } else if (!isSoftLoaded) { - loader = ( -
      - Loading Modelina Playground. Rendering playground components... -
      - ); - } - return ( -
      -
      - - Modelina Playground - - - Try out Modelina and see a small fraction of what it can do. Use it - to play around, with small examples, otherwise turn to the CLI or - library instead. - -
      - {loader} -
      -
      -
      -
      -

      - Modelina Options -

      -

      - , or see the Modelina - configuration you can use directly in your library -

      -
      - -
      { - this.setState({ ...this.state, showGeneratorCode: false }); - }} - className={`${!this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' - } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - > -

      - Options -

      -
      -
      { - this.setState({ ...this.state, showGeneratorCode: true }); - }} - className={`${this.state.showGeneratorCode ? 'bg-blue-100' : 'bg-white' - } px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 basis-3/12`} - > -

      - Generator code -

      -
      -
      - {this.state.showGeneratorCode ? ( -
      - -
      - ) : ( - - - - - - - - - - - - - - - - - - - - - - - - - - )} -
      -
      -
      - { - this.setState({ ...this.state, input: change }); - this.generateNewCode(change); - }} - editorDidMount={() => { - this.setState({ - loaded: { ...this.state.loaded, editorLoaded: true } - }); - }} - language="json" - /> -
      -
      -
      - {this.state.error ? ( - - ) : ( - - - - )} -
      -
      -
      - ); - } -} -export default withRouter(Playground); \ No newline at end of file diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 58171a0c6f..bfef18de72 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -1,7 +1,5 @@ -import React, { useState, useEffect } from 'react'; -import MonacoEditorWrapper from '../MonacoEditorWrapper'; +import React, { useEffect } from 'react'; import { - defaultAsyncapiDocument, ModelinaOptions, ModelinaQueryOptions, GenerateMessage, @@ -9,23 +7,6 @@ import { } from '@/types'; import Router, { withRouter, NextRouter } from 'next/router'; import { encode } from 'js-base64'; -import PlaygroundOptions from './PlaygroundOptions'; -import Heading from '../typography/Heading'; -import Paragraph from '../typography/Paragraph'; -import { - PlaygroundTypeScriptConfigContext, - PlaygroundCSharpConfigContext, - PlaygroundDartConfigContext, - PlaygroundGoConfigContext, - PlaygroundJavaConfigContext, - PlaygroundJavaScriptConfigContext, - PlaygroundKotlinConfigContext, - PlaygroundPythonConfigContext, - PlaygroundRustConfigContext, - PlaygroundCplusplusConfigContext, - PlaygroundGeneralConfigContext, - PlaygroundPhpConfigContext -} from '../contexts/PlaygroundConfigContext'; import { PanelContextProvider } from '../contexts/PlaygroundPanelContext'; import { usePlaygroundContext } from '../contexts/PlaygroundContext'; import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; @@ -45,11 +26,6 @@ import { Content } from './Content'; interface WithRouterProps { router: NextRouter; } - -interface ModelsGeneratorProps { - code: string; - name: string; -} interface ModelinaPlaygroundProps extends WithRouterProps { maxInputSize?: number; } @@ -57,20 +33,12 @@ interface ModelinaPlaygroundProps extends WithRouterProps { const Playground: React.FC = (props) => { const { input, - setInput, - models, setModels, - generatorCode, setGeneratorCode, loaded, setLoaded, - showGeneratorCode, - setShowGeneratorCode, - error, setError, - statusCode, setStatusCode, - errorMessage, setErrorMessage, isLoaded, setIsLoaded, From d2aaab08621dc52e1bf7b52adadceb82d22c786e Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Mon, 4 Dec 2023 11:41:25 +0530 Subject: [PATCH 18/29] performed code cleanups --- modelina-website/src/pages/playground.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modelina-website/src/pages/playground.tsx b/modelina-website/src/pages/playground.tsx index b1bd72e6e6..cd326cd75a 100644 --- a/modelina-website/src/pages/playground.tsx +++ b/modelina-website/src/pages/playground.tsx @@ -1,6 +1,4 @@ import Playground from '@/components/playground/Playground'; -import OldPlayground from '@/components/playground/OldPlayground'; -import NewPlayground from '@/components/playground/NewPlayground'; import GenericLayout from '@/components/layouts/GenericLayout'; import { PlaygroundContextProvider } from '@/components/contexts/PlaygroundContext'; @@ -19,8 +17,6 @@ export default function PlaygroundPage() { footerPadding = "mb-0" > - {/* */} - {/* */} From b32d6806adaece9f81b41f58419bd470a7694e2e Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Mon, 4 Dec 2023 12:08:56 +0530 Subject: [PATCH 19/29] removed code smells suggested by sonarcloud --- .../components/contexts/PlaygroundContext.tsx | 76 +++++++++++++------ .../contexts/PlaygroundPanelContext.tsx | 16 ++-- .../src/components/playground/Content.tsx | 12 +-- .../components/playground/GeneratedModels.tsx | 2 +- .../src/components/playground/Navigation.tsx | 2 +- 5 files changed, 71 insertions(+), 37 deletions(-) diff --git a/modelina-website/src/components/contexts/PlaygroundContext.tsx b/modelina-website/src/components/contexts/PlaygroundContext.tsx index 41b4c800fc..5db294383a 100644 --- a/modelina-website/src/components/contexts/PlaygroundContext.tsx +++ b/modelina-website/src/components/contexts/PlaygroundContext.tsx @@ -4,7 +4,8 @@ import React, { useContext, Dispatch, SetStateAction, - useState + useState, + useMemo } from 'react'; import { defaultAsyncapiDocument } from '@/types'; @@ -61,31 +62,56 @@ export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> const [hasLoadedQuery, setHasLoadedQuery] = useState(false); const [renderModels, setRenderModels] = React.useState(null); + const contextValue = useMemo(() => ({ + input, + setInput, + models, + setModels, + generatorCode, + setGeneratorCode, + loaded, + setLoaded, + showGeneratorCode, + setShowGeneratorCode, + error, + setError, + statusCode, + setStatusCode, + errorMessage, + setErrorMessage, + isLoaded, + setIsLoaded, + hasLoadedQuery, + setHasLoadedQuery, + renderModels, + setRenderModels + }), [ + input, + setInput, + models, + setModels, + generatorCode, + setGeneratorCode, + loaded, + setLoaded, + showGeneratorCode, + setShowGeneratorCode, + error, + setError, + statusCode, + setStatusCode, + errorMessage, + setErrorMessage, + isLoaded, + setIsLoaded, + hasLoadedQuery, + setHasLoadedQuery, + renderModels, + setRenderModels, + ]); + return ( - + {children} ); diff --git a/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx b/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx index d59af2e3a7..710a37ec3b 100644 --- a/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx +++ b/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx @@ -4,7 +4,8 @@ import React, { useContext, Dispatch, SetStateAction, - useState + useState, + useMemo } from 'react'; interface PanelContextProps { @@ -21,12 +22,17 @@ export const PanelContextProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { const [panel, setPanel] = useState(''); + + const contextValue = useMemo(() => ({ + panel, + setPanel + }), [ + panel, + setPanel + ]); return ( {children} diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index 40259b2f67..9722f73361 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -1,6 +1,6 @@ 'use client'; -import { FunctionComponent } from 'react'; +import { FunctionComponent, useMemo } from 'react'; import { usePanelContext } from '../contexts/PlaygroundPanelContext'; import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; import { usePlaygroundContext } from '../contexts/PlaygroundContext'; @@ -31,6 +31,11 @@ export const Content: FunctionComponent = ({ config, setNewConfig, } = usePlaygroundContext(); const panelEnabled = panel !== ''; + + const PlaygroundGeneratedContextValue = useMemo(() => ({ + language: config.language, + models: models + }), [config.language, models]); return (
      @@ -75,10 +80,7 @@ export const Content: FunctionComponent = ({ config, setNewConfig, ) : ( diff --git a/modelina-website/src/components/playground/GeneratedModels.tsx b/modelina-website/src/components/playground/GeneratedModels.tsx index f631c1a83d..09f4d814e7 100644 --- a/modelina-website/src/components/playground/GeneratedModels.tsx +++ b/modelina-website/src/components/playground/GeneratedModels.tsx @@ -55,7 +55,7 @@ const GeneratedModelsComponent: React.FC = ({
      { - setNewQuery && setNewQuery('selectedModel', model.name); + setNewQuery?.('selectedModel', model.name); setSelectedModel(model.name); setShowGeneratorCode(false); }} diff --git a/modelina-website/src/components/playground/Navigation.tsx b/modelina-website/src/components/playground/Navigation.tsx index 448533a0d3..4fd9d045a1 100644 --- a/modelina-website/src/components/playground/Navigation.tsx +++ b/modelina-website/src/components/playground/Navigation.tsx @@ -35,7 +35,7 @@ const Output: React.FunctionComponent = () => { const { renderModels, showGeneratorCode, setShowGeneratorCode } = usePlaygroundContext(); return (
      -
      setShowGeneratorCode(true)}>Generator Code
      +
      From 18ba05d1084f79a6a3796028bb78870d7f468eca Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Thu, 7 Dec 2023 17:44:11 +0530 Subject: [PATCH 20/29] re-structured playground layout --- .../components/contexts/PlaygroundContext.tsx | 14 +++ .../contexts/PlaygroundPanelContext.tsx | 43 -------- .../src/components/playground/Content.tsx | 98 +++++++++---------- .../{Navigation.tsx => OptionsNavigation.tsx} | 43 +------- .../playground/OutputNavigation.tsx | 26 +++++ .../src/components/playground/Playground.tsx | 12 ++- .../src/components/playground/Sidebar.tsx | 10 +- 7 files changed, 101 insertions(+), 145 deletions(-) delete mode 100644 modelina-website/src/components/contexts/PlaygroundPanelContext.tsx rename modelina-website/src/components/playground/{Navigation.tsx => OptionsNavigation.tsx} (60%) create mode 100644 modelina-website/src/components/playground/OutputNavigation.tsx diff --git a/modelina-website/src/components/contexts/PlaygroundContext.tsx b/modelina-website/src/components/contexts/PlaygroundContext.tsx index 5db294383a..9d7a333022 100644 --- a/modelina-website/src/components/contexts/PlaygroundContext.tsx +++ b/modelina-website/src/components/contexts/PlaygroundContext.tsx @@ -20,6 +20,10 @@ interface LoadedState { } interface PlaygroundContextProps { + showOptions: boolean; + setShowOptions: Dispatch>; + showOutputNavigation: boolean; + setShowOutputNavigation: Dispatch>; input: string; setInput: Dispatch>; models: ModelsGeneratorProps[]; @@ -47,6 +51,8 @@ interface PlaygroundContextProps { const PlaygroundContext = createContext(undefined); export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { + const [showOptions, setShowOptions] = useState(true); + const [showOutputNavigation, setShowOutputNavigation] = useState(true); const [input, setInput] = useState(JSON.stringify(defaultAsyncapiDocument, null, 4)); const [models, setModels] = useState([]); const [generatorCode, setGeneratorCode] = useState(''); @@ -63,6 +69,10 @@ export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> const [renderModels, setRenderModels] = React.useState(null); const contextValue = useMemo(() => ({ + showOptions, + setShowOptions, + showOutputNavigation, + setShowOutputNavigation, input, setInput, models, @@ -86,6 +96,10 @@ export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> renderModels, setRenderModels }), [ + showOptions, + setShowOptions, + showOutputNavigation, + setShowOutputNavigation, input, setInput, models, diff --git a/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx b/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx deleted file mode 100644 index 710a37ec3b..0000000000 --- a/modelina-website/src/components/contexts/PlaygroundPanelContext.tsx +++ /dev/null @@ -1,43 +0,0 @@ -'use client'; -import React, { - createContext, - useContext, - Dispatch, - SetStateAction, - useState, - useMemo -} from 'react'; - -interface PanelContextProps { - panel: string; - setPanel: Dispatch>; -} - -const PanelContext = createContext({ - panel: '' || 'options' || 'output', - setPanel: (): string => '' -}); - -export const PanelContextProvider: React.FC<{ - children: React.ReactNode; -}> = ({ children }) => { - const [panel, setPanel] = useState(''); - - const contextValue = useMemo(() => ({ - panel, - setPanel - }), [ - panel, - setPanel - ]); - return ( - - {children} - - ); -}; - -export const usePanelContext = (): PanelContextProps => - useContext(PanelContext); diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index 9722f73361..9290fa4fb5 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -1,13 +1,13 @@ 'use client'; import { FunctionComponent, useMemo } from 'react'; -import { usePanelContext } from '../contexts/PlaygroundPanelContext'; import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; import { usePlaygroundContext } from '../contexts/PlaygroundContext'; -import { Navigation } from './Navigation'; -import GeneratedModelsComponent from './GeneratedModels'; import MonacoEditorWrapper from '../MonacoEditorWrapper'; import CustomError from '../CustomError'; +import OutputNavigation from './OutputNavigation'; +import { OptionsNavigation } from './OptionsNavigation'; +import GeneratedModelsComponent from './GeneratedModels'; import { ModelinaOptions } from '@/types'; interface ContentProps { @@ -18,7 +18,6 @@ interface ContentProps { } export const Content: FunctionComponent = ({ config, setNewConfig, setNewQuery, generateNewCode }) => { - const { panel } = usePanelContext(); const { input, setInput, @@ -28,64 +27,61 @@ export const Content: FunctionComponent = ({ config, setNewConfig, error, statusCode, errorMessage, + showOptions, + showOutputNavigation, } = usePlaygroundContext(); - const panelEnabled = panel !== ''; - const PlaygroundGeneratedContextValue = useMemo(() => ({ language: config.language, models: models }), [config.language, models]); + return ( -
      -
      - {panelEnabled ? ( -
      - +
      + {/* OPTIONS & EDITOR */} +
      + { + showOptions &&
      +
      - ) : null} -
      - {/* EDITOR */} -
      -
      -
      - { - setInput(change); - generateNewCode(change); - }} - editorDidMount={() => { - setLoaded({ ...loaded, editorLoaded: true }); - }} - language="json" - /> -
      + } +
      +
      +
      + { + setInput(change); + generateNewCode(change); + }} + editorDidMount={() => { + setLoaded({ ...loaded, editorLoaded: true }); + }} + language="json" + />
      +
      +
      - {/* OUTPUT */} -
      -
      - {error ? ( - - ) : ( - - - - )} -
      + {/* OUTPUT NAVIGATION AND OUTPUTS */} +
      + { + showOutputNavigation &&
      + +
      + } +
      +
      + {error ? ( + + ) : ( + + + + )}
      diff --git a/modelina-website/src/components/playground/Navigation.tsx b/modelina-website/src/components/playground/OptionsNavigation.tsx similarity index 60% rename from modelina-website/src/components/playground/Navigation.tsx rename to modelina-website/src/components/playground/OptionsNavigation.tsx index 4fd9d045a1..51c61b8560 100644 --- a/modelina-website/src/components/playground/Navigation.tsx +++ b/modelina-website/src/components/playground/OptionsNavigation.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { usePanelContext } from "../contexts/PlaygroundPanelContext"; import PlaygroundOptions from './PlaygroundOptions'; import { PlaygroundTypeScriptConfigContext, @@ -18,40 +17,13 @@ import { import { ModelinaOptions, } from '@/types'; -import { usePlaygroundContext } from "../contexts/PlaygroundContext"; -import InfoModal from "../InfoModal"; -interface OptionsProps { +interface OptionsNavigationProps { config: ModelinaOptions; setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; } -interface OutputProps { } -interface NavigationProps { - config: ModelinaOptions; - setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; -} - -const Output: React.FunctionComponent = () => { - const { renderModels, showGeneratorCode, setShowGeneratorCode } = usePlaygroundContext(); - return ( -
      - - -
      - -

      - This list contains all the generated models, select one to show their generated code. -

      -
      -
      Generated Models
      -
      - - {renderModels} -
      - ) -} -const Options: React.FunctionComponent = ({ config, setNewConfig }) => { +export const OptionsNavigation: React.FunctionComponent = ({ config, setNewConfig }) => { return (
      @@ -82,14 +54,3 @@ const Options: React.FunctionComponent = ({ config, setNewConfig }
      ) } - -export const Navigation: React.FunctionComponent = ({ config, setNewConfig }) => { - const { panel } = usePanelContext(); - - return ( -
      - {panel !== 'options' && } - {panel !== 'output' && } -
      - ) -} diff --git a/modelina-website/src/components/playground/OutputNavigation.tsx b/modelina-website/src/components/playground/OutputNavigation.tsx new file mode 100644 index 0000000000..b38fb0fd2a --- /dev/null +++ b/modelina-website/src/components/playground/OutputNavigation.tsx @@ -0,0 +1,26 @@ +import { usePlaygroundContext } from "../contexts/PlaygroundContext"; +import InfoModal from "../InfoModal"; + +interface OutputProps { } + +const OutputNavigation: React.FunctionComponent = () => { + const { renderModels, showGeneratorCode, setShowGeneratorCode } = usePlaygroundContext(); + return ( +
      + + +
      + +

      + This list contains all the generated models, select one to show their generated code. +

      +
      +
      Generated Models
      +
      + + {renderModels} +
      + ) +} + +export default OutputNavigation; \ No newline at end of file diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index bfef18de72..5d93f08afa 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -7,7 +7,6 @@ import { } from '@/types'; import Router, { withRouter, NextRouter } from 'next/router'; import { encode } from 'js-base64'; -import { PanelContextProvider } from '../contexts/PlaygroundPanelContext'; import { usePlaygroundContext } from '../contexts/PlaygroundContext'; import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; @@ -189,6 +188,7 @@ const Playground: React.FC = (props) => { if (query.goPackageName !== undefined) { config.goPackageName = query.goPackageName; } + if (query.kotlinPackageName !== undefined) { config.kotlinPackageName = query.kotlinPackageName; } @@ -300,12 +300,14 @@ const Playground: React.FC = (props) => { Loading Modelina Playground. Rendering playground components...
      : -
      -
      - +
      +
      +
      +
      +
      - +
      } diff --git a/modelina-website/src/components/playground/Sidebar.tsx b/modelina-website/src/components/playground/Sidebar.tsx index a5994bc8d1..97ae52658c 100644 --- a/modelina-website/src/components/playground/Sidebar.tsx +++ b/modelina-website/src/components/playground/Sidebar.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { IoOptionsOutline } from 'react-icons/io5'; import { VscListSelection } from 'react-icons/vsc'; import { Tooltip } from './Tooltip'; -import { usePanelContext } from '../contexts/PlaygroundPanelContext'; +import { usePlaygroundContext } from '../contexts/PlaygroundContext'; interface SidebarItem { name: string; @@ -16,7 +16,7 @@ interface SidebarItem { interface SidebarProps {} export const Sidebar: React.FunctionComponent = () => { - const { panel, setPanel } = usePanelContext(); + const { setShowOptions, setShowOutputNavigation } = usePlaygroundContext(); const sidebarItems: SidebarItem[] = [ // Options { @@ -24,7 +24,7 @@ export const Sidebar: React.FunctionComponent = () => { title: 'Options', isActive: false, onClick: () => { - setPanel(panel !== 'options' ? 'options' : ''); + setShowOptions((prevShowOptions) => !prevShowOptions); }, icon: , tooltip: 'Option' @@ -35,7 +35,7 @@ export const Sidebar: React.FunctionComponent = () => { title: 'Output', isActive: false, onClick: () => { - setPanel(panel !== 'output' ? 'output' : ''); + setShowOutputNavigation((prevShowOutputNavigation) => !prevShowOutputNavigation); }, icon: , tooltip: 'Output' @@ -43,7 +43,7 @@ export const Sidebar: React.FunctionComponent = () => { ]; return ( -
      +
      {sidebarItems.map((item) => ( Date: Thu, 7 Dec 2023 18:47:55 +0530 Subject: [PATCH 21/29] rectified option bugs --- modelina-website/src/components/playground/Playground.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 5d93f08afa..b78bee8ab0 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -199,10 +199,10 @@ const Playground: React.FC = (props) => { } }, [props.router.isReady, hasLoadedQuery]); - const setNewConfig = (config: string, configValue: any, updateCode?: boolean) => { - setNewQuery(config, configValue); + const setNewConfig = (configName: string, configValue: any, updateCode?: boolean) => { + setNewQuery(configName, configValue); /* eslint-disable-next-line security/detect-object-injection */ - (config as any)[config] = configValue; + (config as any)[configName] = configValue; if (updateCode === true || updateCode === undefined) { generateNewCode(input); } From d9595c186c7741ad0bbeb56c2f00052f5c0e642e Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Thu, 7 Dec 2023 22:58:06 +0530 Subject: [PATCH 22/29] rectified info-modal bug --- modelina-website/src/components/InfoModal.tsx | 14 ++--- .../playground/options/GeneralOptions.tsx | 56 +++++++++---------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/modelina-website/src/components/InfoModal.tsx b/modelina-website/src/components/InfoModal.tsx index 8564c3a5da..c2ac027096 100644 --- a/modelina-website/src/components/InfoModal.tsx +++ b/modelina-website/src/components/InfoModal.tsx @@ -5,7 +5,7 @@ interface InfoModalProps { children: React.ReactNode; } -export default function InfoModal(props: InfoModalProps){ +export default function InfoModal(props: InfoModalProps) { const [showModal, setShowModal] = useState(false); @@ -21,21 +21,21 @@ export default function InfoModal(props: InfoModalProps){ const MyModal = () => { return ( - <> -
      -
      + <> +
      +

      {props.text}

      {props.children} -
      +
      ) } - return( + return ( <> - {showModal && } + {showModal && } ) diff --git a/modelina-website/src/components/playground/options/GeneralOptions.tsx b/modelina-website/src/components/playground/options/GeneralOptions.tsx index 125db7eea6..00c77f3ac6 100644 --- a/modelina-website/src/components/playground/options/GeneralOptions.tsx +++ b/modelina-website/src/components/playground/options/GeneralOptions.tsx @@ -8,7 +8,7 @@ import InfoModal from '@/components/InfoModal'; interface WithRouterProps { setNewConfig?: (queryKey: string, queryValue: string) => void; } -interface GeneralOptionsState {} +interface GeneralOptionsState { } export const defaultState: GeneralOptionsState = {}; @@ -66,7 +66,7 @@ class GeneralOptions extends React.Component< } } - + render() { @@ -101,7 +101,7 @@ class GeneralOptions extends React.Component<

      In code generation, a common task is to map the data types from the input model to the output. In Modelina you can do this through type mapping. -

      +

      This option includes a simple example type mapping, that maps integers to a custom type.

      @@ -122,7 +122,7 @@ class GeneralOptions extends React.Component<
    • - The indentation type option allows you to choose between using tabs or spaces for indentation in the generated code. + The indentation type option allows you to choose between using tabs or spaces for indentation in the generated code.

    • - This option allows you to customize the naming style for model names. There are no limitations to how you can format it, but for this simple example it provides the following options: -

      + This option allows you to customize the naming style for model names. There are no limitations to how you can format it, but for this simple example it provides the following options: +

      Default: This option refers to the default naming format for models, which may vary depending on the programming language or coding convention being used. -

      +

      Snake case: Model names are written in lowercase letters, and words are separated by underscores. (e.g: model_name) -

      +

      Pascal case: Model names start with an uppercase letter, and subsequent words are also capitalized. (e.g: ModelName) -

      +

      Camel case: Model names start with a lowercase letter, and subsequent words are capitalized. (e.g: modelName) -

      +

      Param case: Model names use hyphens to separate words, and all letters are in lowercase. (e.g: model-name) -

      +

      Constant case: Model names are written in uppercase letters, and words are separated by underscores. (e.g: MODEL_NAME)

      @@ -212,7 +212,7 @@ class GeneralOptions extends React.Component< { value: 'param_case', text: 'Param Case' }, { value: 'constant_case', text: 'Constant Case' } ]} - + value={this.context?.modelNamingFormat} onChange={this.onChangeModelNamingFormat} className="shadow-outline-blue cursor-pointer" @@ -223,18 +223,18 @@ class GeneralOptions extends React.Component<
    • - This option allows you to customize the naming style for enum keys. There are no limitations to how you can format it, but for this simple example it provides the following options: -

      + This option allows you to customize the naming style for enum keys. There are no limitations to how you can format it, but for this simple example it provides the following options: +

      Default: This option refers to the default naming format for enum keys, which may vary depending on the programming language or coding convention being used. -

      +

      Snake case: Enum key names are written in lowercase letters, and words are separated by underscores. (e.g: enum_key) -

      +

      Pascal case: Enum key names start with an uppercase letter, and subsequent words are also capitalized. (e.g: EnumKey) -

      +

      Camel case: Enum key names start with a lowercase letter, and subsequent words are capitalized. (e.g: enumKey) -

      +

      Param case: Enum key names use hyphens to separate words, and all letters are in lowercase. (e.g: enum-key) -

      +

      Constant case: Enum key names are written in uppercase letters, and words are separated by underscores. (e.g: ENUM_KEY)

      @@ -251,7 +251,7 @@ class GeneralOptions extends React.Component< { value: 'param_case', text: 'Param Case' }, { value: 'constant_case', text: 'Constant Case' } ]} - + value={this.context?.enumKeyNamingFormat} onChange={this.onChangeEnumKeyNamingFormat} className="shadow-outline-blue cursor-pointer" From 2e2219bbcd13fc7c0c3c8cdff18f58dee9b8566e Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Fri, 8 Dec 2023 23:40:22 +0530 Subject: [PATCH 23/29] rectified bug: option change was not visible --- .../components/contexts/PlaygroundContext.tsx | 47 ++++++- .../src/components/playground/Content.tsx | 10 +- .../playground/OptionsNavigation.tsx | 5 +- .../src/components/playground/Playground.tsx | 110 +++++---------- .../playground/PlaygroundOptions.tsx | 127 ++++++++---------- .../options/CSharpGeneratorOptions.tsx | 2 +- .../options/CplusplusGeneratorOptions.tsx | 2 +- .../options/DartGeneratorOptions.tsx | 2 +- .../playground/options/GoGeneratorOptions.tsx | 2 +- .../options/JavaGeneratorOptions.tsx | 2 +- .../options/JavaScriptGeneratorOptions.tsx | 2 +- .../options/KotlinGeneratorOptions.tsx | 2 +- .../options/PhpGeneratorOptions.tsx | 2 +- .../options/PythonGeneratorOptions.tsx | 2 +- .../options/RustGeneratorOptions.tsx | 2 +- 15 files changed, 160 insertions(+), 159 deletions(-) diff --git a/modelina-website/src/components/contexts/PlaygroundContext.tsx b/modelina-website/src/components/contexts/PlaygroundContext.tsx index 9d7a333022..435f98bb3f 100644 --- a/modelina-website/src/components/contexts/PlaygroundContext.tsx +++ b/modelina-website/src/components/contexts/PlaygroundContext.tsx @@ -7,7 +7,7 @@ import React, { useState, useMemo } from 'react'; -import { defaultAsyncapiDocument } from '@/types'; +import { defaultAsyncapiDocument, ModelinaOptions } from '@/types'; interface ModelsGeneratorProps { code: string; @@ -24,6 +24,8 @@ interface PlaygroundContextProps { setShowOptions: Dispatch>; showOutputNavigation: boolean; setShowOutputNavigation: Dispatch>; + config: ModelinaOptions; + setConfig: Dispatch>; input: string; setInput: Dispatch>; models: ModelsGeneratorProps[]; @@ -51,8 +53,47 @@ interface PlaygroundContextProps { const PlaygroundContext = createContext(undefined); export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { + const defaultConfig: ModelinaOptions = { + language: 'typescript', + propertyNamingFormat: 'default', + modelNamingFormat: 'default', + enumKeyNamingFormat: 'default', + indentationType: 'spaces', + showTypeMappingExample: false, + tsMarshalling: false, + tsModelType: 'class', + tsEnumType: 'enum', + tsModuleSystem: 'CJS', + tsIncludeDescriptions: false, + tsIncludeExampleFunction: false, + tsIncludeJsonBinPack: false, + csharpArrayType: 'Array', + csharpAutoImplemented: false, + csharpOverwriteHashcode: false, + csharpIncludeJson: false, + csharpOverwriteEqual: false, + csharpIncludeNewtonsoft: false, + csharpNamespace: 'asyncapi.models', + csharpNullable: false, + phpIncludeDescriptions: false, + phpNamespace: 'AsyncAPI/Models', + cplusplusNamespace: 'AsyncapiModels', + javaPackageName: 'asyncapi.models', + javaIncludeJackson: false, + javaIncludeMarshaling: false, + javaArrayType: 'Array', + javaOverwriteHashcode: false, + javaOverwriteEqual: false, + javaOverwriteToString: false, + javaJavaDocs: false, + javaJavaxAnnotation: false, + goPackageName: 'asyncapi.models', + kotlinPackageName: 'asyncapi.models' + }; + const [showOptions, setShowOptions] = useState(true); const [showOutputNavigation, setShowOutputNavigation] = useState(true); + const [config, setConfig] = useState(defaultConfig); const [input, setInput] = useState(JSON.stringify(defaultAsyncapiDocument, null, 4)); const [models, setModels] = useState([]); const [generatorCode, setGeneratorCode] = useState(''); @@ -73,6 +114,8 @@ export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> setShowOptions, showOutputNavigation, setShowOutputNavigation, + config, + setConfig, input, setInput, models, @@ -100,6 +143,8 @@ export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> setShowOptions, showOutputNavigation, setShowOutputNavigation, + config, + setConfig, input, setInput, models, diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index 9290fa4fb5..f3e6c3ef14 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -11,14 +11,14 @@ import GeneratedModelsComponent from './GeneratedModels'; import { ModelinaOptions } from '@/types'; interface ContentProps { - config: ModelinaOptions; setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; setNewQuery: (queryKey: string, queryValue: any) => void; generateNewCode: (input: string) => void; } -export const Content: FunctionComponent = ({ config, setNewConfig, setNewQuery, generateNewCode }) => { +export const Content: FunctionComponent = ({ setNewConfig, setNewQuery, generateNewCode }) => { const { + config, input, setInput, models, @@ -41,8 +41,8 @@ export const Content: FunctionComponent = ({ config, setNewConfig, {/* OPTIONS & EDITOR */}
      { - showOptions &&
      - + showOptions &&
      +
      }
      @@ -67,7 +67,7 @@ export const Content: FunctionComponent = ({ config, setNewConfig, {/* OUTPUT NAVIGATION AND OUTPUTS */}
      { - showOutputNavigation &&
      + showOutputNavigation &&
      } diff --git a/modelina-website/src/components/playground/OptionsNavigation.tsx b/modelina-website/src/components/playground/OptionsNavigation.tsx index 51c61b8560..5cebca1a78 100644 --- a/modelina-website/src/components/playground/OptionsNavigation.tsx +++ b/modelina-website/src/components/playground/OptionsNavigation.tsx @@ -17,13 +17,14 @@ import { import { ModelinaOptions, } from '@/types'; +import { usePlaygroundContext } from "../contexts/PlaygroundContext"; interface OptionsNavigationProps { - config: ModelinaOptions; setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; } -export const OptionsNavigation: React.FunctionComponent = ({ config, setNewConfig }) => { +export const OptionsNavigation: React.FunctionComponent = ({ setNewConfig }) => { + const { config } = usePlaygroundContext(); return (
      diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index b78bee8ab0..bd59427122 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -31,6 +31,8 @@ interface ModelinaPlaygroundProps extends WithRouterProps { const Playground: React.FC = (props) => { const { + config, + setConfig, input, setModels, setGeneratorCode, @@ -45,44 +47,6 @@ const Playground: React.FC = (props) => { setHasLoadedQuery, } = usePlaygroundContext(); - const config: ModelinaOptions = { - language: 'typescript', - propertyNamingFormat: 'default', - modelNamingFormat: 'default', - enumKeyNamingFormat: 'default', - indentationType: 'spaces', - showTypeMappingExample: false, - tsMarshalling: false, - tsModelType: 'class', - tsEnumType: 'enum', - tsModuleSystem: 'CJS', - tsIncludeDescriptions: false, - tsIncludeExampleFunction: false, - tsIncludeJsonBinPack: false, - csharpArrayType: 'Array', - csharpAutoImplemented: false, - csharpOverwriteHashcode: false, - csharpIncludeJson: false, - csharpOverwriteEqual: false, - csharpIncludeNewtonsoft: false, - csharpNamespace: 'asyncapi.models', - csharpNullable: false, - phpIncludeDescriptions: false, - phpNamespace: 'AsyncAPI/Models', - cplusplusNamespace: 'AsyncapiModels', - javaPackageName: 'asyncapi.models', - javaIncludeJackson: false, - javaIncludeMarshaling: false, - javaArrayType: 'Array', - javaOverwriteHashcode: false, - javaOverwriteEqual: false, - javaOverwriteToString: false, - javaJavaDocs: false, - javaJavaxAnnotation: false, - goPackageName: 'asyncapi.models', - kotlinPackageName: 'asyncapi.models' - }; - useEffect(() => { const isHardLoaded = loaded.hasReceivedCode; const isSoftLoaded = loaded.editorLoaded; @@ -90,107 +54,107 @@ const Playground: React.FC = (props) => { const query = props.router.query as ModelinaQueryOptions; if (query.language !== undefined) { - config.language = query.language as any; + setConfig({ ...config, language: query.language as any }); } if (query.enumKeyNamingFormat !== undefined) { - config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; + setConfig({ ...config, enumKeyNamingFormat: query.enumKeyNamingFormat as any }); } if (query.propertyNamingFormat !== undefined) { - config.propertyNamingFormat = query.propertyNamingFormat as any; + setConfig({ ...config, propertyNamingFormat: query.propertyNamingFormat as any }); } if (query.modelNamingFormat !== undefined) { - config.modelNamingFormat = query.modelNamingFormat as any; + setConfig({ ...config, modelNamingFormat: query.modelNamingFormat as any }); } if (query.showTypeMappingExample !== undefined) { - config.showTypeMappingExample = query.showTypeMappingExample === 'true'; + setConfig({ ...config, showTypeMappingExample: query.showTypeMappingExample === 'true' }); } if (query.indentationType !== undefined) { - config.indentationType = query.indentationType as any; + setConfig({ ...config, indentationType: query.indentationType as any }); } if (query.tsMarshalling !== undefined) { - config.tsMarshalling = query.tsMarshalling === 'true'; + setConfig({ ...config, tsMarshalling: query.tsMarshalling === 'true' }); } if (query.tsModelType !== undefined) { - config.tsModelType = query.tsModelType as any; + setConfig({ ...config, tsModelType: query.tsModelType as any }); } if (query.tsEnumType !== undefined) { - config.tsEnumType = query.tsEnumType as any; + setConfig({ ...config, tsEnumType: query.tsEnumType as any }); } if (query.tsIncludeDescriptions !== undefined) { - config.tsIncludeDescriptions = query.tsIncludeDescriptions === 'true'; + setConfig({ ...config, tsIncludeDescriptions: query.tsIncludeDescriptions === 'true' }); } if (query.tsIncludeJsonBinPack !== undefined) { - config.tsIncludeJsonBinPack = query.tsIncludeJsonBinPack === 'true'; + setConfig({ ...config, tsIncludeJsonBinPack: query.tsIncludeJsonBinPack === 'true' }); } if (query.tsIncludeExampleFunction !== undefined) { - config.tsIncludeExampleFunction = query.tsIncludeExampleFunction === 'true'; + setConfig({ ...config, tsIncludeExampleFunction: query.tsIncludeExampleFunction === 'true' }); } if (query.csharpArrayType !== undefined) { - config.csharpArrayType = query.csharpArrayType as any; + setConfig({ ...config, csharpArrayType: query.csharpArrayType as any }); } if (query.csharpAutoImplemented !== undefined) { - config.csharpAutoImplemented = query.csharpAutoImplemented === 'true'; + setConfig({ ...config, csharpAutoImplemented: query.csharpAutoImplemented === 'true' }); } if (query.csharpOverwriteHashcode !== undefined) { - config.csharpOverwriteHashcode = query.csharpOverwriteHashcode === 'true'; + setConfig({ ...config, csharpOverwriteHashcode: query.csharpOverwriteHashcode === 'true' }); } if (query.phpIncludeDescriptions !== undefined) { - config.phpIncludeDescriptions = query.phpIncludeDescriptions === 'true'; + setConfig({ ...config, phpIncludeDescriptions: query.phpIncludeDescriptions === 'true' }); } if (query.phpNamespace !== undefined) { - config.phpNamespace = query.phpNamespace; + setConfig({ ...config, phpNamespace: query.phpNamespace }); } if (query.csharpIncludeJson !== undefined) { - config.csharpIncludeJson = query.csharpIncludeJson === 'true'; + setConfig({ ...config, csharpIncludeJson: query.csharpIncludeJson === 'true' }); } if (query.csharpOverwriteEqual !== undefined) { - config.csharpOverwriteEqual = query.csharpOverwriteEqual === 'true'; + setConfig({ ...config, csharpOverwriteEqual: query.csharpOverwriteEqual === 'true' }); } if (query.csharpIncludeNewtonsoft !== undefined) { - config.csharpIncludeNewtonsoft = query.csharpIncludeNewtonsoft === 'true'; + setConfig({ ...config, csharpIncludeNewtonsoft: query.csharpIncludeNewtonsoft === 'true' }); } if (query.csharpNamespace !== undefined) { - config.csharpNamespace = query.csharpNamespace; + setConfig({ ...config, csharpNamespace: query.csharpNamespace }); } if (query.csharpNullable !== undefined) { - config.csharpNullable = query.csharpNullable === 'true'; + setConfig({ ...config, csharpNullable: query.csharpNullable === 'true' }); } if (query.cplusplusNamespace !== undefined) { - config.cplusplusNamespace = query.cplusplusNamespace; + setConfig({ ...config, cplusplusNamespace: query.cplusplusNamespace }); } if (query.javaPackageName !== undefined) { - config.javaPackageName = query.javaPackageName; + setConfig({ ...config, javaPackageName: query.javaPackageName }); } if (query.javaIncludeJackson !== undefined) { - config.javaIncludeJackson = query.javaIncludeJackson === 'true'; + setConfig({ ...config, javaIncludeJackson: query.javaIncludeJackson === 'true' }); } if (query.javaIncludeMarshaling !== undefined) { - config.javaIncludeMarshaling = query.javaIncludeMarshaling === 'true'; + setConfig({ ...config, javaIncludeMarshaling: query.javaIncludeMarshaling === 'true' }); } if (query.javaArrayType !== undefined) { - config.javaArrayType = query.javaArrayType as any; + setConfig({ ...config, javaArrayType: query.javaArrayType as any }); } if (query.javaOverwriteHashcode !== undefined) { - config.javaOverwriteHashcode = query.javaOverwriteHashcode === 'true'; + setConfig({ ...config, javaOverwriteHashcode: query.javaOverwriteHashcode === 'true' }); } if (query.javaOverwriteEqual !== undefined) { - config.javaOverwriteEqual = query.javaOverwriteEqual === 'true'; + setConfig({ ...config, javaOverwriteEqual: query.javaOverwriteEqual === 'true' }); } if (query.javaOverwriteToString !== undefined) { - config.javaOverwriteToString = query.javaOverwriteToString === 'true'; + setConfig({ ...config, javaOverwriteToString: query.javaOverwriteToString === 'true' }); } if (query.javaJavaDocs !== undefined) { - config.javaJavaDocs = query.javaJavaDocs === 'true'; + setConfig({ ...config, javaJavaDocs: query.javaJavaDocs === 'true' }); } if (query.javaJavaxAnnotation !== undefined) { - config.javaJavaxAnnotation = query.javaJavaxAnnotation === 'true'; + setConfig({ ...config, javaJavaxAnnotation: query.javaJavaxAnnotation === 'true' }); } if (query.goPackageName !== undefined) { - config.goPackageName = query.goPackageName; + setConfig({ ...config, goPackageName: query.goPackageName }); } if (query.kotlinPackageName !== undefined) { - config.kotlinPackageName = query.kotlinPackageName; + setConfig({ ...config, kotlinPackageName: query.kotlinPackageName }); } if (props.router.isReady && !hasLoadedQuery) { @@ -306,7 +270,7 @@ const Playground: React.FC = (props) => {
      - +
      diff --git a/modelina-website/src/components/playground/PlaygroundOptions.tsx b/modelina-website/src/components/playground/PlaygroundOptions.tsx index c1ec6e98c0..c0149d6a02 100644 --- a/modelina-website/src/components/playground/PlaygroundOptions.tsx +++ b/modelina-website/src/components/playground/PlaygroundOptions.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useContext, useEffect } from 'react'; import TypeScriptGeneratorOptions from './options/TypeScriptGeneratorOptions'; import GeneralOptions from './options/GeneralOptions'; import JavaScriptGeneratorOptions from './options/JavaScriptGeneratorOptions'; @@ -13,77 +13,68 @@ import CplusplusGeneratorOptions from './options/CplusplusGeneratorOptions'; import PhpGeneratorOptions from './options/PhpGeneratorOptions'; import { PlaygroundGeneralConfigContext } from '../contexts/PlaygroundConfigContext'; -interface WithRouterProps { +interface PlaygroundOptionsProps { setNewConfig?: (queryKey: string, queryValue: string) => void; } -interface PlaygroundOptionsState {} -export const defaultState: PlaygroundOptionsState = {}; +const PlaygroundOptions: React.FC = ({ setNewConfig }) => { + const context = useContext(PlaygroundGeneralConfigContext); -class PlaygroundOptions extends React.Component< - WithRouterProps, - PlaygroundOptionsState -> { - static contextType = PlaygroundGeneralConfigContext; - declare context: React.ContextType; - constructor(props: any) { - super(props); - this.state = defaultState; - } - - render() { - let generatorOptions; - if (this.context?.language === 'typescript') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'javascript') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'csharp') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'dart') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'go') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'cplusplus') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'java') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'kotlin') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'rust') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'python') { - generatorOptions = ( - - ); - } else if (this.context?.language === 'php') { - generatorOptions = ( - - ); + let generatorOptions; + const handleLanguageChange = () => { + switch (context?.language) { + case 'typescript': + generatorOptions = ; + break; + case 'javascript': + generatorOptions = ; + break; + case 'csharp': + generatorOptions = ; + break; + case 'dart': + generatorOptions = ; + break; + case 'go': + generatorOptions = ; + break; + case 'cplusplus': + generatorOptions = ; + break; + case 'java': + generatorOptions = ; + break; + case 'kotlin': + generatorOptions = ; + break; + case 'rust': + generatorOptions = ; + break; + case 'python': + generatorOptions = ; + break; + case 'php': + generatorOptions = ; + break; + default: + generatorOptions = null; + break; } - return ( -
      - - {generatorOptions} -
      - ); } -} + + handleLanguageChange(); + + useEffect(() => { + handleLanguageChange(); + console.log(context?.language); + }, [context?.language]); + + return ( +
      + + {generatorOptions} +
      + ); +}; + export default PlaygroundOptions; diff --git a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx index eec5f32676..39a1ba9331 100644 --- a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx @@ -95,7 +95,7 @@ class CSharpGeneratorOptions extends React.Component< render() { return (
        -

        +

        CSharp Specific options

      • diff --git a/modelina-website/src/components/playground/options/CplusplusGeneratorOptions.tsx b/modelina-website/src/components/playground/options/CplusplusGeneratorOptions.tsx index dd9b946691..dc6688cbb9 100644 --- a/modelina-website/src/components/playground/options/CplusplusGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/CplusplusGeneratorOptions.tsx @@ -43,7 +43,7 @@ class CplusplusGeneratorOptions extends React.Component< render() { return (
          -

          +

          C++ Specific options

        • diff --git a/modelina-website/src/components/playground/options/DartGeneratorOptions.tsx b/modelina-website/src/components/playground/options/DartGeneratorOptions.tsx index 95c51924ab..fffa0e0eba 100644 --- a/modelina-website/src/components/playground/options/DartGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/DartGeneratorOptions.tsx @@ -22,7 +22,7 @@ class DartGeneratorOptions extends React.Component< render() { return (
            -

            +

            Dart Specific options

            diff --git a/modelina-website/src/components/playground/options/GoGeneratorOptions.tsx b/modelina-website/src/components/playground/options/GoGeneratorOptions.tsx index 1c17005f2b..c9b705fa94 100644 --- a/modelina-website/src/components/playground/options/GoGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/GoGeneratorOptions.tsx @@ -43,7 +43,7 @@ class GoGeneratorOptions extends React.Component< render() { return (
              -

              +

              Go Specific options

            • diff --git a/modelina-website/src/components/playground/options/JavaGeneratorOptions.tsx b/modelina-website/src/components/playground/options/JavaGeneratorOptions.tsx index 7282091627..8519d3bdb3 100644 --- a/modelina-website/src/components/playground/options/JavaGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/JavaGeneratorOptions.tsx @@ -99,7 +99,7 @@ class JavaGeneratorOptions extends React.Component< render() { return (
                -

                +

                Java Specific options

              • diff --git a/modelina-website/src/components/playground/options/JavaScriptGeneratorOptions.tsx b/modelina-website/src/components/playground/options/JavaScriptGeneratorOptions.tsx index 269e288c5d..45daa02d8a 100644 --- a/modelina-website/src/components/playground/options/JavaScriptGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/JavaScriptGeneratorOptions.tsx @@ -23,7 +23,7 @@ class JavaScriptGeneratorOptions extends React.Component< render() { return (
                  -

                  +

                  JavaScript Specific options

                  diff --git a/modelina-website/src/components/playground/options/KotlinGeneratorOptions.tsx b/modelina-website/src/components/playground/options/KotlinGeneratorOptions.tsx index cb52bbac31..156ef26fec 100644 --- a/modelina-website/src/components/playground/options/KotlinGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/KotlinGeneratorOptions.tsx @@ -42,7 +42,7 @@ class KotlinGeneratorOptions extends React.Component< render() { return (
                    -

                    +

                    Kotlin Specific options

                  • diff --git a/modelina-website/src/components/playground/options/PhpGeneratorOptions.tsx b/modelina-website/src/components/playground/options/PhpGeneratorOptions.tsx index b38ddec81a..9e1477d00b 100644 --- a/modelina-website/src/components/playground/options/PhpGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/PhpGeneratorOptions.tsx @@ -50,7 +50,7 @@ class PhpGeneratorOptions extends React.Component< render() { return (
                      -

                      +

                      PHP Specific options

                    • diff --git a/modelina-website/src/components/playground/options/PythonGeneratorOptions.tsx b/modelina-website/src/components/playground/options/PythonGeneratorOptions.tsx index 680adf0313..6078ea5979 100644 --- a/modelina-website/src/components/playground/options/PythonGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/PythonGeneratorOptions.tsx @@ -23,7 +23,7 @@ class PythonGeneratorOptions extends React.Component< render() { return (
                        -

                        +

                        Python Specific options

                        diff --git a/modelina-website/src/components/playground/options/RustGeneratorOptions.tsx b/modelina-website/src/components/playground/options/RustGeneratorOptions.tsx index 87d21a45c7..ac441c27fb 100644 --- a/modelina-website/src/components/playground/options/RustGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/RustGeneratorOptions.tsx @@ -23,7 +23,7 @@ class RustGeneratorOptions extends React.Component< render() { return (
                          -

                          +

                          Rust Specific options

                          From e5185b1ee884a624df5fe3138c4380ceb9a1b539 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Fri, 8 Dec 2023 23:47:45 +0530 Subject: [PATCH 24/29] removed sonarcloud code smells --- modelina-website/src/components/playground/Content.tsx | 1 - .../src/components/playground/OptionsNavigation.tsx | 5 +---- modelina-website/src/components/playground/Playground.tsx | 7 +++---- .../src/components/playground/PlaygroundOptions.tsx | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/modelina-website/src/components/playground/Content.tsx b/modelina-website/src/components/playground/Content.tsx index f3e6c3ef14..9021476ca7 100644 --- a/modelina-website/src/components/playground/Content.tsx +++ b/modelina-website/src/components/playground/Content.tsx @@ -8,7 +8,6 @@ import CustomError from '../CustomError'; import OutputNavigation from './OutputNavigation'; import { OptionsNavigation } from './OptionsNavigation'; import GeneratedModelsComponent from './GeneratedModels'; -import { ModelinaOptions } from '@/types'; interface ContentProps { setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; diff --git a/modelina-website/src/components/playground/OptionsNavigation.tsx b/modelina-website/src/components/playground/OptionsNavigation.tsx index 5cebca1a78..e5bcaef587 100644 --- a/modelina-website/src/components/playground/OptionsNavigation.tsx +++ b/modelina-website/src/components/playground/OptionsNavigation.tsx @@ -1,5 +1,4 @@ import React from "react"; -import PlaygroundOptions from './PlaygroundOptions'; import { PlaygroundTypeScriptConfigContext, PlaygroundCSharpConfigContext, @@ -14,10 +13,8 @@ import { PlaygroundGeneralConfigContext, PlaygroundPhpConfigContext } from '../contexts/PlaygroundConfigContext'; -import { - ModelinaOptions, -} from '@/types'; import { usePlaygroundContext } from "../contexts/PlaygroundContext"; +import PlaygroundOptions from './PlaygroundOptions'; interface OptionsNavigationProps { setNewConfig: (config: string, configValue: any, updateCode?: boolean) => void; diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index bd59427122..b657e632c3 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -1,13 +1,11 @@ import React, { useEffect } from 'react'; +import Router, { withRouter, NextRouter } from 'next/router'; +import { encode } from 'js-base64'; import { - ModelinaOptions, ModelinaQueryOptions, GenerateMessage, UpdateMessage } from '@/types'; -import Router, { withRouter, NextRouter } from 'next/router'; -import { encode } from 'js-base64'; -import { usePlaygroundContext } from '../contexts/PlaygroundContext'; import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; import { getJavaGeneratorCode } from '@/helpers/GeneratorCode/JavaGenerator'; @@ -19,6 +17,7 @@ import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; +import { usePlaygroundContext } from '../contexts/PlaygroundContext'; import { Sidebar } from './Sidebar'; import { Content } from './Content'; diff --git a/modelina-website/src/components/playground/PlaygroundOptions.tsx b/modelina-website/src/components/playground/PlaygroundOptions.tsx index c0149d6a02..cda13164c4 100644 --- a/modelina-website/src/components/playground/PlaygroundOptions.tsx +++ b/modelina-website/src/components/playground/PlaygroundOptions.tsx @@ -1,4 +1,5 @@ import React, { useContext, useEffect } from 'react'; +import { PlaygroundGeneralConfigContext } from '../contexts/PlaygroundConfigContext'; import TypeScriptGeneratorOptions from './options/TypeScriptGeneratorOptions'; import GeneralOptions from './options/GeneralOptions'; import JavaScriptGeneratorOptions from './options/JavaScriptGeneratorOptions'; @@ -11,7 +12,6 @@ import RustGeneratorOptions from './options/RustGeneratorOptions'; import PythonGeneratorOptions from './options/PythonGeneratorOptions'; import CplusplusGeneratorOptions from './options/CplusplusGeneratorOptions'; import PhpGeneratorOptions from './options/PhpGeneratorOptions'; -import { PlaygroundGeneralConfigContext } from '../contexts/PlaygroundConfigContext'; interface PlaygroundOptionsProps { setNewConfig?: (queryKey: string, queryValue: string) => void; From 6562394cccc165fa9f6f7717ecd9fcac66998915 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Sat, 9 Dec 2023 07:04:38 +0530 Subject: [PATCH 25/29] Added Seprate Display for mobile visitors to playground --- modelina-website/src/pages/playground.tsx | 28 ++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/modelina-website/src/pages/playground.tsx b/modelina-website/src/pages/playground.tsx index cd326cd75a..3c24143854 100644 --- a/modelina-website/src/pages/playground.tsx +++ b/modelina-website/src/pages/playground.tsx @@ -1,11 +1,26 @@ +"use client" +import { useEffect, useState } from 'react'; import Playground from '@/components/playground/Playground'; import GenericLayout from '@/components/layouts/GenericLayout'; import { PlaygroundContextProvider } from '@/components/contexts/PlaygroundContext'; export default function PlaygroundPage() { + const [width, setWidth] = useState(window.innerWidth); const description = 'Try out Modelina and see a fraction of what it can do.'; const image = '/img/social/modelina-card.jpg'; + useEffect(() => { + const handleResize = () => { + setWidth(window.innerWidth); + } + + window.addEventListener('resize', handleResize); + + return () => { + window.removeEventListener('resize', handleResize); + } + }, []); + return ( - - - + { + width > 768 ? + + + + : +
                          + Please revisit from the desktop to use the Modelina Playground. +
                          + }
                          ); } From 8b51fb092acfe950fce6c36c5ede4ba281c21a71 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Sat, 9 Dec 2023 07:55:25 +0530 Subject: [PATCH 26/29] removed bugs --- modelina-website/src/components/CodeBlock.tsx | 2 +- .../src/components/playground/Playground.tsx | 13 ++++++- .../playground/PlaygroundOptions.tsx | 35 ++++++++++--------- modelina-website/src/pages/playground.tsx | 21 +++++++---- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/modelina-website/src/components/CodeBlock.tsx b/modelina-website/src/components/CodeBlock.tsx index a1c3f63734..d834579b03 100644 --- a/modelina-website/src/components/CodeBlock.tsx +++ b/modelina-website/src/components/CodeBlock.tsx @@ -224,7 +224,7 @@ export default function CodeBlock({ className: 'pl-2 float-left left-0 sticky bg-code-editor-dark', style: {} }} - lineNumberProps={(lineNumber: any) => { + linenumberprops={(lineNumber: any) => { const isHighlighted = highlightedLines?.includes(lineNumber) || false; return { className: `${ diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index b657e632c3..87d841745c 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import Router, { withRouter, NextRouter } from 'next/router'; import { encode } from 'js-base64'; import { @@ -46,6 +46,13 @@ const Playground: React.FC = (props) => { setHasLoadedQuery, } = usePlaygroundContext(); + // To avoid hydration error + const [isMounted, setIsMounted] = useState(false); + + useEffect(() => { + setIsMounted(true); + }, []); + useEffect(() => { const isHardLoaded = loaded.hasReceivedCode; const isSoftLoaded = loaded.editorLoaded; @@ -254,6 +261,10 @@ const Playground: React.FC = (props) => { } }; + if (!isMounted) { + return null; + } + return (
                          { diff --git a/modelina-website/src/components/playground/PlaygroundOptions.tsx b/modelina-website/src/components/playground/PlaygroundOptions.tsx index cda13164c4..68ca5dcb8e 100644 --- a/modelina-website/src/components/playground/PlaygroundOptions.tsx +++ b/modelina-website/src/components/playground/PlaygroundOptions.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { PlaygroundGeneralConfigContext } from '../contexts/PlaygroundConfigContext'; import TypeScriptGeneratorOptions from './options/TypeScriptGeneratorOptions'; import GeneralOptions from './options/GeneralOptions'; @@ -19,55 +19,56 @@ interface PlaygroundOptionsProps { const PlaygroundOptions: React.FC = ({ setNewConfig }) => { const context = useContext(PlaygroundGeneralConfigContext); + const [generatorOptions, setGeneratorOptions] = useState(null); - let generatorOptions; const handleLanguageChange = () => { switch (context?.language) { case 'typescript': - generatorOptions = ; + setGeneratorOptions(prevOptions => ); break; case 'javascript': - generatorOptions = ; + setGeneratorOptions(); break; case 'csharp': - generatorOptions = ; + setGeneratorOptions(); break; case 'dart': - generatorOptions = ; + setGeneratorOptions(); break; case 'go': - generatorOptions = ; + setGeneratorOptions(); break; case 'cplusplus': - generatorOptions = ; + setGeneratorOptions(); break; case 'java': - generatorOptions = ; + setGeneratorOptions(); break; case 'kotlin': - generatorOptions = ; + setGeneratorOptions(); break; case 'rust': - generatorOptions = ; + setGeneratorOptions(); break; case 'python': - generatorOptions = ; + setGeneratorOptions(); break; case 'php': - generatorOptions = ; + setGeneratorOptions(); break; default: - generatorOptions = null; + setGeneratorOptions(prevOptions => null); break; } } - handleLanguageChange(); + useEffect(() => { + handleLanguageChange(); + }, []) useEffect(() => { handleLanguageChange(); - console.log(context?.language); - }, [context?.language]); + }, [context?.language, setNewConfig]); return (
                          diff --git a/modelina-website/src/pages/playground.tsx b/modelina-website/src/pages/playground.tsx index 3c24143854..19c97605de 100644 --- a/modelina-website/src/pages/playground.tsx +++ b/modelina-website/src/pages/playground.tsx @@ -5,11 +5,16 @@ import GenericLayout from '@/components/layouts/GenericLayout'; import { PlaygroundContextProvider } from '@/components/contexts/PlaygroundContext'; export default function PlaygroundPage() { - const [width, setWidth] = useState(window.innerWidth); + const [width, setWidth] = useState(typeof window !== 'undefined' ? window.innerWidth : 0); const description = 'Try out Modelina and see a fraction of what it can do.'; const image = '/img/social/modelina-card.jpg'; + // To avoid hydration error + const [isMounted, setIsMounted] = useState(false); + useEffect(() => { + setIsMounted(true); + const handleResize = () => { setWidth(window.innerWidth); } @@ -21,6 +26,10 @@ export default function PlaygroundPage() { } }, []); + if (!isMounted) { + return null; + } + return ( { - width > 768 ? + width > 768 ? - : -
                          + : +
                          Please revisit from the desktop to use the Modelina Playground.
                          } From 64e44b69b3f4aa7551d020d908bb7febfdec96b7 Mon Sep 17 00:00:00 2001 From: devilkiller-ag Date: Sun, 10 Dec 2023 23:46:18 +0530 Subject: [PATCH 27/29] rectified design bugs --- modelina-website/src/components/InfoModal.tsx | 2 +- .../src/components/playground/Content.tsx | 10 ++--- .../components/playground/GeneratedModels.tsx | 4 +- .../playground/OutputNavigation.tsx | 4 +- .../playground/PlaygroundOptions.tsx | 2 +- .../options/CSharpGeneratorOptions.tsx | 36 +++++++++--------- .../options/CplusplusGeneratorOptions.tsx | 6 +-- .../playground/options/GeneralOptions.tsx | 12 +++--- .../playground/options/GoGeneratorOptions.tsx | 6 +-- .../options/JavaGeneratorOptions.tsx | 38 +++++++++---------- .../options/KotlinGeneratorOptions.tsx | 6 +-- .../options/PhpGeneratorOptions.tsx | 10 ++--- .../options/TypeScriptGeneratorOptions.tsx | 28 +++++++------- 13 files changed, 82 insertions(+), 82 deletions(-) diff --git a/modelina-website/src/components/InfoModal.tsx b/modelina-website/src/components/InfoModal.tsx index c2ac027096..ac84d75c86 100644 --- a/modelina-website/src/components/InfoModal.tsx +++ b/modelina-website/src/components/InfoModal.tsx @@ -38,7 +38,7 @@ export default function InfoModal(props: InfoModalProps) { return ( <> +
                          +
                          diff --git a/modelina-website/src/components/playground/PlaygroundOptions.tsx b/modelina-website/src/components/playground/PlaygroundOptions.tsx index 68ca5dcb8e..7948f27aca 100644 --- a/modelina-website/src/components/playground/PlaygroundOptions.tsx +++ b/modelina-website/src/components/playground/PlaygroundOptions.tsx @@ -71,7 +71,7 @@ const PlaygroundOptions: React.FC = ({ setNewConfig }) = }, [context?.language, setNewConfig]); return ( -
                          +
                          {generatorOptions}
                          diff --git a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx index 39a1ba9331..7e889cc480 100644 --- a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx @@ -90,7 +90,7 @@ class CSharpGeneratorOptions extends React.Component< } } - debouncedSetNewConfig = debounce(this.props.setNewConfig || (() => {}), 500); + debouncedSetNewConfig = debounce(this.props.setNewConfig || (() => { }), 500); render() { return ( @@ -98,7 +98,7 @@ class CSharpGeneratorOptions extends React.Component<

                          CSharp Specific options

                          -
                        • +
                        • In C#, a namespace is used to organize code into logical groups @@ -109,20 +109,20 @@ class CSharpGeneratorOptions extends React.Component< of your code.

                          -
                        • -
                        • +
                        • In C#, arrays are used to store collections of elements of the @@ -138,7 +138,7 @@ class CSharpGeneratorOptions extends React.Component< functionality and flexibility for working with collections.

                          -
                        • -
                        • +
                        • Auto-implemented properties in C# allow you to define properties @@ -165,7 +165,7 @@ class CSharpGeneratorOptions extends React.Component< boilerplate code you need to write.

                          -
                        • -
                        • +
                        • In C#, the GetHashCode() method is used to generate a hash code @@ -190,7 +190,7 @@ class CSharpGeneratorOptions extends React.Component< calculation based on the model's properties.

                          -
                        • -
                        • +
                        • The Equals() method in C# is used to compare two objects for @@ -216,7 +216,7 @@ class CSharpGeneratorOptions extends React.Component< comparisons.

                          -
                        • -
                        • +
                        • In C#, JSON serialization is the process of converting an object @@ -240,7 +240,7 @@ class CSharpGeneratorOptions extends React.Component< of the models.

                          -
                        • -
                        • +
                        • Newtonsoft.Json (Json.NET) is a popular third-party JSON @@ -264,7 +264,7 @@ class CSharpGeneratorOptions extends React.Component< using the Json.NET library.

                          -
                        • -
                        • +
                        • In C#, the nullable feature allows you to explicitly indicate @@ -288,7 +288,7 @@ class CSharpGeneratorOptions extends React.Component< flexibility when dealing with optional or unknown data values.

                          -
                        • +
                        • In C++, a namespace is a feature that allows you to organize your code into logical groups or containers. It helps in avoiding naming conflicts between different parts of your code and provides a way to encapsulate related code.

                          -
                        • +
                        • In Go, a package name is used to organize code into logical groups or containers. It serves as a namespace for the code elements within it and helps in avoiding naming conflicts.

                          -
                        • +
                        • In Java, a package name is a way to organize and group related classes and interfaces. It is a naming convention that helps prevent naming conflicts and provides a hierarchical structure to the Java codebase. @@ -110,20 +110,20 @@ class JavaGeneratorOptions extends React.Component< A package name is written as series of identifiers separated by dots ('.'). Each identifier represents a level in the package hierarchy. For example, a package name could be 'com.example.myapp'.

                          -
                        • -
                        • +
                        • When you enable the "Include Jackson serialization" option, it means that the code generator will include the necessary annotations from the Jackson library in the generated code. These annotations are used to configure and control how Java objects are serialized to JSON and deserialized from JSON. @@ -131,7 +131,7 @@ class JavaGeneratorOptions extends React.Component< Annotations in Java are represented by the @ symbol followed by the annotation name.

                          -
                        • -
                        • +
                        • This option indicates whether the marshal and unmarshal functions would be included in the generated code or not @@ -156,7 +156,7 @@ class JavaGeneratorOptions extends React.Component< unmarshal - this function takes a JSON object and returns an instanve of the class.

                          -
                        • -
                        • +
                        • This option allows you to switch between rendering collections as List type or Array. @@ -177,7 +177,7 @@ class JavaGeneratorOptions extends React.Component< The default value is Array.

                          -
                        • -
                        • +
                        • In Java, the "hashCode()" method is used to generate a unique numeric value (hash code) for an object. The default implementation of hashCode() in the Object class generates hash codes based on the memory address of the object, which may not be suitable for all classes. @@ -200,7 +200,7 @@ class JavaGeneratorOptions extends React.Component< When you enable the "Include Overwrite HashCode Support" option, it means that the code generator will automatically generate a customized implementation of the hashCode() method for the class you are working with. Instead of using the default implementation.

                          -
                        • -
                        • +
                        • In Java, the "equals()" method is used to determine if two objects are equal based on their content rather than their memory addresses. The default implementation of equals() in the Object class performs a reference equality check, meaning it only returns true if the compared objects are the same instance in memory. @@ -221,7 +221,7 @@ class JavaGeneratorOptions extends React.Component< When you enable the "Include Overwrite Equal Support" option, it means that the code generator will automatically generate a customized implementation of the equals() method for the class you are working with. Instead of using the default implementation.

                          -
                        • -
                        • +
                        • In Java, the "toString()" method is a built-in method defined in the Object class and inherited by all other classes. Its purpose is to provide a string representation of an object. By default, the toString() method in the Object class returns a string that includes the class name, an "@" symbol, and the hexadecimal representation of the object's hash code. @@ -242,7 +242,7 @@ class JavaGeneratorOptions extends React.Component< When you enable the "Include Overwrite toString Support" option, it means that the code generator will automatically generate a customized implementation of the toString() method for the class you are working with. Instead of using the default implementation.

                          -
                        • -
                        • +
                        • Enabling this option will include the description of the properties as comments in the generated code. @@ -263,7 +263,7 @@ class JavaGeneratorOptions extends React.Component< The default value if false.

                          -
                        • -
                        • +
                        • By using the 'javax.validation.constraints' annotations, you can ensure that the data in your Java object adheres to specific rules and constraints. This helps in validating user input, ensuring data integrity, and facilitating error handling and validation reporting.

                          -
                        • +
                        • In Kotlin, a package name is used to organize classes, functions, and other code elements into logical groups or containers. It helps in avoiding naming conflicts and provides a way to structure your code.

                          -
                        • +
                        • In PHP namespaces are used to organize code into logical groups. It helps to avoid naming conflicts and allows to use the same class names in different namespaces.

                          -
                        • -
                        • +
                        • It indicates whether the descriptions should be included in the generated code. @@ -80,7 +80,7 @@ class PhpGeneratorOptions extends React.Component< The default value is false.

                          -
                        • - +

                          It indicates which model type should be rendered for the object type. Its value can be either interface or class.

                          The default value is class.

                          -
                        • - +

                          It indicates which type should be rendered for some enum type. Its value can be either union or enum.

                          The default value is union.

                          -
                        • - +

                          It indicates which module system should be used for the generated code. Its value can be either ESM or CJS.

                          @@ -141,7 +141,7 @@ class TypeScriptGeneratorOptions extends React.Component< CJS - CommonJS Modules. This uses the require/module.exports syntax.

                          -
                        • - +

                          It indicates whether the descriptions should be included in the generated code.

                          The default value is false.

                          -
                        • {this.context?.tsModelType === 'class' ? (
                        • - +

                          It indicates whether the un/marshal functions should be included in the generated code.

                          @@ -190,7 +190,7 @@ class TypeScriptGeneratorOptions extends React.Component< Marshal - This function takes an instance of the class and returns a JSON object.

                          -
                        • - +

                          It indicates whether the JsonBinPack support should be included in the generated code. This allows you to convert models to a buffer, which is highly space-efficient, instead of sending pure JSON data over the wire. @@ -226,7 +226,7 @@ class TypeScriptGeneratorOptions extends React.Component<

                        -