Skip to content

Commit

Permalink
Merge pull request #628 from bigcapitalhq/fix-webapp-env-variables
Browse files Browse the repository at this point in the history
fix: Make webapp package env variables dynamic
  • Loading branch information
abouolia authored Aug 25, 2024
2 parents 1eaac9d + 2072e35 commit 58552c6
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 118 deletions.
11 changes: 7 additions & 4 deletions packages/server/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 || '',
},
};
4 changes: 4 additions & 0 deletions packages/server/src/interfaces/Authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export interface IAuthSendedResetPassword {

export interface IAuthGetMetaPOJO {
signupDisabled: boolean;
oneClickDemo: {
enable: boolean;
demoUrl: string;
};
}

export interface IAuthSignUpVerifingEventPayload {
Expand Down
4 changes: 4 additions & 0 deletions packages/server/src/services/Authentication/GetAuthMeta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class GetAuthMeta {
public async getAuthMeta(): Promise<IAuthGetMetaPOJO> {
return {
signupDisabled: config.signupRestrictions.disabled,
oneClickDemo: {
enable: config.oneClickDemoAccounts.enable,
demoUrl: config.oneClickDemoAccounts.demoUrl,
},
};
}
}
10 changes: 2 additions & 8 deletions packages/webapp/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand All @@ -31,6 +30,7 @@ const RegisterVerify = LazyLoader({
const OneClickDemoPage = LazyLoader({
loader: () => import('@/containers/OneClickDemo/OneClickDemoPage'),
});

/**
* App inner.
*/
Expand All @@ -40,13 +40,7 @@ function AppInsider({ history }) {
<DashboardThemeProvider>
<Router history={history}>
<Switch>
<Route path={'/one_click_demo'}>
<EnsureOneClickDemoAccountEnabled>
<EnsureAuthNotAuthenticated>
<OneClickDemoPage />
</EnsureAuthNotAuthenticated>
</EnsureOneClickDemoAccountEnabled>
</Route>
<Route path={'/one_click_demo'} children={<OneClickDemoPage />} />
<Route path={'/auth/register/verify'}>
<EnsureAuthenticated>
<EnsureUserEmailNotVerified>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @ts-nocheck
import React from 'react';
import { useApplicationBoot } from '@/components';
import { useAuthMetadata } from '@/hooks/query/authentication';

/**
* Private pages provider.
Expand All @@ -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 <React.Fragment>{!isLoading ? children : null}</React.Fragment>;
}
6 changes: 0 additions & 6 deletions packages/webapp/src/config.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 <Redirect to={{ pathname: redirectTo }} />;
}
return <>{children}</>;
Expand Down
45 changes: 45 additions & 0 deletions packages/webapp/src/containers/OneClickDemo/OneClickDemoBoot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { createContext, useContext, ReactNode } from 'react';
import { useAuthMetadata } from '@/hooks/query/authentication';

interface OneClickDemoContextType {
authMeta: any;
}

const OneClickDemoContext = createContext<OneClickDemoContextType>(
{} 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<OneClickDemoBootProps> = ({
children,
}) => {
const { isLoading: isAuthMetaLoading, data: authMeta } = useAuthMetadata();

const value = {
isAuthMetaLoading,
authMeta,
};

if (isAuthMetaLoading) {
return null;
}
return (
<OneClickDemoContext.Provider value={value}>
{children}
</OneClickDemoContext.Provider>
);
};
103 changes: 11 additions & 92 deletions packages/webapp/src/containers/OneClickDemo/OneClickDemoPage.tsx
Original file line number Diff line number Diff line change
@@ -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<string>('');
const [buildJobId, setBuildJobId] = useState<string>('');
const [isJobDone, setIsJobDone] = useState<boolean>(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 (
<Box className={style.root}>
<Box className={style.inner}>
<Stack align={'center'} spacing={40}>
<Icon icon="bigcapital" height={37} width={228} />

{isLoading && (
<Stack align={'center'} spacing={15}>
<ProgressBar stripes value={null} className={style.progressBar} />
{isOneclickDemoSigningIn && (
<Text className={style.waitingText}>
It's signin-in to your demo account, Just a second!
</Text>
)}
{running && (
<Text className={style.waitingText}>
We're preparing temporary environment for trial, It typically
take few seconds. Do not close or refresh the page.
</Text>
)}
</Stack>
)}
</Stack>

{!isLoading && (
<Button
className={style.oneClickBtn}
intent={Intent.NONE}
onClick={handleCreateAccountBtnClick}
loading={isCreateOneClickLoading}
>
Create Demo Account
</Button>
)}
</Box>
</Box>
<EnsureAuthNotAuthenticated>
<OneClickDemoBoot>
<EnsureOneClickDemoAccountEnabled>
<OneClickDemoPageContent />
</EnsureOneClickDemoAccountEnabled>
</OneClickDemoBoot>
</EnsureAuthNotAuthenticated>
);
}
Original file line number Diff line number Diff line change
@@ -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<string>('');
const [buildJobId, setBuildJobId] = useState<string>('');
const [isJobDone, setIsJobDone] = useState<boolean>(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 (
<Box className={style.root}>
<Box className={style.inner}>
<Stack align={'center'} spacing={40}>
<Icon icon="bigcapital" height={37} width={228} />

{isLoading && (
<Stack align={'center'} spacing={15}>
<ProgressBar stripes value={null} className={style.progressBar} />
{isOneclickDemoSigningIn && (
<Text className={style.waitingText}>
It's signin-in to your demo account, Just a second!
</Text>
)}
{running && (
<Text className={style.waitingText}>
We're preparing temporary environment for trial, It typically
take few seconds. Do not close or refresh the page.
</Text>
)}
</Stack>
)}
</Stack>

{!isLoading && (
<Button
className={style.oneClickBtn}
intent={Intent.NONE}
onClick={handleCreateAccountBtnClick}
loading={isCreateOneClickLoading}
>
Create Demo Account
</Button>
)}
</Box>
</Box>
);
}
9 changes: 6 additions & 3 deletions packages/webapp/src/containers/Setup/SetupLeftSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 (
<div className={'content__footer'}>
{Config.oneClickDemo.demoUrl && (
{demoUrl && (
<Stack spacing={16}>
<Text className={style.demoButtonLabel}>Not Now?</Text>
<button className={style.demoButton} onClick={handleDemoBtnClick}>
Expand Down
Loading

0 comments on commit 58552c6

Please sign in to comment.