diff --git a/modelina-website/src/components/contexts/PlaygroundContext.tsx b/modelina-website/src/components/contexts/PlaygroundContext.tsx index 9ed959ec20..85846febc4 100644 --- a/modelina-website/src/components/contexts/PlaygroundContext.tsx +++ b/modelina-website/src/components/contexts/PlaygroundContext.tsx @@ -48,6 +48,8 @@ interface PlaygroundContextProps { setHasLoadedQuery: Dispatch>; renderModels: React.ReactNode | null; setRenderModels: (models: React.ReactNode) => void; + outputLoading: boolean; + setOutputLoading: Dispatch>; } const PlaygroundContext = createContext(undefined); @@ -111,6 +113,7 @@ export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> const [isLoaded, setIsLoaded] = useState(false); const [hasLoadedQuery, setHasLoadedQuery] = useState(false); const [renderModels, setRenderModels] = React.useState(null); + const [outputLoading, setOutputLoading] = useState(false); const contextValue = useMemo(() => ({ showOptions, @@ -140,7 +143,9 @@ export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> hasLoadedQuery, setHasLoadedQuery, renderModels, - setRenderModels + setRenderModels, + outputLoading, + setOutputLoading }), [ showOptions, setShowOptions, @@ -170,6 +175,8 @@ export const PlaygroundContextProvider: React.FC<{ children: React.ReactNode; }> setHasLoadedQuery, renderModels, setRenderModels, + outputLoading, + setOutputLoading ]); return ( diff --git a/modelina-website/src/components/playground/GeneratedModels.tsx b/modelina-website/src/components/playground/GeneratedModels.tsx index d20e95e990..8878dcace6 100644 --- a/modelina-website/src/components/playground/GeneratedModels.tsx +++ b/modelina-website/src/components/playground/GeneratedModels.tsx @@ -15,7 +15,7 @@ const GeneratedModelsComponent: React.FC = ({ const context = useContext(PlaygroundGeneratedContext); const [selectedModel, setSelectedModel] = useState(''); const { setRenderModels, generatorCode, showGeneratorCode, setShowGeneratorCode } = usePlaygroundContext(); - + const { outputLoading } = usePlaygroundContext(); const toShow = () => { let selectedCode = ''; let updatedSelectedModel = selectedModel; @@ -75,6 +75,14 @@ const GeneratedModelsComponent: React.FC = ({ setRenderModels(modelsToRender); }, [updatedSelectedModel, showGeneratorCode]); + if (outputLoading) { + return ( +
+
Loading...
+
+ ); + } + if (showAllInOneFile === true) { return (
diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index fae6a49957..b8dba82e53 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -45,6 +45,8 @@ const Playground: React.FC = (props) => { setIsLoaded, hasLoadedQuery, setHasLoadedQuery, + outputLoading, + setOutputLoading } = usePlaygroundContext(); // To avoid hydration error @@ -263,10 +265,12 @@ const Playground: React.FC = (props) => { setError(false); setStatusCode(200); setErrorMessage(''); + setOutputLoading(false); }).catch(error => { console.error(error); setError(true); setErrorMessage("Input is not a correct AsyncAPI document, so it cannot be processed."); + setOutputLoading(true); setStatusCode(500); }); } @@ -274,6 +278,7 @@ const Playground: React.FC = (props) => { console.error(e); setError(true); setErrorMessage("Input is not a correct AsyncAPI document, so it cannot be processed."); + setOutputLoading(true); setStatusCode(400); } }; diff --git a/modelina-website/src/components/playground/options/GeneralOptions.tsx b/modelina-website/src/components/playground/options/GeneralOptions.tsx index d74bcb061e..36dfad627a 100644 --- a/modelina-website/src/components/playground/options/GeneralOptions.tsx +++ b/modelina-website/src/components/playground/options/GeneralOptions.tsx @@ -4,6 +4,7 @@ import { modelinaLanguageOptions } from '@/types'; import { PlaygroundGeneralConfigContext } from '@/components/contexts/PlaygroundConfigContext'; import InfoModal from '@/components/InfoModal'; import Select from '../../Select'; +import { usePlaygroundContext } from '../../contexts/PlaygroundContext'; interface GeneralOptionsProps { setNewConfig?: (queryKey: string, queryValue: any) => void; @@ -13,32 +14,44 @@ interface GeneralOptionsState { } export const defaultState: GeneralOptionsState = {}; + const GeneralOptions: React.FC = ({ setNewConfig }) => { const context = useContext(PlaygroundGeneralConfigContext); const [state, setState] = useState(defaultState); + const { + setOutputLoading + } = usePlaygroundContext(); + + const onChangeLanguage = (language: any) => { setNewConfig?.('language', String(language)); + setOutputLoading(true); }; const onChangeShowTypeMappingExample = (event: React.ChangeEvent) => { setNewConfig?.('showTypeMappingExample', event.target.checked); + setOutputLoading(true); }; const onChangeIndentationType = (value: any) => { setNewConfig?.('indentationType', String(value)); + setOutputLoading(true); }; const onChangePropertyNamingFormat = (value: any) => { setNewConfig?.('propertyNamingFormat', String(value)); + setOutputLoading(true); }; const onChangeModelNamingFormat = (value: any) => { setNewConfig?.('modelNamingFormat', String(value)); + setOutputLoading(true); }; const onChangeEnumKeyNamingFormat = (value: any) => { setNewConfig?.('enumKeyNamingFormat', String(value)); + setOutputLoading(true); }; return ( diff --git a/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx b/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx index 0e3b9c3889..367f134c86 100644 --- a/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx @@ -2,6 +2,7 @@ import React, { useContext, useState } from 'react'; import Select from '../../Select'; import { PlaygroundTypeScriptConfigContext } from '@/components/contexts/PlaygroundConfigContext'; import InfoModal from '@/components/InfoModal'; +import { usePlaygroundContext } from '../../contexts/PlaygroundContext'; interface TypeScriptGeneratorOptionsProps { setNewConfig?: (queryKey: string, queryValue: any, updateCode?: boolean) => void; @@ -14,35 +15,46 @@ export const defaultState: TypeScriptGeneratorState = {}; const TypeScriptGeneratorOptions: React.FC = ({ setNewConfig }) => { const context = useContext(PlaygroundTypeScriptConfigContext); const [state, setState] = useState(defaultState); + const { + setOutputLoading + } = usePlaygroundContext(); + const onChangeMarshalling = (event: React.ChangeEvent) => { setNewConfig && setNewConfig('tsMarshalling', event.target.checked); + setOutputLoading(true); }; const onChangeIncludeDescriptions = (event: React.ChangeEvent) => { setNewConfig && setNewConfig('tsIncludeDescriptions', event.target.checked); + setOutputLoading(true); }; const onChangeVariant = (variant: string) => { setNewConfig && setNewConfig('tsModelType', variant); + setOutputLoading(true); }; const onChangeModuleSystem = (moduleSystem: string) => { setNewConfig && setNewConfig('tsModuleSystem', moduleSystem); + setOutputLoading(true); }; const onChangeEnumType = (enumType: string) => { setNewConfig && setNewConfig('tsEnumType', enumType); + setOutputLoading(true); }; const onChangeMapType = (mapType: string) => { setNewConfig && setNewConfig('tsMapType', mapType); + setOutputLoading(true); }; const onChangeIncludeJsonBinPack = (event: React.ChangeEvent) => { if (setNewConfig) { const shouldIncludeMarshalling = context?.tsMarshalling === false && event.target.checked === true; setNewConfig('tsIncludeJsonBinPack', event.target.checked, !shouldIncludeMarshalling); + setOutputLoading(true); if (shouldIncludeMarshalling) { setNewConfig('tsMarshalling', event.target.checked); @@ -52,6 +64,7 @@ const TypeScriptGeneratorOptions: React.FC = ({ const onChangeIncludeExampleFunction = (event: React.ChangeEvent) => { setNewConfig && setNewConfig('tsIncludeExampleFunction', event.target.checked); + setOutputLoading(true); }; return (