2022-07-30 10:35:35 +00:00
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
Center,
|
|
|
|
Flex,
|
|
|
|
Input,
|
|
|
|
InputGroup,
|
|
|
|
MenuItem,
|
|
|
|
Modal,
|
|
|
|
ModalBody,
|
|
|
|
ModalCloseButton,
|
|
|
|
ModalContent,
|
|
|
|
ModalFooter,
|
|
|
|
ModalHeader,
|
|
|
|
ModalOverlay,
|
|
|
|
Select,
|
2022-07-30 14:45:49 +00:00
|
|
|
Text,
|
2022-07-30 10:35:35 +00:00
|
|
|
useDisclosure,
|
|
|
|
useToast,
|
2022-08-09 06:11:51 +00:00
|
|
|
Alert,
|
|
|
|
AlertIcon,
|
|
|
|
Collapse,
|
|
|
|
Box,
|
|
|
|
TableContainer,
|
|
|
|
Table,
|
|
|
|
Thead,
|
|
|
|
Tr,
|
|
|
|
Th,
|
|
|
|
Tbody,
|
|
|
|
Td,
|
|
|
|
Code,
|
2022-07-30 10:35:35 +00:00
|
|
|
} from '@chakra-ui/react';
|
2022-08-09 06:11:51 +00:00
|
|
|
import { FaPlus, FaAngleDown, FaAngleUp } from 'react-icons/fa';
|
2022-07-30 10:35:35 +00:00
|
|
|
import { useClient } from 'urql';
|
2022-07-30 13:13:02 +00:00
|
|
|
import { Editor } from 'react-draft-wysiwyg';
|
2022-07-30 14:45:49 +00:00
|
|
|
import { EditorState, convertToRaw, Modifier } from 'draft-js';
|
2022-07-30 13:13:02 +00:00
|
|
|
import draftToHtml from 'draftjs-to-html';
|
|
|
|
import { stateFromHTML } from 'draft-js-import-html';
|
2022-07-30 10:35:35 +00:00
|
|
|
import {
|
|
|
|
UpdateModalViews,
|
|
|
|
EmailTemplateInputDataFields,
|
|
|
|
emailTemplateEventNames,
|
2022-08-01 08:37:06 +00:00
|
|
|
emailTemplateVariables,
|
2022-07-30 10:35:35 +00:00
|
|
|
} from '../constants';
|
|
|
|
import { capitalizeFirstLetter } from '../utils';
|
|
|
|
import { AddEmailTemplate, EditEmailTemplate } from '../graphql/mutation';
|
|
|
|
|
|
|
|
interface selectedEmailTemplateDataTypes {
|
|
|
|
[EmailTemplateInputDataFields.ID]: string;
|
|
|
|
[EmailTemplateInputDataFields.EVENT_NAME]: string;
|
|
|
|
[EmailTemplateInputDataFields.SUBJECT]: string;
|
|
|
|
[EmailTemplateInputDataFields.CREATED_AT]: number;
|
|
|
|
[EmailTemplateInputDataFields.TEMPLATE]: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface UpdateEmailTemplateInputPropTypes {
|
|
|
|
view: UpdateModalViews;
|
|
|
|
selectedTemplate?: selectedEmailTemplateDataTypes;
|
|
|
|
fetchEmailTemplatesData: Function;
|
|
|
|
}
|
|
|
|
|
2022-08-01 08:37:06 +00:00
|
|
|
interface templateVariableDataTypes {
|
|
|
|
text: string;
|
|
|
|
value: string;
|
2022-08-09 06:11:51 +00:00
|
|
|
description: string;
|
2022-08-01 08:37:06 +00:00
|
|
|
}
|
|
|
|
|
2022-07-30 10:35:35 +00:00
|
|
|
interface emailTemplateDataType {
|
|
|
|
[EmailTemplateInputDataFields.EVENT_NAME]: string;
|
|
|
|
[EmailTemplateInputDataFields.SUBJECT]: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface validatorDataType {
|
|
|
|
[EmailTemplateInputDataFields.SUBJECT]: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
const initTemplateData: emailTemplateDataType = {
|
2022-08-09 03:37:47 +00:00
|
|
|
[EmailTemplateInputDataFields.EVENT_NAME]: emailTemplateEventNames.Signup,
|
2022-07-30 10:35:35 +00:00
|
|
|
[EmailTemplateInputDataFields.SUBJECT]: '',
|
|
|
|
};
|
|
|
|
|
|
|
|
const initTemplateValidatorData: validatorDataType = {
|
|
|
|
[EmailTemplateInputDataFields.SUBJECT]: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
const UpdateEmailTemplate = ({
|
|
|
|
view,
|
|
|
|
selectedTemplate,
|
|
|
|
fetchEmailTemplatesData,
|
|
|
|
}: UpdateEmailTemplateInputPropTypes) => {
|
|
|
|
const client = useClient();
|
|
|
|
const toast = useToast();
|
|
|
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
|
|
|
const [loading, setLoading] = useState<boolean>(false);
|
2022-07-30 13:13:02 +00:00
|
|
|
const [editorState, setEditorState] = React.useState<EditorState>(
|
|
|
|
EditorState.createEmpty()
|
|
|
|
);
|
2022-08-01 08:37:06 +00:00
|
|
|
const [templateVariables, setTemplateVariables] = useState<
|
|
|
|
templateVariableDataTypes[]
|
|
|
|
>([]);
|
2022-07-30 10:35:35 +00:00
|
|
|
const [templateData, setTemplateData] = useState<emailTemplateDataType>({
|
|
|
|
...initTemplateData,
|
|
|
|
});
|
|
|
|
const [validator, setValidator] = useState<validatorDataType>({
|
|
|
|
...initTemplateValidatorData,
|
|
|
|
});
|
2022-07-30 13:13:02 +00:00
|
|
|
const onEditorStateChange = (editorState: EditorState) => {
|
|
|
|
setEditorState(editorState);
|
|
|
|
};
|
2022-08-09 06:11:51 +00:00
|
|
|
const [isDynamicVariableInfoOpen, setIsDynamicVariableInfoOpen] =
|
|
|
|
useState<boolean>(false);
|
|
|
|
|
2022-07-30 10:35:35 +00:00
|
|
|
const inputChangehandler = (inputType: string, value: any) => {
|
|
|
|
if (inputType !== EmailTemplateInputDataFields.EVENT_NAME) {
|
|
|
|
setValidator({
|
|
|
|
...validator,
|
|
|
|
[inputType]: value?.trim().length,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
setTemplateData({ ...templateData, [inputType]: value });
|
|
|
|
};
|
|
|
|
|
|
|
|
const validateData = () => {
|
2022-07-30 14:58:36 +00:00
|
|
|
const rawData: string = draftToHtml(
|
|
|
|
convertToRaw(editorState.getCurrentContent())
|
|
|
|
).trim();
|
2022-07-30 10:35:35 +00:00
|
|
|
return (
|
|
|
|
!loading &&
|
2022-07-30 14:58:36 +00:00
|
|
|
rawData &&
|
|
|
|
rawData !== '<p></p>' &&
|
|
|
|
rawData !== '<h1></h1>' &&
|
2022-07-30 10:35:35 +00:00
|
|
|
templateData[EmailTemplateInputDataFields.EVENT_NAME].length > 0 &&
|
|
|
|
templateData[EmailTemplateInputDataFields.SUBJECT].length > 0 &&
|
|
|
|
validator[EmailTemplateInputDataFields.SUBJECT]
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const saveData = async () => {
|
|
|
|
if (!validateData()) return;
|
|
|
|
setLoading(true);
|
|
|
|
const params = {
|
|
|
|
[EmailTemplateInputDataFields.EVENT_NAME]:
|
|
|
|
templateData[EmailTemplateInputDataFields.EVENT_NAME],
|
|
|
|
[EmailTemplateInputDataFields.SUBJECT]:
|
|
|
|
templateData[EmailTemplateInputDataFields.SUBJECT],
|
2022-07-30 13:13:02 +00:00
|
|
|
[EmailTemplateInputDataFields.TEMPLATE]: draftToHtml(
|
|
|
|
convertToRaw(editorState.getCurrentContent())
|
|
|
|
).trim(),
|
2022-07-30 10:35:35 +00:00
|
|
|
};
|
|
|
|
let res: any = {};
|
|
|
|
if (
|
|
|
|
view === UpdateModalViews.Edit &&
|
|
|
|
selectedTemplate?.[EmailTemplateInputDataFields.ID]
|
|
|
|
) {
|
|
|
|
res = await client
|
|
|
|
.mutation(EditEmailTemplate, {
|
|
|
|
params: {
|
|
|
|
...params,
|
|
|
|
id: selectedTemplate[EmailTemplateInputDataFields.ID],
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.toPromise();
|
|
|
|
} else {
|
|
|
|
res = await client.mutation(AddEmailTemplate, { params }).toPromise();
|
|
|
|
}
|
|
|
|
setLoading(false);
|
|
|
|
if (res.error) {
|
|
|
|
toast({
|
|
|
|
title: capitalizeFirstLetter(res.error.message),
|
|
|
|
isClosable: true,
|
|
|
|
status: 'error',
|
|
|
|
position: 'bottom-right',
|
|
|
|
});
|
|
|
|
} else if (
|
|
|
|
res.data?._add_email_template ||
|
|
|
|
res.data?._update_email_template
|
|
|
|
) {
|
|
|
|
toast({
|
|
|
|
title: capitalizeFirstLetter(
|
|
|
|
res.data?._add_email_template?.message ||
|
|
|
|
res.data?._update_email_template?.message
|
|
|
|
),
|
|
|
|
isClosable: true,
|
|
|
|
status: 'success',
|
|
|
|
position: 'bottom-right',
|
|
|
|
});
|
|
|
|
setTemplateData({
|
|
|
|
...initTemplateData,
|
|
|
|
});
|
|
|
|
setValidator({ ...initTemplateValidatorData });
|
|
|
|
fetchEmailTemplatesData();
|
|
|
|
}
|
|
|
|
view === UpdateModalViews.ADD && onClose();
|
|
|
|
};
|
|
|
|
const resetData = () => {
|
|
|
|
if (selectedTemplate) {
|
|
|
|
setTemplateData(selectedTemplate);
|
2022-07-30 13:13:02 +00:00
|
|
|
setEditorState(
|
|
|
|
EditorState.createWithContent(stateFromHTML(selectedTemplate.template))
|
|
|
|
);
|
2022-07-30 10:35:35 +00:00
|
|
|
} else {
|
|
|
|
setTemplateData({ ...initTemplateData });
|
2022-07-30 13:13:02 +00:00
|
|
|
setEditorState(EditorState.createEmpty());
|
2022-07-30 10:35:35 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
useEffect(() => {
|
|
|
|
if (
|
|
|
|
isOpen &&
|
|
|
|
view === UpdateModalViews.Edit &&
|
|
|
|
selectedTemplate &&
|
|
|
|
Object.keys(selectedTemplate || {}).length
|
|
|
|
) {
|
2022-07-30 13:13:02 +00:00
|
|
|
const { id, created_at, template, ...rest } = selectedTemplate;
|
2022-07-30 10:35:35 +00:00
|
|
|
setTemplateData(rest);
|
2022-07-30 13:13:02 +00:00
|
|
|
setEditorState(EditorState.createWithContent(stateFromHTML(template)));
|
2022-07-30 10:35:35 +00:00
|
|
|
}
|
|
|
|
}, [isOpen]);
|
2022-08-01 08:37:06 +00:00
|
|
|
useEffect(() => {
|
|
|
|
const updatedTemplateVariables = Object.entries(
|
|
|
|
emailTemplateVariables
|
2022-08-09 06:11:51 +00:00
|
|
|
).reduce((acc, [key, val]): any => {
|
2022-08-01 08:37:06 +00:00
|
|
|
if (
|
|
|
|
(templateData[EmailTemplateInputDataFields.EVENT_NAME] !==
|
2022-08-09 03:37:47 +00:00
|
|
|
emailTemplateEventNames['Verify Otp'] &&
|
2022-08-09 06:11:51 +00:00
|
|
|
val === emailTemplateVariables.otp) ||
|
2022-08-01 08:37:06 +00:00
|
|
|
(templateData[EmailTemplateInputDataFields.EVENT_NAME] ===
|
2022-08-09 03:37:47 +00:00
|
|
|
emailTemplateEventNames['Verify Otp'] &&
|
2022-08-09 06:11:51 +00:00
|
|
|
val === emailTemplateVariables.verification_url)
|
2022-08-01 08:37:06 +00:00
|
|
|
) {
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
return [
|
|
|
|
...acc,
|
|
|
|
{
|
2022-08-09 06:11:51 +00:00
|
|
|
text: key,
|
|
|
|
value: val.value,
|
|
|
|
description: val.description,
|
2022-08-01 08:37:06 +00:00
|
|
|
},
|
|
|
|
];
|
|
|
|
}, []);
|
|
|
|
setTemplateVariables(updatedTemplateVariables);
|
|
|
|
}, [templateData[EmailTemplateInputDataFields.EVENT_NAME]]);
|
2022-08-09 06:11:51 +00:00
|
|
|
|
2022-07-30 10:35:35 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{view === UpdateModalViews.ADD ? (
|
|
|
|
<Button
|
|
|
|
leftIcon={<FaPlus />}
|
|
|
|
colorScheme="blue"
|
|
|
|
variant="solid"
|
|
|
|
onClick={onOpen}
|
|
|
|
isDisabled={false}
|
|
|
|
size="sm"
|
|
|
|
>
|
|
|
|
<Center h="100%">Add Template</Center>{' '}
|
|
|
|
</Button>
|
|
|
|
) : (
|
|
|
|
<MenuItem onClick={onOpen}>Edit</MenuItem>
|
|
|
|
)}
|
|
|
|
<Modal isOpen={isOpen} onClose={onClose} size="3xl">
|
|
|
|
<ModalOverlay />
|
|
|
|
<ModalContent>
|
|
|
|
<ModalHeader>
|
|
|
|
{view === UpdateModalViews.ADD
|
|
|
|
? 'Add New Email Template'
|
|
|
|
: 'Edit Email Template'}
|
|
|
|
</ModalHeader>
|
|
|
|
<ModalCloseButton />
|
|
|
|
<ModalBody>
|
|
|
|
<Flex
|
|
|
|
flexDirection="column"
|
|
|
|
border="1px"
|
|
|
|
borderRadius="md"
|
|
|
|
borderColor="gray.200"
|
|
|
|
p="5"
|
|
|
|
>
|
2022-08-09 06:11:51 +00:00
|
|
|
<Alert
|
|
|
|
status="info"
|
|
|
|
onClick={() =>
|
|
|
|
setIsDynamicVariableInfoOpen(!isDynamicVariableInfoOpen)
|
|
|
|
}
|
|
|
|
borderRadius="5"
|
|
|
|
marginY={5}
|
|
|
|
cursor="pointer"
|
|
|
|
fontSize="sm"
|
|
|
|
>
|
|
|
|
<AlertIcon />
|
|
|
|
<Flex
|
|
|
|
width="100%"
|
|
|
|
justifyContent="space-between"
|
|
|
|
alignItems="center"
|
|
|
|
>
|
|
|
|
<Box width="85%">
|
|
|
|
<b>Note:</b> You can add set of dynamic variables to subject
|
|
|
|
and email body. Click here to see the set of dynamic
|
|
|
|
variables.
|
|
|
|
</Box>
|
|
|
|
{isDynamicVariableInfoOpen ? <FaAngleUp /> : <FaAngleDown />}
|
|
|
|
</Flex>
|
|
|
|
</Alert>
|
|
|
|
<Collapse
|
|
|
|
style={{
|
|
|
|
width: '100%',
|
|
|
|
}}
|
|
|
|
in={isDynamicVariableInfoOpen}
|
|
|
|
>
|
|
|
|
<TableContainer
|
|
|
|
background="gray.100"
|
|
|
|
borderRadius={5}
|
|
|
|
height={200}
|
|
|
|
width="100%"
|
|
|
|
overflowY="auto"
|
|
|
|
overflowWrap="break-word"
|
|
|
|
>
|
|
|
|
<Table variant="simple">
|
|
|
|
<Thead>
|
|
|
|
<Tr>
|
|
|
|
<Th>Variable</Th>
|
|
|
|
<Th>Description</Th>
|
|
|
|
</Tr>
|
|
|
|
</Thead>
|
|
|
|
<Tbody>
|
|
|
|
{templateVariables.map((i) => (
|
|
|
|
<Tr key={i.text}>
|
|
|
|
<Td>
|
|
|
|
<Code fontSize="sm">{`{{${i.text}}}`}</Code>
|
|
|
|
</Td>
|
|
|
|
<Td>
|
|
|
|
<Text
|
|
|
|
size="sm"
|
|
|
|
fontSize="sm"
|
|
|
|
overflowWrap="break-word"
|
|
|
|
width="100%"
|
|
|
|
>
|
|
|
|
{i.description}
|
|
|
|
</Text>
|
|
|
|
</Td>
|
|
|
|
</Tr>
|
|
|
|
))}
|
|
|
|
</Tbody>
|
|
|
|
</Table>
|
|
|
|
</TableContainer>
|
|
|
|
</Collapse>
|
2022-07-30 10:35:35 +00:00
|
|
|
<Flex
|
|
|
|
width="100%"
|
|
|
|
justifyContent="space-between"
|
|
|
|
alignItems="center"
|
|
|
|
marginBottom="2%"
|
|
|
|
>
|
|
|
|
<Flex flex="1">Event Name</Flex>
|
|
|
|
<Flex flex="3">
|
|
|
|
<Select
|
|
|
|
size="md"
|
|
|
|
value={
|
|
|
|
templateData[EmailTemplateInputDataFields.EVENT_NAME]
|
|
|
|
}
|
|
|
|
onChange={(e) =>
|
|
|
|
inputChangehandler(
|
|
|
|
EmailTemplateInputDataFields.EVENT_NAME,
|
|
|
|
e.currentTarget.value
|
|
|
|
)
|
|
|
|
}
|
|
|
|
>
|
|
|
|
{Object.entries(emailTemplateEventNames).map(
|
|
|
|
([key, value]: any) => (
|
|
|
|
<option value={value} key={key}>
|
|
|
|
{key}
|
|
|
|
</option>
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
</Select>
|
|
|
|
</Flex>
|
|
|
|
</Flex>
|
|
|
|
<Flex
|
|
|
|
width="100%"
|
|
|
|
justifyContent="start"
|
|
|
|
alignItems="center"
|
|
|
|
marginBottom="5%"
|
|
|
|
>
|
|
|
|
<Flex flex="1">Subject</Flex>
|
|
|
|
<Flex flex="3">
|
|
|
|
<InputGroup size="md">
|
|
|
|
<Input
|
|
|
|
pr="4.5rem"
|
|
|
|
type="text"
|
|
|
|
placeholder="Subject Line"
|
|
|
|
value={templateData[EmailTemplateInputDataFields.SUBJECT]}
|
|
|
|
isInvalid={
|
|
|
|
!validator[EmailTemplateInputDataFields.SUBJECT]
|
|
|
|
}
|
|
|
|
onChange={(e) =>
|
|
|
|
inputChangehandler(
|
|
|
|
EmailTemplateInputDataFields.SUBJECT,
|
|
|
|
e.currentTarget.value
|
|
|
|
)
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</InputGroup>
|
|
|
|
</Flex>
|
|
|
|
</Flex>
|
|
|
|
<Flex
|
|
|
|
width="100%"
|
2022-07-30 14:45:49 +00:00
|
|
|
justifyContent="space-between"
|
2022-07-30 10:35:35 +00:00
|
|
|
alignItems="center"
|
|
|
|
marginBottom="2%"
|
|
|
|
>
|
|
|
|
<Flex>Template Body</Flex>
|
2022-07-30 14:45:49 +00:00
|
|
|
<Text
|
|
|
|
style={{
|
|
|
|
fontSize: 14,
|
|
|
|
}}
|
|
|
|
color="gray.400"
|
|
|
|
>{`To select dynamic variables open curly braces "{"`}</Text>
|
2022-07-30 10:35:35 +00:00
|
|
|
</Flex>
|
2022-07-30 13:13:02 +00:00
|
|
|
<Editor
|
|
|
|
editorState={editorState}
|
|
|
|
onEditorStateChange={onEditorStateChange}
|
|
|
|
editorStyle={{
|
|
|
|
border: '1px solid #d9d9d9',
|
|
|
|
borderRadius: '5px',
|
|
|
|
marginTop: '2%',
|
2022-08-09 06:11:51 +00:00
|
|
|
height: '30vh',
|
2022-07-30 13:13:02 +00:00
|
|
|
}}
|
2022-07-30 14:45:49 +00:00
|
|
|
mention={{
|
|
|
|
separator: ' ',
|
|
|
|
trigger: '{',
|
2022-08-01 08:37:06 +00:00
|
|
|
suggestions: templateVariables,
|
2022-07-30 14:45:49 +00:00
|
|
|
}}
|
2022-07-30 13:13:02 +00:00
|
|
|
/>
|
2022-08-09 06:11:51 +00:00
|
|
|
<Alert status="info" marginY={5} borderRadius={5}>
|
|
|
|
<AlertIcon />
|
|
|
|
<Box fontSize="sm">
|
|
|
|
<b>Note:</b> In order to use dynamic variables with link and
|
|
|
|
images you can put them as part of URL in editor section.
|
|
|
|
</Box>
|
|
|
|
</Alert>
|
2022-07-30 10:35:35 +00:00
|
|
|
</Flex>
|
|
|
|
</ModalBody>
|
|
|
|
<ModalFooter>
|
|
|
|
<Button
|
|
|
|
variant="outline"
|
|
|
|
onClick={resetData}
|
|
|
|
isDisabled={loading}
|
|
|
|
marginRight="5"
|
|
|
|
>
|
|
|
|
Reset
|
|
|
|
</Button>
|
|
|
|
<Button
|
|
|
|
colorScheme="blue"
|
|
|
|
variant="solid"
|
|
|
|
isLoading={loading}
|
|
|
|
onClick={saveData}
|
|
|
|
isDisabled={!validateData()}
|
|
|
|
>
|
|
|
|
<Center h="100%" pt="5%">
|
|
|
|
Save
|
|
|
|
</Center>
|
|
|
|
</Button>
|
|
|
|
</ModalFooter>
|
|
|
|
</ModalContent>
|
|
|
|
</Modal>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default UpdateEmailTemplate;
|