show popup when email not configured

This commit is contained in:
Maidul Islam
2023-03-16 09:56:42 -07:00
parent dce5c8f621
commit 8e55d17a55
12 changed files with 149 additions and 14 deletions

View File

@@ -2,10 +2,13 @@ import React, { useState } from 'react';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import { useFetchServerStatus } from '@app/hooks/api/serverDetails';
import { usePopUp } from '@app/hooks/usePopUp';
import addUserToOrg from '@app/pages/api/organization/addUserToOrg';
import getWorkspaces from '@app/pages/api/workspace/getWorkspaces';
import Button from '../basic/buttons/Button';
import { EmailServiceSetupModal } from '../v2';
/**
* This is the last step of the signup flow. People can optionally invite their teammates here.
@@ -14,6 +17,10 @@ export default function TeamInviteStep(): JSX.Element {
const [emails, setEmails] = useState('');
const { t } = useTranslation();
const router = useRouter();
const {data: serverDetails } = useFetchServerStatus()
const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp([
'setUpEmail'
] as const);
// Redirect user to the getting started page
const redirectToHome = async () => {
@@ -62,10 +69,20 @@ export default function TeamInviteStep(): JSX.Element {
</div>
<Button
text={t('signup:step5-send-invites') ?? ''}
onButtonPressed={() => inviteUsers({ emails })}
onButtonPressed={() => {
if(serverDetails?.emailConfigured){
inviteUsers({ emails })
}else{
handlePopUpOpen('setUpEmail');
}
}}
size="lg"
/>
</div>
<EmailServiceSetupModal
isOpen={popUp.setUpEmail?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
/>
</div>
);
}

View File

@@ -0,0 +1,21 @@
import { Button } from '../Button';
import { Modal, ModalContent } from '../Modal';
type Props = {
isOpen?: boolean;
onOpenChange?: (isOpen: boolean) => void;
};
export const EmailServiceSetupModal = ({ isOpen, onOpenChange }: Props): JSX.Element => (
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalContent title="Email service not configured">
<p className="mb-4 text-bunker-300">
The administrators of this Infisical instance have not yet set up an email service provider required to perform this action
</p>
<a href="https://infisical.com/docs/self-hosting/configuration/email">
<Button className="mr-4">Learn more</Button>
</a>
</ModalContent>
</Modal>
);

View File

@@ -0,0 +1 @@
export { EmailServiceSetupModal } from './EmailServiceSetupModal';

View File

@@ -3,6 +3,7 @@ export * from './Card';
export * from './Checkbox';
export * from './DeleteActionModal';
export * from './Dropdown';
export * from './EmailServiceSetupModal'
export * from './EmptyState';
export * from './FormControl';
export * from './IconButton';

View File

@@ -0,0 +1 @@
export { useFetchServerStatus } from './queries'

View File

@@ -0,0 +1,19 @@
import {useQuery } from '@tanstack/react-query';
import { apiRequest } from '@app/config/request';
import { ServerStatus } from './types';
// cache key
const serverStatusKeys = {
serverStatus: ['serverStatus'] as const
};
const fetchServerStatus = async () => {
const {data} = await apiRequest.get<ServerStatus>('/api/status');
return data;
};
export const useFetchServerStatus= () => {
return useQuery({ queryKey: serverStatusKeys.serverStatus, queryFn: fetchServerStatus });
}

View File

@@ -0,0 +1,5 @@
export type ServerStatus = {
date: string;
message: string;
emailConfigured: boolean;
};

View File

@@ -13,6 +13,7 @@ import TeamInviteStep from '@app/components/signup/TeamInviteStep';
import UserInfoStep from '@app/components/signup/UserInfoStep';
import SecurityClient from '@app/components/utilities/SecurityClient';
import { getTranslatedStaticProps } from '@app/components/utilities/withTranslateProps';
import { useFetchServerStatus } from '@app/hooks/api/serverDetails';
import checkEmailVerificationCode from './api/auth/CheckEmailVerificationCode';
import getWorkspaces from './api/workspace/getWorkspaces';
@@ -25,10 +26,12 @@ export default function SignUp() {
const [password, setPassword] = useState('');
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [code, setCode] = useState('');
const [code, setCode] = useState('123456');
const [codeError, setCodeError] = useState(false);
const [step, setStep] = useState(1);
const router = useRouter();
const {data: serverDetails } = useFetchServerStatus()
const { t } = useTranslation();
@@ -68,6 +71,13 @@ export default function SignUp() {
}
};
// when email service is not configured, skip step 2
useEffect(() => {
if (!serverDetails?.emailConfigured && step === 2){
incrementStep()
}
}, [step]);
return (
<div className="bg-bunker-800 h-screen flex flex-col items-center justify-center">
<Head>

View File

@@ -6,12 +6,19 @@ import Link from 'next/link';
import Button from '@app/components/basic/buttons/Button';
import InputField from '@app/components/basic/InputField';
import { getTranslatedStaticProps } from '@app/components/utilities/withTranslateProps';
import { EmailServiceSetupModal } from '@app/components/v2';
import { usePopUp } from '@app/hooks';
import { useFetchServerStatus } from '@app/hooks/api/serverDetails';
import SendEmailOnPasswordReset from './api/auth/SendEmailOnPasswordReset';
export default function VerifyEmail() {
const [email, setEmail] = useState('');
const [step, setStep] = useState(1);
const {data: serverDetails } = useFetchServerStatus()
const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp([
'setUpEmail'
] as const);
/**
* This function sends the verification email and forwards a user to the next step.
@@ -63,7 +70,13 @@ export default function VerifyEmail() {
</div>
<div className="flex flex-col items-center justify-center w-full md:p-2 max-h-20 max-w-md mt-4 mx-auto text-sm">
<div className="text-l mt-6 m-8 px-8 py-3 text-lg">
<Button text="Continue" onButtonPressed={sendVerificationEmail} size="lg" />
<Button text="Continue" onButtonPressed={()=>{
if (serverDetails?.emailConfigured){
sendVerificationEmail()
} else {
handlePopUpOpen('setUpEmail');
}
}} size="lg" />
</div>
</div>
</div>
@@ -80,6 +93,11 @@ export default function VerifyEmail() {
</div>
</div>
)}
<EmailServiceSetupModal
isOpen={popUp.setUpEmail?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
/>
</div>
);
}

View File

@@ -13,6 +13,7 @@ import * as yup from 'yup';
import {
Button,
DeleteActionModal,
EmailServiceSetupModal,
EmptyState,
FormControl,
IconButton,
@@ -28,6 +29,7 @@ import {
THead,
Tr} from '@app/components/v2';
import { usePopUp } from '@app/hooks';
import { useFetchServerStatus } from '@app/hooks/api/serverDetails';
import { IncidentContact } from '@app/hooks/api/types';
type Props = {
@@ -50,9 +52,11 @@ export const OrgIncidentContactsTable = ({
isLoading
}: Props) => {
const [searchContact, setSearchContact] = useState('');
const {data: serverDetails } = useFetchServerStatus()
const { handlePopUpToggle, popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([
'addContact',
'removeContact'
'removeContact',
'setUpEmail'
] as const);
const {
@@ -92,7 +96,13 @@ export const OrgIncidentContactsTable = ({
<div>
<Button
leftIcon={<FontAwesomeIcon icon={faPlus} />}
onClick={() => handlePopUpOpen('addContact')}
onClick={() => {
if (serverDetails?.emailConfigured){
handlePopUpOpen('addContact');
} else {
handlePopUpOpen('setUpEmail');
}
}}
>
Add Contact
</Button>
@@ -180,6 +190,10 @@ export const OrgIncidentContactsTable = ({
onChange={(isOpen) => handlePopUpToggle('removeContact', isOpen)}
onDeleteApproved={onRemoveIncidentContact}
/>
<EmailServiceSetupModal
isOpen={popUp.setUpEmail?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
/>
</div>
);
};

View File

@@ -9,7 +9,7 @@ import * as yup from 'yup';
import {
Button,
DeleteActionModal,
EmptyState,
EmailServiceSetupModal, EmptyState,
FormControl,
IconButton,
Input,
@@ -28,6 +28,7 @@ import {
Tr,
UpgradePlanModal} from '@app/components/v2';
import { usePopUp } from '@app/hooks';
import { useFetchServerStatus } from '@app/hooks/api/serverDetails';
import { OrgUser, Workspace } from '@app/hooks/api/types';
type Props = {
@@ -64,10 +65,12 @@ export const OrgMembersTable = ({
}: Props) => {
const router = useRouter();
const [searchMemberFilter, setSearchMemberFilter] = useState('');
const {data: serverDetails } = useFetchServerStatus()
const { handlePopUpToggle, popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([
'addMember',
'removeMember',
'upgradePlan'
'upgradePlan',
'setUpEmail'
] as const);
const {
@@ -79,8 +82,8 @@ export const OrgMembersTable = ({
const onAddMember = async ({ email }: TAddMemberForm) => {
await onInviteMember(email);
handlePopUpClose('addMember');
reset();
handlePopUpClose('addMember');
reset();
};
const onRemoveOrgMemberApproved = async () => {
@@ -121,10 +124,14 @@ export const OrgMembersTable = ({
<Button
leftIcon={<FontAwesomeIcon icon={faPlus} />}
onClick={() => {
if (isMoreUserNotAllowed) {
handlePopUpOpen('upgradePlan');
if (serverDetails?.emailConfigured){
if (isMoreUserNotAllowed) {
handlePopUpOpen('upgradePlan');
} else {
handlePopUpOpen('addMember');
}
} else {
handlePopUpOpen('addMember');
handlePopUpOpen('setUpEmail');
}
}}
>
@@ -291,6 +298,10 @@ export const OrgMembersTable = ({
onOpenChange={(isOpen) => handlePopUpToggle('upgradePlan', isOpen)}
text="You can add custom environments if you switch to Infisical's Team plan."
/>
<EmailServiceSetupModal
isOpen={popUp.setUpEmail?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
/>
</div>
);
};

View File

@@ -1,7 +1,9 @@
import { useEffect, useState } from 'react';
import { useNotificationContext } from '@app/components/context/Notifications/NotificationProvider';
import { Checkbox } from '@app/components/v2';
import { Checkbox, EmailServiceSetupModal } from '@app/components/v2';
import { useFetchServerStatus } from '@app/hooks/api/serverDetails';
import { usePopUp } from '@app/hooks/usePopUp';
import { useGetUser } from '../../../../hooks/api';
import { User } from '../../../../hooks/api/types';
@@ -11,6 +13,11 @@ export const SecuritySection = () => {
const [isMfaEnabled, setIsMfaEnabled] = useState(false);
const { data: user } = useGetUser();
const { createNotification } = useNotificationContext();
const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp([
'setUpEmail'
] as const);
const {data: serverDetails } = useFetchServerStatus()
useEffect(() => {
if (user && typeof user.isMfaEnabled !== 'undefined') {
@@ -42,6 +49,7 @@ export const SecuritySection = () => {
}
return (
<>
<form>
<div className="mb-6 mt-2 flex w-full flex-col items-start rounded-md bg-white/5 px-6 pb-6 pt-2">
<p className="mb-4 mt-2 text-xl font-semibold">
@@ -52,12 +60,21 @@ export const SecuritySection = () => {
id="isTwoFAEnabled"
isChecked={isMfaEnabled}
onCheckedChange={(state) => {
toggleMfa(state as boolean);
if (serverDetails?.emailConfigured){
toggleMfa(state as boolean);
} else {
handlePopUpOpen('setUpEmail');
}
}}
>
Enable 2-factor authentication via your personal email.
</Checkbox>
</div>
</form>
<EmailServiceSetupModal
isOpen={popUp.setUpEmail?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
/>
</>
);
};