diff --git a/packages/server/src/config/index.ts b/packages/server/src/config/index.ts index f9abb8622..79c3911b3 100644 --- a/packages/server/src/config/index.ts +++ b/packages/server/src/config/index.ts @@ -246,8 +246,11 @@ module.exports = { apiKey: process.env.LOOPS_API_KEY, }, - oneClickDemoAccounts: parseBoolean( - process.env.ONE_CLICK_DEMO_ACCOUNTS, - false - ), + /** + * One-click demo accounts. + */ + oneClickDemoAccounts: { + enable: parseBoolean(process.env.ONE_CLICK_DEMO_ACCOUNTS, false), + demoUrl: process.env.ONE_CLICK_DEMO_ACCOUNTS_URL || '', + }, }; diff --git a/packages/server/src/interfaces/Authentication.ts b/packages/server/src/interfaces/Authentication.ts index 2743ee513..aee2d3521 100644 --- a/packages/server/src/interfaces/Authentication.ts +++ b/packages/server/src/interfaces/Authentication.ts @@ -76,6 +76,10 @@ export interface IAuthSendedResetPassword { export interface IAuthGetMetaPOJO { signupDisabled: boolean; + oneClickDemo: { + enable: boolean; + demoUrl: string; + }; } export interface IAuthSignUpVerifingEventPayload { diff --git a/packages/server/src/services/Authentication/GetAuthMeta.ts b/packages/server/src/services/Authentication/GetAuthMeta.ts index 80e68d682..0183043b8 100644 --- a/packages/server/src/services/Authentication/GetAuthMeta.ts +++ b/packages/server/src/services/Authentication/GetAuthMeta.ts @@ -11,6 +11,10 @@ export class GetAuthMeta { public async getAuthMeta(): Promise { return { signupDisabled: config.signupRestrictions.disabled, + oneClickDemo: { + enable: config.oneClickDemoAccounts.enable, + demoUrl: config.oneClickDemoAccounts.demoUrl, + }, }; } } diff --git a/packages/webapp/src/components/App.tsx b/packages/webapp/src/components/App.tsx index 98242e9db..1a78ef10e 100644 --- a/packages/webapp/src/components/App.tsx +++ b/packages/webapp/src/components/App.tsx @@ -20,7 +20,6 @@ import { queryConfig } from '../hooks/query/base'; import { EnsureUserEmailVerified } from './Guards/EnsureUserEmailVerified'; import { EnsureAuthNotAuthenticated } from './Guards/EnsureAuthNotAuthenticated'; import { EnsureUserEmailNotVerified } from './Guards/EnsureUserEmailNotVerified'; -import { EnsureOneClickDemoAccountEnabled } from '@/containers/OneClickDemo/EnsureOneClickDemoAccountEnabled'; const EmailConfirmation = LazyLoader({ loader: () => import('@/containers/Authentication/EmailConfirmation'), @@ -31,6 +30,7 @@ const RegisterVerify = LazyLoader({ const OneClickDemoPage = LazyLoader({ loader: () => import('@/containers/OneClickDemo/OneClickDemoPage'), }); + /** * App inner. */ @@ -40,13 +40,7 @@ function AppInsider({ history }) { - - - - - - - + } /> diff --git a/packages/webapp/src/components/Dashboard/PrivatePagesProvider.tsx b/packages/webapp/src/components/Dashboard/PrivatePagesProvider.tsx index 3716b3011..0396a7838 100644 --- a/packages/webapp/src/components/Dashboard/PrivatePagesProvider.tsx +++ b/packages/webapp/src/components/Dashboard/PrivatePagesProvider.tsx @@ -1,6 +1,7 @@ // @ts-nocheck import React from 'react'; import { useApplicationBoot } from '@/components'; +import { useAuthMetadata } from '@/hooks/query/authentication'; /** * Private pages provider. @@ -9,7 +10,10 @@ export function PrivatePagesProvider({ // #ownProps children, }) { - const { isLoading } = useApplicationBoot(); + const { isLoading: isAppBootLoading } = useApplicationBoot(); + const { isLoading: isAuthMetaLoading } = useAuthMetadata(); + + const isLoading = isAppBootLoading || isAuthMetaLoading; return {!isLoading ? children : null}; } diff --git a/packages/webapp/src/config.ts b/packages/webapp/src/config.ts deleted file mode 100644 index 1d2b73985..000000000 --- a/packages/webapp/src/config.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const Config = { - oneClickDemo: { - enable: process.env.REACT_APP_ONE_CLICK_DEMO_ENABLE === 'true', - demoUrl: process.env.REACT_APP_DEMO_ACCOUNT_URL || '', - }, -}; diff --git a/packages/webapp/src/containers/OneClickDemo/EnsureOneClickDemoAccountEnabled.tsx b/packages/webapp/src/containers/OneClickDemo/EnsureOneClickDemoAccountEnabled.tsx index 7b224372f..4bffd4043 100644 --- a/packages/webapp/src/containers/OneClickDemo/EnsureOneClickDemoAccountEnabled.tsx +++ b/packages/webapp/src/containers/OneClickDemo/EnsureOneClickDemoAccountEnabled.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Redirect } from 'react-router-dom'; -import { Config } from '@/config'; +import { useOneClickDemoBoot } from './OneClickDemoBoot'; interface EnsureOneClickDemoAccountEnabledProps { children: React.ReactNode; @@ -11,9 +11,10 @@ export const EnsureOneClickDemoAccountEnabled = ({ children, redirectTo = '/', }: EnsureOneClickDemoAccountEnabledProps) => { - const enabeld = Config.oneClickDemo.enable || false; + const { authMeta } = useOneClickDemoBoot(); + const enabled = authMeta?.meta?.one_click_demo?.enable || false; - if (!enabeld) { + if (!enabled) { return ; } return <>{children}; diff --git a/packages/webapp/src/containers/OneClickDemo/OneClickDemoBoot.tsx b/packages/webapp/src/containers/OneClickDemo/OneClickDemoBoot.tsx new file mode 100644 index 000000000..63036c344 --- /dev/null +++ b/packages/webapp/src/containers/OneClickDemo/OneClickDemoBoot.tsx @@ -0,0 +1,45 @@ +import React, { createContext, useContext, ReactNode } from 'react'; +import { useAuthMetadata } from '@/hooks/query/authentication'; + +interface OneClickDemoContextType { + authMeta: any; +} + +const OneClickDemoContext = createContext( + {} as OneClickDemoContextType, +); + +export const useOneClickDemoBoot = () => { + const context = useContext(OneClickDemoContext); + + if (!context) { + throw new Error( + 'useOneClickDemo must be used within a OneClickDemoProvider', + ); + } + return context; +}; + +interface OneClickDemoBootProps { + children: ReactNode; +} + +export const OneClickDemoBoot: React.FC = ({ + children, +}) => { + const { isLoading: isAuthMetaLoading, data: authMeta } = useAuthMetadata(); + + const value = { + isAuthMetaLoading, + authMeta, + }; + + if (isAuthMetaLoading) { + return null; + } + return ( + + {children} + + ); +}; diff --git a/packages/webapp/src/containers/OneClickDemo/OneClickDemoPage.tsx b/packages/webapp/src/containers/OneClickDemo/OneClickDemoPage.tsx index cc200ce52..fb040ec71 100644 --- a/packages/webapp/src/containers/OneClickDemo/OneClickDemoPage.tsx +++ b/packages/webapp/src/containers/OneClickDemo/OneClickDemoPage.tsx @@ -1,97 +1,16 @@ -// @ts-nocheck -import { Button, Intent, ProgressBar, Text } from '@blueprintjs/core'; -import { useEffect, useState } from 'react'; -import { - useCreateOneClickDemo, - useOneClickDemoSignin, -} from '@/hooks/query/oneclick-demo'; -import { Box, Icon, Stack } from '@/components'; -import { useJob } from '@/hooks/query'; -import style from './OneClickDemoPage.module.scss'; +import { EnsureAuthNotAuthenticated } from '@/components/Guards/EnsureAuthNotAuthenticated'; +import { EnsureOneClickDemoAccountEnabled } from './EnsureOneClickDemoAccountEnabled'; +import { OneClickDemoBoot } from './OneClickDemoBoot'; +import { OneClickDemoPageContent } from './OneClickDemoPageContent'; export default function OneClickDemoPage() { - const { - mutateAsync: createOneClickDemo, - isLoading: isCreateOneClickLoading, - } = useCreateOneClickDemo(); - const { - mutateAsync: oneClickDemoSignIn, - isLoading: isOneclickDemoSigningIn, - } = useOneClickDemoSignin(); - - // Job states. - const [demoId, setDemoId] = useState(''); - const [buildJobId, setBuildJobId] = useState(''); - const [isJobDone, setIsJobDone] = useState(false); - - const { - data: { running, completed }, - } = useJob(buildJobId, { - refetchInterval: 2000, - enabled: !isJobDone && !!buildJobId, - }); - - useEffect(() => { - if (completed) { - setIsJobDone(true); - } - }, [completed, setIsJobDone]); - - // One the job done request sign-in using the demo id. - useEffect(() => { - if (isJobDone) { - oneClickDemoSignIn({ demoId }).then((res) => { - debugger; - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isJobDone]); - - const handleCreateAccountBtnClick = () => { - createOneClickDemo({}) - .then(({ data: { data } }) => { - setBuildJobId(data?.build_job?.job_id); - setDemoId(data?.demo_id); - }) - .catch(() => {}); - }; - const isLoading = running || isOneclickDemoSigningIn; - return ( - - - - - - {isLoading && ( - - - {isOneclickDemoSigningIn && ( - - It's signin-in to your demo account, Just a second! - - )} - {running && ( - - We're preparing temporary environment for trial, It typically - take few seconds. Do not close or refresh the page. - - )} - - )} - - - {!isLoading && ( - - )} - - + + + + + + + ); } diff --git a/packages/webapp/src/containers/OneClickDemo/OneClickDemoPageContent.tsx b/packages/webapp/src/containers/OneClickDemo/OneClickDemoPageContent.tsx new file mode 100644 index 000000000..20a15fa20 --- /dev/null +++ b/packages/webapp/src/containers/OneClickDemo/OneClickDemoPageContent.tsx @@ -0,0 +1,97 @@ +// @ts-nocheck +import { Button, Intent, ProgressBar, Text } from '@blueprintjs/core'; +import { useEffect, useState } from 'react'; +import { + useCreateOneClickDemo, + useOneClickDemoSignin, +} from '@/hooks/query/oneclick-demo'; +import { Box, Icon, Stack } from '@/components'; +import { useJob } from '@/hooks/query'; +import style from './OneClickDemoPage.module.scss'; + +export function OneClickDemoPageContent() { + const { + mutateAsync: createOneClickDemo, + isLoading: isCreateOneClickLoading, + } = useCreateOneClickDemo(); + const { + mutateAsync: oneClickDemoSignIn, + isLoading: isOneclickDemoSigningIn, + } = useOneClickDemoSignin(); + + // Job states. + const [demoId, setDemoId] = useState(''); + const [buildJobId, setBuildJobId] = useState(''); + const [isJobDone, setIsJobDone] = useState(false); + + const { + data: { running, completed }, + } = useJob(buildJobId, { + refetchInterval: 2000, + enabled: !isJobDone && !!buildJobId, + }); + + useEffect(() => { + if (completed) { + setIsJobDone(true); + } + }, [completed, setIsJobDone]); + + // One the job done request sign-in using the demo id. + useEffect(() => { + if (isJobDone) { + oneClickDemoSignIn({ demoId }).then((res) => { + debugger; + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isJobDone]); + + const handleCreateAccountBtnClick = () => { + createOneClickDemo({}) + .then(({ data: { data } }) => { + setBuildJobId(data?.build_job?.job_id); + setDemoId(data?.demo_id); + }) + .catch(() => {}); + }; + const isLoading = running || isOneclickDemoSigningIn; + + return ( + + + + + + {isLoading && ( + + + {isOneclickDemoSigningIn && ( + + It's signin-in to your demo account, Just a second! + + )} + {running && ( + + We're preparing temporary environment for trial, It typically + take few seconds. Do not close or refresh the page. + + )} + + )} + + + {!isLoading && ( + + )} + + + ); +} diff --git a/packages/webapp/src/containers/Setup/SetupLeftSection.tsx b/packages/webapp/src/containers/Setup/SetupLeftSection.tsx index 487c4bbb9..8d96cea37 100644 --- a/packages/webapp/src/containers/Setup/SetupLeftSection.tsx +++ b/packages/webapp/src/containers/Setup/SetupLeftSection.tsx @@ -6,7 +6,7 @@ import { Icon, For, FormattedMessage as T, Stack } from '@/components'; import { getFooterLinks } from '@/constants/footerLinks'; import { useAuthActions } from '@/hooks/state'; import style from './SetupLeftSection.module.scss'; -import { Config } from '@/config'; +import { useAuthMetadata } from '@/hooks/query'; /** * Footer item link. @@ -28,13 +28,16 @@ function SetupLeftSectionFooter() { // Retrieve the footer links. const footerLinks = getFooterLinks(); + const { data: authMeta } = useAuthMetadata(); + const demoUrl = authMeta?.meta?.one_click_demo?.demo_url; + const handleDemoBtnClick = () => { - window.open(Config.oneClickDemo.demoUrl); + window.open(demoUrl); }; return (
- {Config.oneClickDemo.demoUrl && ( + {demoUrl && ( Not Now?