setOpen(false)}\n submit={deleteTemplate}\n title=\"Delete\"\n text=\"Do you want to remove this template ?\"\n canceltext=\"Cancel\"\n submitText=\"Delete\"\n />\n \n \n \n \n navigate(`/app/templates/${id}/edit`)}>\n \n \n \n Edit\n \n \n \n \n \n Duplicate\n \n \n \n \n \n Switch to {mod === 'simple' ? 'Advanced' : 'Simple'} mod\n \n setOpen(true)}>\n \n \n \n Delete\n \n \n >\n );\n};\nexport default Actions;\n","import { Container, CircularProgress } from '@mui/material';\nimport React from 'react';\n\nconst style = {\n root: {\n margin: 'auto',\n textAlign: 'center',\n marginBottom: '4px',\n marginTop: '4px',\n },\n};\n\nconst Loader = () => {\n return (\n \n \n \n );\n};\nexport default Loader;\n","import React, { useState } from 'react';\nimport {\n styled,\n Button,\n Box,\n CircularProgress,\n Alert,\n Container,\n TableHead,\n TableBody,\n TableRow,\n TableCell,\n TableSortLabel,\n TableContainer,\n Table,\n TablePagination,\n} from '@mui/material';\nimport AddIcon from '@mui/icons-material/Add';\nimport RefreshIcon from '@mui/icons-material/Refresh';\nimport useAxios from 'axios-hooks';\nimport { useNavigate } from 'react-router';\nimport { visuallyHidden } from '@mui/utils';\nimport Moment from 'react-moment';\nimport Title from '../../../components/Title';\nimport Actions from '../components/Actions';\nimport Loader from '../../../components/Loader';\n\nconst style = {\n button: {\n marginLeft: '10px',\n },\n};\n\nconst Action = styled(Container)(({ theme }) => ({\n marginBottom: '14px',\n textAlign: 'end',\n padding: theme.spacing(1),\n [theme.breakpoints.down('md')]: {\n textAlign: 'start',\n },\n [theme.breakpoints.up('md')]: {\n textAlign: 'end',\n },\n}));\n\nconst TemplatesList = () => {\n const navigate = useNavigate();\n const [order, setOrder] = useState('desc');\n const [orderBy, setOrderBy] = useState('updated_at');\n const [page, setPage] = useState(0);\n const [rowsPerPage, setRowsPerPage] = useState(25);\n const [{ data, loading, error }, refetch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/templates`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const headCells = [\n {\n id: 'id',\n numeric: false,\n disablePadding: false,\n label: '#',\n },\n {\n id: 'title',\n numeric: false,\n disablePadding: false,\n label: 'Title',\n },\n {\n id: 'app',\n numeric: false,\n disablePadding: false,\n label: 'Application',\n },\n {\n id: 'mod',\n numeric: false,\n disablePadding: false,\n label: 'Mode',\n },\n {\n id: 'documents_count',\n numeric: false,\n disablePadding: false,\n label: 'Nb Docs',\n },\n {\n id: 'updated_at',\n numeric: false,\n disablePadding: false,\n label: 'Updated At',\n },\n {\n id: 'action',\n numeric: true,\n disablePadding: false,\n label: 'Actions',\n },\n ];\n\n /* eslint-disable-next-line */\n const descendingComparator = (a, b, orderBy) => {\n if (b[orderBy] < a[orderBy]) {\n return -1;\n }\n if (b[orderBy] > a[orderBy]) {\n return 1;\n }\n return 0;\n };\n\n /* eslint-disable-next-line */\n const getComparator = (order, orderBy) => {\n return order === 'desc'\n ? (a, b) => descendingComparator(a, b, orderBy)\n : (a, b) => -descendingComparator(a, b, orderBy);\n };\n\n const stableSort = (array, comparator) => {\n const stabilizedThis = array.map((el, index) => [el, index]);\n stabilizedThis.sort((a, b) => {\n /* eslint-disable-next-line */\n const order = comparator(a[0], b[0]);\n if (order !== 0) {\n return order;\n }\n return a[1] - b[1];\n });\n return stabilizedThis.map((el) => el[0]);\n };\n\n const handleChangePage = (event, newPage) => {\n setPage(newPage);\n };\n\n const handleChangeRowsPerPage = (event) => {\n setRowsPerPage(parseInt(event.target.value, 10));\n setPage(0);\n };\n\n const handleRequestSort = (event, property) => {\n const isAsc = orderBy === property && order === 'asc';\n setOrder(isAsc ? 'desc' : 'asc');\n setOrderBy(property);\n };\n\n const createSortHandler = (property) => (event) => {\n handleRequestSort(event, property);\n };\n\n return (\n \n \n \n : }\n onClick={() => refetch()}\n >\n Refresh\n \n }\n onClick={() => navigate('/app/templates/initialize')}\n >\n Create a template\n \n \n {error && {error} }\n {loading && }\n {!loading && (\n \n {data.length === 0 && (\n \n Get started, make your first PDF template\n \n )}\n \n \n \n \n {headCells.map((headCell) => (\n \n \n {headCell.label}\n {orderBy === headCell.id ? (\n \n {order === 'desc' ? 'sorted descending' : 'sorted ascending'}\n \n ) : null}\n \n \n ))}\n \n \n \n {stableSort(data, getComparator(order, orderBy))\n .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)\n .map((row) => {\n return (\n \n {row.id} \n {row.title} \n {row.app} \n {row.mod} \n {row.documents_count} \n \n {row.updated_at} \n \n \n \n \n \n );\n })}\n \n
\n \n \n \n )}\n \n );\n};\nexport default TemplatesList;\n","export const PAGE_SIZES = [\n { format: 'A0', size: '841 x 1189 mm' },\n { format: 'A1', size: '594 x 841 mm' },\n { format: 'A2', size: '420 x 594 mm' },\n { format: 'A3', size: '297 x 420 mm' },\n { format: 'A4', size: '210 x 297 mm' },\n { format: 'A5', size: '148 x 210 mm\t' },\n { format: 'A6', size: '105 x 148 mm\t' },\n { format: 'A7', size: '74 x 105 mm\t' },\n { format: 'A8', size: '52 x 74 mm' },\n { format: 'A9', size: '37 x 52 mm\t' },\n];\nexport default PAGE_SIZES;\n","import React, { useState } from 'react';\nimport {\n Grid,\n Tabs,\n FormControl,\n MenuItem,\n TextField,\n Box,\n Typography,\n Tab,\n useTheme,\n InputLabel,\n Select,\n FormHelperText,\n} from '@mui/material';\nimport PropTypes from 'prop-types';\nimport SwipeableViews from 'react-swipeable-views';\nimport AceEditor from 'react-ace';\nimport { CKEditor } from '@ckeditor/ckeditor5-react';\nimport Cookies from 'js-cookie';\n// import ClassicEditor from '../../../../components/Editor/ckeditor';\n// import ClassicEditor from 'ckeditor5/packages/ckeditor5-build-classic';\nimport FullEditor from 'ckeditor5-build-full';\nimport { PAGE_SIZES } from '../../../../utilities/page_size';\n/* eslint-disable-next-line */\nimport '../../../../components/Themes/index.js';\n\nconst TabPanel = (props) => {\n const { children, value, index, ...other } = props;\n\n return (\n \n {value === index && (\n \n {children} \n \n )}\n
\n );\n};\n\nTabPanel.propTypes = {\n children: PropTypes.node.isRequired,\n index: PropTypes.number.isRequired,\n value: PropTypes.number.isRequired,\n};\n\nconst a11yProps = (index) => {\n return {\n id: `full-width-tab-${index}`,\n 'aria-controls': `full-width-tabpanel-${index}`,\n };\n};\n\nconst style = {\n select: {\n marginTop: '16px',\n },\n actions: {\n margin: 'auto',\n textAlign: 'right',\n paddingBottom: '12px',\n },\n};\n\nconst SimpleTemplate = ({ template, setTemplate, preview, setHtml, html }) => {\n const [tab, setTab] = useState(0);\n const theme = useTheme();\n\n const handleChangeTab = (event, value) => {\n setTab(value);\n };\n\n const handleChangeIndex = (index) => {\n setTab(index);\n };\n\n const editorChange = (name, value) => {\n setTemplate({ ...template, [name]: value });\n };\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setTemplate({ ...template, [name]: value });\n };\n\n return (\n \n \n \n \n \n \n \n \n \n \n \n {html && template.id && (\n {\n editor &&\n editor.editing.view.change((writer) => {\n writer.setStyle(\n 'min-height',\n '500px',\n editor.editing.view.document.getRoot()\n );\n });\n }} */\n onChange={(_, editor) => {\n const data = editor.getData();\n console.log(data);\n setHtml(data || '
');\n }}\n config={{\n simpleUpload: {\n uploadUrl: `${process.env.REACT_APP_API_URL}/templates/upload/${template.id}`,\n headers: { Authorization: `Bearer ${Cookies.get('token')}` },\n },\n image: {\n resizeUnit: 'px',\n resizeOptions: [\n {\n name: 'resizeImage:original',\n label: 'Original',\n value: null,\n },\n {\n name: 'resizeImage:100',\n label: '100px',\n value: '100',\n },\n {\n name: 'resizeImage:200',\n label: '200px',\n value: '200',\n },\n ],\n },\n toolbar: {\n removeItems: ['restrictedEditingException', 'mediaEmbed'],\n shouldNotGroupWhenFull: true,\n },\n }}\n />\n )}\n \n \n editorChange('sample', value)}\n name=\"sample\"\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n highlightActiveLine: true,\n showLineNumbers: true,\n }}\n />\n \n \n \n \n \n \n Orientation \n \n Portrait \n Landscape \n \n \n \n Format \n \n {PAGE_SIZES.map((row) => (\n {row.format} \n ))}\n \n \n {PAGE_SIZES.filter((row) => row.format === template.page_size).pop().size}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n};\nexport default SimpleTemplate;\n","import React, { useState } from 'react';\nimport {\n Grid,\n Tabs,\n FormControl,\n MenuItem,\n TextField,\n Box,\n Typography,\n Tab,\n useTheme,\n InputLabel,\n FormHelperText,\n Select,\n} from '@mui/material';\nimport PropTypes from 'prop-types';\nimport SwipeableViews from 'react-swipeable-views';\nimport AceEditor from 'react-ace';\nimport Cookies from 'js-cookie';\n/* eslint-disable-next-line */\nimport '../../../../components/Themes/index.js';\nimport { PAGE_SIZES } from '../../../../utilities/page_size';\n\nconst TabPanel = (props) => {\n const { children, value, index, ...other } = props;\n\n return (\n \n {value === index && (\n \n {children} \n \n )}\n
\n );\n};\n\nTabPanel.propTypes = {\n children: PropTypes.node.isRequired,\n index: PropTypes.number.isRequired,\n value: PropTypes.number.isRequired,\n};\n\nconst a11yProps = (index) => {\n return {\n id: `full-width-tab-${index}`,\n 'aria-controls': `full-width-tabpanel-${index}`,\n };\n};\n\nconst AdvancedTemplate = ({ template, setTemplate, preview, setHtml, html }) => {\n const [tab, setTab] = useState(0);\n const theme = useTheme();\n\n const handleChangeTab = (event, value) => {\n setTab(value);\n };\n\n const handleChangeIndex = (index) => {\n setTab(index);\n };\n\n const editorChange = (name, value) => {\n if (name === 'html') {\n setHtml(value);\n } else {\n setTemplate({ ...template, [name]: value });\n }\n };\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setTemplate({ ...template, [name]: value });\n };\n\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n editorChange('html', value)}\n name=\"html\"\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n highlightActiveLine: true,\n showLineNumbers: true,\n }}\n />\n \n \n editorChange('css', value)}\n name=\"css\"\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n highlightActiveLine: true,\n showLineNumbers: true,\n }}\n />\n \n \n editorChange('sample', value)}\n name=\"sample\"\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n highlightActiveLine: true,\n showLineNumbers: true,\n }}\n />\n \n \n \n \n \n \n Orientation \n \n Portrait \n Landscape \n \n \n \n Format \n \n {PAGE_SIZES.map((row) => (\n {row.format} \n ))}\n \n \n {PAGE_SIZES.filter((row) => row.format === template.page_size).pop().size}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n};\nexport default AdvancedTemplate;\n","import React, { useState, useEffect } from 'react';\nimport { Box, Grid, Button, Divider, styled, Alert } from '@mui/material';\nimport { useParams } from 'react-router-dom';\n// import 'ace-builds/src-noconflict/mode-html';\n// import 'ace-builds/src-noconflict/ext-language_tools';\nimport useAxios from 'axios-hooks';\nimport { Worker, Viewer } from '@react-pdf-viewer/core';\nimport '@react-pdf-viewer/core/lib/styles/index.css';\nimport SaveIcon from '@mui/icons-material/Save';\nimport VisibilityIcon from '@mui/icons-material/Visibility';\nimport VisibilityOffIcon from '@mui/icons-material/VisibilityOff';\nimport BugReportIcon from '@mui/icons-material/BugReport';\n/* eslint-disable-next-line */\nimport { html_beautify } from 'js-beautify';\nimport SimpleTemplate from '../components/Simple';\nimport AdvancedTemplate from '../components/Advanced';\nimport { useFeedback } from '../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK } from '../../../utilities/feedback';\nimport Title from '../../../components/Title';\n\nconst style = {\n button: {\n marginLeft: '10px',\n },\n};\n\nconst Action = styled(Box)(({ theme }) => ({\n margin: 'auto',\n textAlign: 'right',\n paddingBottom: '12px',\n [theme.breakpoints.down('md')]: {\n textAlign: 'start',\n },\n [theme.breakpoints.up('md')]: {\n textAlign: 'end',\n },\n}));\n\nconst TemplateNew = () => {\n const { id } = useParams();\n const [, setFeedback] = useFeedback();\n const [rand, setRand] = useState(Math.random());\n const [preview, setPreview] = useState(true);\n const [html, setHtml] = useState('');\n const [template, setTemplate] = useState({\n title: '',\n mod: 'simple',\n html: '',\n css: '',\n sample: '',\n orientation: 'Portrait',\n page_size: 'A4',\n margin_top: 10,\n margin_bottom: 10,\n margin_left: 10,\n margin_right: 10,\n });\n\n const [, executePost] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/templates`,\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n manual: true,\n }\n );\n\n const [, executePatch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/templates/${id}`,\n method: 'PATCH',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const [, fetchTemplate] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/templates/${id}/edit`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const createTemplate = () => {\n executePost({ data: template }).then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Template created',\n })\n );\n });\n };\n\n const updateTemplate = () => {\n executePatch({ data: { ...template, html } }).then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Template updated',\n })\n );\n setRand(Math.random());\n });\n };\n\n const createOrUpdate = () => (id ? updateTemplate() : createTemplate());\n\n useEffect(() => {\n if (id)\n fetchTemplate().then(({ data }) => {\n setTemplate({ ...template, ...data });\n setHtml(html_beautify(data.html, { indent_size: 2, type: 'html' }));\n });\n }, [id]);\n\n return (\n \n \n \n }\n onClick={() => createOrUpdate()}\n >\n Save\n \n : }\n onClick={() => setPreview(!preview)}\n >\n Preview\n \n }\n onClick={() =>\n window.open(\n `${process.env.REACT_APP_API_URL}/templates/sample/${id}/html?rand=${rand}`,\n '_blank'\n )\n }\n >\n Debug\n \n \n \n \n {template.mod === 'simple' ? (\n \n ) : (\n \n )}\n \n {preview && (\n <>\n \n \n \n Invalid data Payload. }\n />\n \n \n >\n )}\n \n \n );\n};\nexport default TemplateNew;\n","export default __webpack_public_path__ + \"static/media/html.485b6e20.png\";","import React, { useState } from 'react';\nimport {\n Box,\n Container,\n Button,\n TextField,\n Grid,\n Paper,\n Typography,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n FormHelperText,\n styled,\n} from '@mui/material';\nimport useAxios from 'axios-hooks';\nimport { useNavigate } from 'react-router';\nimport Title from '../../../components/Title';\nimport { useFeedback } from '../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK } from '../../../utilities/feedback';\nimport htmlIcon from '../../../assets/html.png';\nimport editorIcon from '../../../assets/writer.png';\n\nconst style = {\n root: {\n marginTop: '40px',\n },\n mod: {\n display: 'inline-flex',\n marginBottom: '8px',\n },\n paper: {\n opacity: 0.5,\n },\n active: {\n opacity: 1,\n },\n img: {\n width: '80%',\n margin: '8px',\n },\n};\n\nconst Mod = styled(Paper)(({ theme }) => ({\n width: '23%',\n marginRight: '8px',\n textAlign: 'center',\n cursor: 'pointer',\n padding: theme.spacing(1),\n [theme.breakpoints.down('md')]: {\n width: '50%',\n },\n [theme.breakpoints.up('md')]: {\n width: '23%',\n },\n}));\n\nconst TemplateInit = () => {\n const [, setFeedback] = useFeedback();\n const navigate = useNavigate();\n const [template, setTemplate] = useState({\n title: '',\n app_id: null,\n mod: 'simple',\n });\n const [errors, setErrors] = useState({\n title: '',\n app_id: '',\n });\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setTemplate((prevTemplate) => ({ ...prevTemplate, [name]: value }));\n };\n\n const handleMod = (value) => {\n setTemplate({ ...template, mod: value });\n };\n\n const [{ data }] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/apps`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const [, executePost] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/templates`,\n method: 'POST',\n },\n {\n useCache: false,\n manual: true,\n }\n );\n\n const createTemplate = () => {\n executePost({ data: template })\n .then((result) => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: \"Template created. Let's go for customization\",\n })\n );\n navigate(`/app/templates/${result.data.id}/edit`);\n })\n .catch((err) => {\n setErrors(err.response.data);\n });\n };\n\n const validTemplate = template.title !== '';\n\n return (\n \n \n \n \n \n \n \n \n \n \n Application \n \n {data &&\n data.map((row) => {\n return {row.name} ;\n })}\n \n {errors.app_id} \n \n \n \n \n \n handleMod('advanced')}\n >\n \n From HTML/CSS \n \n handleMod('simple')}\n >\n \n From WYSIWYG Editor \n \n \n \n \n \n Create my template\n \n \n \n \n \n );\n};\nexport default TemplateInit;\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7d1rlJ1Xfd/x3z7XuUlz0egykrEcS7GRzMWk5E0xbrpW6FqUxpYBCVsuMeVi2rXCJQS6oDfcvEtIWAS3zTI0xoZaCoYUL5fkRchqWiRIV7ABJ77JkQQI27JuMyONLjNzznl2X4yOGMmSZs45z7P3fp79/bwCXWb/R7b1+5397Od5JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwmV8D9Are8emNUrMrTLJTbLmtTK6QbKjkhmRNCSp6ntGAIhUQ9JpyU5LZkrSPhn7vKyekTF7zLcOHPU9YMxyWQDsO6//VVndJWveJukm5fT7AICIWUnPSPYvlWi3efzgE74Hik1ugtO+ffNK1ey9Mnq/pC2+5wEApOpZWX1FtvKAeXzfjO9hYhB8AbDbrxnTfN/HZOxHJI36ngcAkKkpyXxRjfk/Mn9+aMr3MEUWbAGwktHtm94roz+QtNr3PAAAl8yklPyubj54v7lPie9piijIAmBv27RZJT0s6R/7ngUA4JHV92TMPeax/Qd8j1I0Jd8DXMrevukOlfQDEf4AAKO3SPZH9o5Nd/oepWiC2QGw96mkH2/+Q8l+3PcsAIAQ2c/r5oOf4pJAOoIoAHb7TTU1Zh+SdJfvWQAAITO7tGb4feZLTzZ8T5J33gvA+fD/lqR/7nsWAEAOWP251o7cQQnojdczAFYyas5+WYQ/AGC5jN6ho9MP2/vCO8eWJ37/8LZt/rysftPrDACAPLpLT236Pd9D5Jm3SwD2js3bZe2jvtYHABSB3WkeO7jb9xR55KUA2G2bN0n2SUnDPtYHABTGSZXLv2L+7IWDvgfJG+eXAKxkJPtVEf4AgN4Nq9V6yAZwqD1v3J8BuH3zB8RDfgAA6Xmr7tjEebIOOW1Mdvs1Y2rU90kad7kuAKDwjkqtG81jP532PUheuN0BaNQ/LsIfAJC+NTKlj/oeIk+c7QDYt29eqbr9qXilLwAgE2ZSSfk68/i+Gd+T5IG7HYCavVeEPwAgM3ZM5daHfE+RF+4KgNE9ztYCAMTJ2g/4HiEvnBQA+87rf1XS61ysBQCI2lZ72+Y3+R4iD9zsAFje8gcAcKRsd/oeIQ8cXQIw/8zNOgCA6Fn7675HyIPM7wKwd2xaI6tXXKzVjcknehtr7M2W9QEgLFat8hrzv1447nuQkGW/A5CYWxVo+AMACsmo0rzV9xChy74AGA7/AQAcs+Ym3yOELvsCYO2Nma8BAMBi1pA9S3CxA/DLma8BAMBixt7ge4TQubgLgGf/AwAcs2TPEhwUALMi+zUAAFiM7FmKgwJgh7JfAwCAi1AAluDiEkDNwRoAACxW9z1A6Ny9DAgAAASDAgAAQIQoAAAARIgCAABAhCgAAABEiAIAAECEKAAAAESo4nsA33y/zz729QEAfrADAABAhCgAAABEiAIAAECEKAAAAESIAgAAQIQoAAAARIgCAABAhKJ/DgAAoJhOXLO5pwedjL3ZNiSdluy0ZKYk7ZOxz8vqGRmzx3zrwNF0JvWDAgAAwOVVJY1KZlTSL0n6FVmz8DNW1m7b9Ixk/1KJdpvHDz7hcc6umKwXsNs28ag5AIBzk0/0FnEdPin1WVl9RbbygHl830xPCzvCGQAAAHq3VUafU6n5M7tt8332HdeO+h5oKRQAAADSMyrZz6pa22+3Xf8xe1+4ORvsYAAA5Jcdk8wX9KNN37XbNm/yPc3lUAAAAMiK0Vsk+yN7x6Y7fY9yKQoAAADZWiGr3Xbb9X8Y0iWBYAYBAKDYzCf0481fs/f+o6rvSSQKAAAADtmdOjL9rRBKAAUAAACXjN6ho9MP+74cQAEAAMC9u/TUpt/zOQAFAAAAH6w+abddf5ev5SkAAAB4Y/7YvuuG632sTAEAAMCfYbVaD1kH7+a5FAUAAAC/3qo7Nv2m60Uzbxw7Hz3M2wABAM7d/4m39vT7O3wbYK+OSq0bzWM/nXa1IDsAAAD4t0am9FGXC1IAAAAIgS19zN524wpXy1EAAAAIgh1TufUhV6tRAAAACIW1H3C1FAUAAIBwbLW3bX6Ti4UoAAAAhKRsd7pYhgIAAEBIrP11F8tQAAAACIp5o/2NG8azXoUCAABAWIwqzVuzXoQCAABAaKy5KeslKAAAAITGmhuzXoICAABAaIy9IeslKAAAAATHcggQAID4mMzfCUABAAAgPBQAAAAiVM96AQoAAAARogAAABAhCgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARogAAABAhCgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARogAAABAhCgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARogAAABAhCgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARogAAABAhCgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARqvgewLdHWv/C9wjIsbvL3/a6/t7nDvf0+2/ZMuF1feRbr//+ZG3bf/rfPf3+14xUU5qkS49l++fLDgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARogAAABAhCgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARogAAABAhCgAAABGiAAAAECEKAAAAEar4HgBA93y/j933+gC6xw4AAAARogAAABAhCgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARogAAABAhCgAAABGiAAAAECEKAAAAEaIAAAAQIQoAAAARogAAABAhCgAAABGq+B4AQPf2PnfY9wjIsVu2TPgeAR6xAwAAQIQoAAAARIgCAABAhCgAAABEiAIAAECEKAAAAESIAgAAQIQoAAAARIgCAAAopFrJ6kM3ntPGoZbvUYJEAQAAFE7FWP3r157VG8ca+q2tZykBl0EBAAAUSsVYvfvaGd0wvBD6/WWrj1ACXoUCAAAojHb4bxxoXPTjfZSAV6EAAAAK4Urh30YJuBgFAACQe0uFfxsl4BcoAACAXFtu+LdRAhZUfA8AoHu8zx2x6zT829ol4P5nB/Sz0+WMpgsbOwAAgFzqNvzbYt8JoAAAAHKn1/Bvi7kEUAAAALmSVvi3xVoCKAAAgNxIO/zbYiwBFAAAQC5kFf5tsZUACgAAIHhZh39bTCWAAgAACJqr8G9rl4CJ/qaT9XyhAAAAguU6/Nv6ylbvuXam0CWAAgAACJKv8G+rlxLteM0pjdf8rJ81CgAAIDi+w7+tr2x193UzhSwBFAAAQFBCCf+2CyWgHsY8aaEAAACCEVr4t/WVre7eWKwSQAEAAAQh1PBvK1oJoAAAALwLPfzbilQCKAAAAK/yEv5tRSkBFd8DAOje3ucO+x4BPbhly4TvEbzLW/i3tUvAIz9boeNzVd/jdIUdAACAF3kN/7a87wRQAAAAzuU9/NvyXAIoAAAAp4oS/m15LQEUAACAM0UL/7Y8lgAKAADAiaKGf1veSgAFAACQuaKHf1ueSgAFAACQqVjCvy0vJYACAADITGzh35aHEkABAABkItbwbwu9BFAAAACpqxird78m3vBv6ytb7dw4o/FaeH8OFAAAQKqaJtF31v6D/sqe9j1KEPrLVndfF95OAAUAAJCapkn03XX7dXjglO6vHtafnJ7zPVIQQrwcQAEAAKSidT78X+k/JUmyspSARUIrARQAAEDPWibR/10U/m2UgIuFVAIoAACAnlwp/NsoARcLpQSYrBfY+ehhm/UaAAA/lgr/xYyMPtKY0AeG6g4mC99sy+iRn63Q8bnqZX9+146JTDOaHQAAQFc6CX+JnYBL+d4JoAAAADrWafi3UQIu5rMEUAAAAB3pNvzbKAEX81UCKAAAgGXrNfzbKAEX81ECKAAAgGVJK/zbKAEXc10CKAAAgCWlHf5t7RLw0BlKgLRQAt48ck7zrexvoKMAAACuKqvwb7Oy+kKFnQBJOjBT1lf39+nY6Wbma1EAAABXlHX4t3E5YCH8/9tzA5prGSUOnqBDAQAAXJar8G+LuQQsDn9XKAAAgFdxHf5t7RLw32fiKQE+wl+iAAAALuEr/NusrP5L9WU9eKr4JcBX+EsUAADAIomx2rP2gLfwb7NG+mKt2CXAZ/hLFAAAwHmJsfru2v16eeCk71EkFbsE+A5/iQIAAFB44d9WxBIQQvhLFAAAiF6o4d9WpBIQSvhLFAAAiFro4d9WhBIQUvhLFAAAiNbCaf9/CD7829ol4NsnW75H6dgLJ8v6r8+GE/4SBQAAotQ+7X/Y82n/Tq2cqum+qR/qB9OJ71GW7cBMWQ/sG9B8Ek74SxQAAIhOXrb9LzU8WdPJuRfVUKJ/M/1kLkpAaNv+i1EAACAieQ//tjyUgJDDX6IAAEA08hv+9YvCv62hRB+efkLfnwrvTEDo4S9RAAAgCvkO/59f8edbsvqtk08GVQLyEP4SBQAACq+o4d8WUgnYfyof4S9RAACg0Ioe/m0hlID9p8r64+fzEf4SBQAACqt9q1/Rw7/NZwnIW/hLFAAAKKR2+L80MO17lI50G/5tPkpAHsNfogAAQOHkNfxXTtZ6Cv+2lqw+evKH2nMs+8cGv3AyP9f8L0UBAIACyWv4D0/Wdeoyt/p1q6FEHz3zY/31kdnUvual9p8K8wl/y0UBAICCyHP4p/HJ/1KJpE+ceyqTEpDXbf/FKAAAUAC5Df+pbMK/LYsSUITwlygAAJB7uQ7/2ezCvy3NElCU8JcoAACQa4T/8qRRAooU/hIFAAByi/DvTC8loGjhL1EAACCXCP/udFMCihj+EgUAAHKH8O9NJyWgqOEvUQAAIFcI/3QspwQUOfwlCgAA5Abhn66rlYCnjydew79eyT6eKQAAkAOEfzYuVwKePp7od7/f9Bj+RqsHy5mvQwEAgMAR/tlaXALa4X+u6WeWhfCvyDjoHpXslwjb3ucO9/T7b9ky4XV9IGa9/veXB7kN/4we75uVRNJ/OPoTrTuwSfOJnxlchr/EDgAABCsxVnvWEP4u1GeGNHrgumjCX6IAAECQLoT/IOGftfrMkNYcuF4myf66+2XX9xD+EgUAAIJD+LsTa/hLFAAACArh707M4S9RAAAgGIS/O7GHv0QBAIAgEP7u1E8PRh/+EgUAALwj/N2pnx7Umv2bog9/iQIAAF4R/u4Q/hejAACAJ4S/O4T/q1EAAMADwt8dwv/yKAAA4Bjh7w7hf2XRvwsAAFxKjNVenu3vBOF/dRQAAHCkHf4v5i38p/IX/iPzo1qx/1qZxM9Gd+jhL3EJAACcyG34T+bjlb6LDc+PaOvkzYT/EtgBAICM5Tr8c/bJf3huVDdN3ayy9RNveQl/iQLg/X3ivtcHkC3C3x3CvzNcAgCAjBD+7hD+naMAAEAGCH93CP/uUAAAIGWEvzuEf/coAACQIsLfHcK/N9EfAgSAtOQ2/HN4n/9C+L9JZctDfrrFDgAApCDX4Z+3+/wJ/1RQAACgR4S/O4R/eigAANADwt8dwj9dFAAA6BLh7w7hnz4KAAB0gfB3h/DPBgUAADpE+LtD+GeH2wABoAML4X+Q8HdgdH6Vtk7drJLlrX5ZYAcAAJbpF+E/5XuUjuQ2/Cf9hX9fvarxAoe/RAEAgGUh/N3xHv61qlaPrlSpwOEvUQAAYEmEvztBhP/YSpWK/NH/vOjPAOx97rDvEYDcumXLhO8RMkf4u0P4u8UOAABcAeHvDuHvHgUAAC6D8HeH8PeDAgAAlyD83SH8/aEAAMAihL87hL9fFAAAOI/wd4fw9y/6uwAAQCL8XRqd8/uEP8J/AQUAQPQSY7V3Dc/2d4HwDweXAABE7UL4DxL+WSP8w0IBABCt/IZ/H+HfIcL/1bgEACBK+Q7/Q77H6Ijv8O+vL4S/EeG/GDsAAKJD+LtD+IeLAgAgKoS/O4R/2CgAAKJB+LvjO/zrlRLhvwQKAIAoEP7uBBH+g2XCfwkUAACFR/i7E0z4k/1Liv4ugBjeZw7EjPB3h/DPF3YAABQW4e8O4Z8/FAAAhUT4u0P451P0lwAAFE9uw3+yrpNzhH8nCP/uUQAAFEq+w5/H+3air2o0PkD4d4tLAAAKg/B3J4zwrxD+PaAAACgEwt8dwr8YKAAAci8xVt8j/J0g/IuDAgAg19rh/3PCP3OEf7FQAADkFuHvDuFfPBQAALlE+LtD+BcTBQBA7hD+7hD+xcVzAADkCuHvzujsuLZOv5HwLyh2AADkBuHvDuFffOwAAMiN2VXH8hf+U4R/p/qqRuODFZH92WIHAEAuDFYS/cdVZd0zv9b3KMs2PFnXyVnCvxOEvzvR7wDsfe6w7xGArt2yZcL3CM68bnhOlZL02ysGpZm1erh2xPdIV8W2f+cIf7fYAQCQC68bnpMkGVn99orBoHcCCP/OEf7uUQAABG/DQFPj9daF/98uAe+bX+dxqssj/DvXVyH8faAAAAjeG0ZmX/VjRlYfXzEQVAngwF/n+ipG40OEvw8UAABBq5WsXrti/rI/1y4B9wRQAoan+zjw1yHC3y8KAICgbVk5p1rJXvHnFy4H+C0Bw9N9OnnukLf1u0H4gwIAIGhvGJlb8te0S8B7G+5LAOHfOcI/DBQAAMEaq7W0vr+5rF9rZPU7Q25LAOHfOcI/HBQAAMG6efTVh/+upl0C/mUj+1sECf/OEf5hoQAACFJJVltWXv7w39UYWX1yaDDTEpDL8J8j/HExCgCAIG1e0dBQJenq9xpZ/c7goHY0Vqc8VY7Df4rwx8UoAACCdLl7/ztRMlafGVyh7fNrUpqI8O9GX5XwDxUFAEBwhiqJrh9a3uG/qykZq383NJRKCSD8O8fjfcNGAQAQnDeMzMnoyvf+dyKNEkD4d47wDx8FAEBQjH7x4p+0tEvAO2c7LwGEf+f6KkarBwj/0FEAAATlmoGGRmutpX9hh0rG6t+vHNRt55Z/MJDw71z7mj/pH76K7wF8i+l96kAevHEZT/7rVsVInx0ekk5Kj/cfu+qvJfw7x7Z/vrADACAY9VKiG7u4978T7RLwG7PjV/w1hH/nCP/8oQAACMbW4XlVTDqH/66mYqT7Vq64bAkg/DtH+OcTBQBAMF6f4fb/pS5XAgj/zhH++RX9GQAAYVhdb2qir/d7/zvRLgH2pLRn7jTh3yHCP9/YAQAQhDeOZHvt/0oqRvrPwyv09mbNy/rdWjW7WjdN3kz4o2sUAADelY20dWVvj/7tRcVIn94wrp21zd5m6MTo3LheO/0GGU/xS/gXAwUAgHe/vGJO/ZXsD/9djZHVv10ffgkYY9sfKaEAAPAuy3v/OxF6CRibG9cWwh8poQAA8GpFJdHGQbeH/64m1BLgO/z7Cf/CoQAA8CrNF/+kJbQSEEL4ryL8C4cCAMAbI+l1gWz/XyqUEkD4IysUAADeXDc4r5Fq+i/+SYvvEkD4I0sUAADevMHTvf+d8FUCCH9kjQIAwIv+stXmoTC3/y/lugSEEP7jA4R/0VEAAHhx44pzquTob6B2Cbizmm0JCCX8Sf/ii/5dAHufO+x7BKBrt2yZ8D1C11adPKgfzpR0zYZxrRks+x5nWYysPr1hXHpJ+tPG/tS//tjsuLZME/5wI0f9G0BRjOiMhnVWK5LTOvbzl3TkdLgHAS/VLgFpXw4g/OEaBQCAcxvNsQv/u6aGjr+YvxKQ5pkAwh8+UAAAOFWS1bU6cdGPxVwCCH/4QgEA4NQGnVBVrw76GEsA4Q+fKAAAnLrOHL/iz8VUAgh/+EYBAODMoOa0WjNX/TUxlADf4d9XIfxBAQDg0LXmuLSMF/8UuQSEEP6rBwl/UAAAOGO1UceW/mXnFbEEEP4ICQUAgBNrNKMBdfbs/yKVgPHZtdo6fTPhj2BQAAA4cZ1Z/qf/xYpQAsZn1+q106+XsX7Sl/DH5UT/KGAA2aupqfWa7OH3L5QAc80GrRnKz2ODP7FulY4cqGluej3hj+BQAABk7lqdUGkZh/+upqaGjr34kuw1G7Q28BJwdLak/3ekpr85VtV8Y6W37CX8cTUUAACZ29jl9v+l2jsBCrAENBLp76cq+v6RuvadLPdYd3pH+GMpFAAAmRoxZzWss6l9vQslYMMGrV3hvwQcOlPW91+p6YkTFc22wkhbwh/LQQEAkKnr7LHUg6h9OaC5fr02DLv/a+xs0+iHkxXtfaWmF8/4LyGL9VeNVg3yVzuWFv2/JXl+nzoQupKsXnOVR//2om4aOvHyS5I2OCkBiZVeOFXW94/U9XeTFTV97/FfRl+1pPGBsAoJwhV9AQCQnSu9+Cct/aaZeQmYmi/pB8cr2vtKXZNz4e6p91VLWj1QZtsfy0YBAJCZjZe89jcLWZSA0A70LYXwRzcoAAAyMag5rTGnnKyVVgl45WxJf3uspu8dq+pMIx9pSvijWxQAAJlY7ot/0tJtCTjXMnryxMIW/4tn8vVwVMIfvaAAAMhAZy/+SctyS0D7QN8PjtX0oxMVzSf5S1DCH72iAABIXTcv/knL1UrA9HxJf3u8ou+9UtOJuXx92l+M8EcaKAAAUtfti3/S0m+aeunl49owvE7NRHpqsqq/OVrVC6cqSkI/0bcEwh9poQAASFWvL/5JSyux2n2gph9P1nWmWYy0JPyRJgoAgFSl8eKfbs3bsvY1RvT83Cq93ByU3NyE4MTCE/7ye9kC4aEAAEjVtY63/62MDjcH9PzcKj3fGFXDFi8kF8K/LMNHf6SIAgAgNSPmrEZSfPHP1ZxOqnp+flRPz63WyaTmZE3XjIwGa0YjAyXCH6mjAABITRYv/lmsZY0ONob1/PyYftpcqcQWMxQrJWmwXtJgraSyKeb3CP8oAABSkeWLf6aSPj07t0rPzI3pnC3mX1tGUn+tpMGaUV+leJcxEJ5i/pcEwLkNZjLVF/80VNGLGtWB1rieOdWX2tcNTa1sNFgvaaBaUokP+3CIAgAgFRvt8RS2/41O2EEd0mod0iq1VNLUbEtSksKE4SgZaaBa0mC9pFqZ1Icf0ReAvc8d9j0C0LVbtkz4HkGSNKD5nl78M6uqDtlx/URrdEb1Cz9uJZ1tFCP8jaR6ZWGLv79W4kgfvIu+AADo3UZzTJ2++Kclo1c0qkNapVfsiOxlIvHcfJL7J/eVjTRYK2uwblRhjx8BoQAA6FFnL/6ZUb9+pnH91K7W/BJ/BZ2Zz2f6c6APeUABANCTtTq15It/2gf6DtnVOqGhZX3dVmI118zX9n+1bDRQMxqqllUi9xE4CgCAnmy84q1/rz7Q14kz84mnBwp3pn2gb6heUpUDfcgRCgCArl3uxT9XOtDXCauwt//bB/oGakb93L6HnKIAAOha+8U/yznQ14m5hlUzwNN/lZI0UOVAH4qBAgCga8M6q6fsRh3SuBoqp/Z1z8wHdO3//Bb/QHXh0z5QFBQAAF17Ur+U+tdMrHQugHv/a+WF2/cGamzxo5goAACCctbj4T9jjAarRgO1kuoVUh/FRgEAEJTTjrf/jRaexz/A8/gRGQoAgGDMt6waLTef/znQh9hRAAAE48xcxp/+Fx/oq5RSeHkRkF8UAABByPLFPxee0Fcrs8UPnEcBABCEc410X/zDgT7g6igAAIJwZq739OdAH7B80ReAUN6nDsSs2eOLfzjQB3Qu+gIAwL+u7v3nCX1ATygAALzq9MU/HOgD0kEBAODVfDNZ8sU/HOgD0kcBAODV6St8+udAH5AtCgAAbxIrnbvk0b8c6APcoAAA8ObC4T8O9AHOUQAAeNNoWY3288pdwAcXBWBeUs3BOgByZnSg7HsEFJWvd0rniIu9ttMO1gAA4AK3L5XOJxcFYMbBGgAAXJBYtgCW4qIAHHewBgAAF6T5YqmiyrwAGGNfyHoNAAAW6+HVEtHIvABYmX1ZrwEAwGKNFg1gKdkXgMQ+nfUaAAAs1mxxDWApmReASrW0R9yQAQBwxEqabRI7S8m8AHztneuOWumZrNcBAEBa+PTPIcClOXnmpjHmOy7WAQCAT//L46QAJCbZ5WIdAADOzrd8j5ALTgrAn757/RNW4jAgACBTjZYV+b88zl67ZawedrUWACBOZ+a5/W+5nBWAvr7KA5KmXK0HAIhLYikAnXBWAB68ffWMke53tR4AIC4zcy1O/3fAWQGQJNuY/4KkYy7XBAAUX8tazcyR/p1wWgB23b1xyljzaZdrAgCK7+S5RDbNNwCa9L5UqJwWAEl6ZMfar0jme67XBQAU01zTpn7t33k4euD+ezTGthJzj6STztcGABRKYqXJs+nf91cyxd8C8FJyvn7n2gNG+qCPtQEAxTF5tqlmBif/SsXPf3+7HI/smPimpM/7Wh8AkG+nZhOda2Rz8K8SwTUAr9/iru3rPinpIZ8zAADy5+x8olOz2T3yr1oufgPw+x0aY4em1t0r6S+8zgEAyI1zjUSTZ5NM3zNfKRf/GoD3ivOlD5vGy6vX3W6NHvQ9CwAgbGcbVifOJLIZxr+R1FehADjxf/6pae5+97oPyugPfM8CAAjTqdlEJ840Mw1/aeHTP4cAXTLG7to+8Slr7R3inQEAgPMSa3X8TEsnM7zmv1gMn/6lkArAebvfs/4xlUtvttIe37MAAPyaa1odmWnpXMPdS34GamVna/kUXAGQpF3vWntw9/Z1/0RG90g66nseAIBbiZWmzrZ09HQ29/lfSbVsFEn+h1kAJLUvCXy1Vp290UqflTTpeyQAQLaSRDo529LLp5o67eHVvoO1cGMxbbm50LH90aNDFTXvNTLvl3ST73kAAOlpJFZn5hKdnk+U5jt9OlEy0sTKajAHAHftmMh0kkC+zc7c+c2X3lSypZ3W2rcZmdcr5J0MAMCrWEmNljTXTHR2vqV5N+f7rmq4r6yVfeHECQVgCXftenncVHWrpK2y2iKZGySNSRqRNCSp5nVAAIiUlWTtwin+JJGaidRI0YHn/gAABKtJREFUEjVbVrNNK4eX9pdUMkbrV5ZlAnoJEAXAs7d+6VBA/4oCALIwNlAO7vp/1gUgrO8WAADH6hUTXPi7EN93DADAeSWz8Ok/RhQAAEC0xgYqqoRy7N8xCgAAIEor+0rqr8YZ/hIFAAAQoYFaSSv74tz6b6MAAACi0l8taWygFP1tcBXfAwAA4MpA1WhssCQTffxTAAAAkVjZV9Jw5Nv+i1EAAACFVjJGYwMl9Ve56r0YBQAAUFj1itHYQDnaW/2uhgIAACickpGG+8saivAJf8tFAQAAFEapJK2olbWiboJ6sU+IKAAAgNyrlowG6yUN1Uoi95eHAgAAyB0jqVqW6pWSBmpl1Tjc3zEKAAAgSEaSMQun+EslqVKSqqWSKmWjvooR5/p6QwFYwmtGqvOSar7nAABEZS7rBTgeubTTvgcAAERnJusFKABLy/wfAgAAl6AABOC47wEAANHJPHsoAEswxr7gewYAQFyMMfuyXoMCsASr7P8hAACwmFVCAfDNJvZp3zMAAOJirJ7Jeg0KwBIq1dIeSdb3HACAaCRJU3uyXoQCsISvvXPdUavsmxgAAOc9tXvneg4BhsAY8x3fMwAA4mCkv3KxDgVgGRKT7PI9AwAgDlYtJ5nDk5SX6a5HD/+9kV7new4AQKE9u2vHxE0uFmIHYJmM1cO+ZwAAFJuV/RNXa1EAlqmvr/KApCnfcwAACmuyv179sqvFKADL9ODtq2eMdL/vOQAABWX1hQdvX+3s/TMUgA7YxvwXJB3zPQcAoHCONEz9iy4XpAB0YNfdG6eMNZ/2PQcAoGjsp76xY+ykyxW5C6BT1pqd3ziyR7Jv8T0KAKAQvrtr+7pfkzFOnzrLDkCnjLGtxNwjyWlTAwAUkZlWufSvXIe/RAHoytfvXHvASB/0PQcAIOdM8oFd71p70MfSFIAuPbJj4puSPu97DgBAPlmr39+1ff3/9LU+BaAHu7av+6Skh3zPAQDIG7vrxufWfcbnBBSAXhhjh6bW3SvpL3yPAgDIjW8PTU287777TOJzCO4CSMGv/bWtTBx/5QFj9X7fswAAwmWM+R+Dk2vf/6UPm4b3WXwPUBjWmp3ffOX3ZfVJ36MAAIJjrdXndu9Y92kfJ/4vhwKQsru+/vI2Y8yDkkZ9zwIACMIpa/Wh3e+ZeNT3IItRADKw88+OXG9byUNGeqvvWQAAXn23LPO+r+1Y9xPfg1yKApCVhUsC75XV5ySt8T0OAMCpScl+Ztf2iS+HsuV/KQpAxt73rZ+MzDX6Pmqkj0ka8z0PACBTJ2T1Rw1T/6LrZ/t3igLgyPZHjw5V1LzXyLxf0k2+5wEApMdKTxtrH2yYype/sWPNad/zLAcFwIM7v/nSm0q2tNNa+zYj83rxPAYAyJtEMn9nZL9j1dq1a8c1P/Y9UKcoAJ7dtevlcVPVrZK2ymqLZG7QwqWCEUlDkmpeBwSAeM1LOi1pWtKkrNmnUvK8sXomaWrP7p3rj3ueDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAwvr/jx1yMr8N5yoAAAAASUVORK5CYII=\"","import React, { useState, useEffect } from 'react';\nimport useAxios from 'axios-hooks';\n\nconst PlanContext = React.createContext();\n\n/* eslint-disable-next-line */\nconst PlanProvider = ({ children }) => {\n const [, fetchPlan] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/plans`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const [plan, setPlan] = useState({\n label: '',\n app: 0,\n app_counter: 0,\n document: 0,\n document_counter: 0,\n });\n\n useEffect(() => {\n fetchPlan().then(({ data }) => setPlan({ ...plan, ...data }));\n }, []);\n\n return (\n \n {children}\n \n );\n};\nexport { PlanContext, PlanProvider };\n","import { useContext } from 'react';\nimport { PlanContext } from '../contexts/PlanContext';\n\nexport const usePlan = () => {\n const { plan, setPlan } = useContext(PlanContext);\n\n return [plan, setPlan];\n};\nexport default usePlan;\n","import React, { useState } from 'react';\nimport { IconButton, ListItemIcon, Menu, MenuItem } from '@mui/material';\nimport useAxios from 'axios-hooks';\nimport MoreVertIcon from '@mui/icons-material/MoreVert';\nimport DownloadIcon from '@mui/icons-material/Download';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport { useNavigate } from 'react-router';\nimport EditIcon from '@mui/icons-material/Edit';\nimport PublishIcon from '@mui/icons-material/Publish';\nimport { usePlan } from '../../../../hooks/usePlan';\nimport { useFeedback } from '../../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK } from '../../../../utilities/feedback';\nimport AlertBox from '../../../../components/AlertBox';\n\nconst Actions = ({ id, state, refetch }) => {\n const [anchorEl, setAnchorEl] = useState(null);\n const [open, setOpen] = useState(false);\n const [plan, setPlan] = usePlan();\n const navigate = useNavigate();\n const isMenuOpen = Boolean(anchorEl);\n const [, setFeedback] = useFeedback();\n\n const handleMenuOpen = (event) => {\n setAnchorEl(event.currentTarget);\n };\n\n const handleMenuClose = () => {\n setAnchorEl(null);\n };\n\n const [, fetchDownload] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/documents/download/${id}`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const [, publishDocument] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/documents/publish/${id}`,\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const [, destroyDocument] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/documents/${id}`,\n method: 'DELETE',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const downloadDocument = () => {\n fetchDownload().then((result) => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Document downloaded',\n })\n );\n window.open(result.data.url, '_blank');\n });\n };\n\n const deleteDocument = () => {\n destroyDocument().then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Document removed',\n })\n );\n refetch();\n setOpen(false);\n });\n };\n\n const generateDocument = () => {\n publishDocument().then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Document published',\n })\n );\n setPlan({ ...plan, document_counter: plan.document_counter + 1 });\n refetch();\n });\n };\n\n return (\n <>\n setOpen(false)}\n submit={deleteDocument}\n title=\"Are your sure ?\"\n text=\"Do you want to remove this document ?\"\n canceltext=\"Cancel\"\n submitText=\"Delete\"\n />\n \n \n \n \n navigate(`/app/documents/${id}/edit`)}>\n \n \n \n Edit\n \n = plan.document}\n >\n \n \n \n Publish\n \n \n \n \n \n Download\n \n setOpen(true)}>\n \n \n \n Delete\n \n \n >\n );\n};\nexport default Actions;\n","import React, { useState } from 'react';\nimport {\n styled,\n Box,\n Button,\n CircularProgress,\n Chip,\n Alert,\n Container,\n TableHead,\n TableBody,\n TableRow,\n TableCell,\n TableSortLabel,\n TableContainer,\n Table,\n TablePagination,\n Tooltip,\n} from '@mui/material';\nimport { visuallyHidden } from '@mui/utils';\nimport AddIcon from '@mui/icons-material/Add';\nimport RefreshIcon from '@mui/icons-material/Refresh';\nimport useAxios from 'axios-hooks';\nimport { useNavigate } from 'react-router';\nimport InfoIcon from '@mui/icons-material/Info';\nimport WarningIcon from '@mui/icons-material/Warning';\nimport CheckCircleIcon from '@mui/icons-material/CheckCircle';\nimport Moment from 'react-moment';\nimport Title from '../../../components/Title';\nimport Actions from '../components/Actions';\nimport Loader from '../../../components/Loader';\n\nconst style = {\n button: {\n marginLeft: '10px',\n },\n};\n\nconst Action = styled(Container)(({ theme }) => ({\n marginBottom: '14px',\n textAlign: 'end',\n padding: theme.spacing(1),\n [theme.breakpoints.down('md')]: {\n textAlign: 'start',\n },\n [theme.breakpoints.up('md')]: {\n textAlign: 'end',\n },\n}));\n\nconst DocumentsList = () => {\n const navigate = useNavigate();\n const [order, setOrder] = useState('desc');\n const [orderBy, setOrderBy] = useState('updated_at');\n const [page, setPage] = useState(0);\n const [rowsPerPage, setRowsPerPage] = useState(25);\n const [{ data, loading, error }, refetch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/documents`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const headCells = [\n {\n id: 'id',\n numeric: false,\n disablePadding: true,\n label: '#',\n },\n {\n id: 'state',\n numeric: false,\n disablePadding: false,\n label: 'State',\n },\n {\n id: 'title',\n numeric: false,\n disablePadding: false,\n label: 'Title',\n },\n {\n id: 'template',\n numeric: false,\n disablePadding: false,\n label: 'Template',\n },\n {\n id: 'updated_at',\n numeric: false,\n disablePadding: false,\n label: 'Updated At',\n },\n {\n id: 'action',\n numeric: true,\n disablePadding: false,\n label: 'Actions',\n },\n ];\n\n /* eslint-disable-next-line */\n const descendingComparator = (a, b, orderBy) => {\n if (b[orderBy] < a[orderBy]) {\n return -1;\n }\n if (b[orderBy] > a[orderBy]) {\n return 1;\n }\n return 0;\n };\n\n /* eslint-disable-next-line */\n const getComparator = (order, orderBy) => {\n return order === 'desc'\n ? (a, b) => descendingComparator(a, b, orderBy)\n : (a, b) => -descendingComparator(a, b, orderBy);\n };\n\n const stableSort = (array, comparator) => {\n const stabilizedThis = array.map((el, index) => [el, index]);\n stabilizedThis.sort((a, b) => {\n /* eslint-disable-next-line */\n const order = comparator(a[0], b[0]);\n if (order !== 0) {\n return order;\n }\n return a[1] - b[1];\n });\n return stabilizedThis.map((el) => el[0]);\n };\n\n const handleChangePage = (event, newPage) => {\n setPage(newPage);\n };\n\n const handleChangeRowsPerPage = (event) => {\n setRowsPerPage(parseInt(event.target.value, 10));\n setPage(0);\n };\n\n const handleRequestSort = (event, property) => {\n const isAsc = orderBy === property && order === 'asc';\n setOrder(isAsc ? 'desc' : 'asc');\n setOrderBy(property);\n };\n\n const createSortHandler = (property) => (event) => {\n handleRequestSort(event, property);\n };\n\n const documentIcon = ({ state }) => {\n switch (state) {\n case 'draft':\n return ;\n case 'pending':\n return ;\n case 'wip':\n return ;\n case 'created':\n return ;\n default:\n return '';\n }\n };\n\n const documentColor = ({ state }) => {\n switch (state) {\n case 'draft':\n return 'info';\n case 'pending':\n return 'warning';\n case 'wip':\n return 'warning';\n case 'created':\n return 'success';\n case 'error':\n return 'error';\n default:\n return 'success';\n }\n };\n\n return (\n \n \n \n : }\n onClick={() => refetch()}\n >\n Refresh\n \n }\n onClick={() => navigate('/app/documents/initialize')}\n >\n Create a document\n \n \n {error && {error} }\n {loading && }\n {!loading && (\n \n {data.length === 0 && (\n \n Get started, make your first PDF document\n \n )}\n \n \n \n \n {headCells.map((headCell) => (\n \n \n {headCell.label}\n {orderBy === headCell.id ? (\n \n {order === 'desc' ? 'sorted descending' : 'sorted ascending'}\n \n ) : null}\n \n \n ))}\n \n \n \n {stableSort(data, getComparator(order, orderBy))\n .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)\n .map((row) => {\n return (\n \n {row.id} \n \n {row.state === 'error' ? (\n \n \n \n ) : (\n \n )}\n \n {row.title} \n {row.template} \n \n {row.updated_at} \n \n \n \n \n \n );\n })}\n \n
\n \n \n \n )}\n \n );\n};\nexport default DocumentsList;\n","import React, { useState } from 'react';\nimport {\n Box,\n Container,\n Button,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n Grid,\n TextField,\n FormHelperText,\n} from '@mui/material';\nimport useAxios from 'axios-hooks';\nimport { useNavigate } from 'react-router';\nimport Title from '../../../components/Title';\nimport { useFeedback } from '../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK } from '../../../utilities/feedback';\n\nconst style = {\n root: {\n marginTop: '40px',\n },\n};\n\nconst DocumentInit = () => {\n const [, setFeedback] = useFeedback();\n const navigate = useNavigate();\n const [document, setDocument] = useState({\n title: '',\n payload: '{}',\n template_id: null,\n });\n const [errors, setErrors] = useState({\n title: '',\n template_id: '',\n });\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setDocument((prevDocument) => ({ ...prevDocument, [name]: value }));\n };\n\n const [{ data }] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/templates`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const [, executePost] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/documents`,\n method: 'POST',\n },\n {\n useCache: false,\n manual: true,\n }\n );\n\n const createDocument = () => {\n executePost({ data: document })\n .then((result) => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: \"Document created. Let's go for read data\",\n })\n );\n navigate(`/app/documents/${result.data.id}/edit`);\n })\n .catch((err) => {\n setErrors(err.response.data);\n });\n };\n\n const validForm = document.title !== '' && document.template !== null;\n\n return (\n \n \n \n \n \n \n \n \n \n \n Template \n \n {data &&\n data.map((row) => {\n return {row.title} ;\n })}\n \n {errors.template_id} \n \n \n \n \n \n Create my document\n \n \n \n \n \n );\n};\nexport default DocumentInit;\n","import React, { useState, useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport {\n Chip,\n Typography,\n Box,\n Grid,\n Button,\n Divider,\n Tabs,\n Tab,\n useTheme,\n styled,\n Alert,\n} from '@mui/material';\nimport SwipeableViews from 'react-swipeable-views';\nimport { useParams } from 'react-router-dom';\nimport { useNavigate } from 'react-router';\nimport AceEditor from 'react-ace';\nimport useAxios from 'axios-hooks';\nimport { Worker, Viewer } from '@react-pdf-viewer/core';\nimport '@react-pdf-viewer/core/lib/styles/index.css';\nimport SaveIcon from '@mui/icons-material/Save';\nimport PublishIcon from '@mui/icons-material/Publish';\nimport Cookies from 'js-cookie';\nimport InfoIcon from '@mui/icons-material/Info';\nimport WarningIcon from '@mui/icons-material/Warning';\nimport CheckCircleIcon from '@mui/icons-material/CheckCircle';\nimport Title from '../../../components/Title';\nimport { useFeedback } from '../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK } from '../../../utilities/feedback';\n\nconst TabPanel = (props) => {\n const { children, value, index, ...other } = props;\n\n return (\n \n {value === index && (\n \n {children} \n \n )}\n
\n );\n};\n\nTabPanel.propTypes = {\n children: PropTypes.node.isRequired,\n index: PropTypes.number.isRequired,\n value: PropTypes.number.isRequired,\n};\n\nconst a11yProps = (index) => {\n return {\n id: `full-width-tab-${index}`,\n 'aria-controls': `full-width-tabpanel-${index}`,\n };\n};\n\nconst style = {\n button: {\n marginLeft: '10px',\n },\n};\n\nconst Action = styled(Box)(({ theme }) => ({\n marginBottom: '14px',\n textAlign: 'end',\n paddingRight: '0',\n [theme.breakpoints.down('md')]: {\n textAlign: 'start',\n },\n [theme.breakpoints.up('md')]: {\n textAlign: 'end',\n },\n}));\n\nconst DocumentNew = () => {\n const { id } = useParams();\n const navigate = useNavigate();\n const theme = useTheme();\n const [, setFeedback] = useFeedback();\n const [tab, setTab] = useState(0);\n const [rand, setRand] = useState(Math.random());\n const [document, setDocument] = useState({\n template: '',\n payload: '{}',\n });\n\n const [, executePatch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/documents/${id}`,\n method: 'PATCH',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const [, fetchDocument] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/documents/${id}/edit`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const [, publishDocument] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/documents/publish/${id}`,\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const updateDocument = () => {\n executePatch({ data: document }).then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Document updated',\n })\n );\n setRand(Math.random());\n setDocument({ ...document, state: 'draft' });\n });\n };\n\n const generateDocument = () => {\n publishDocument().then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Document published',\n })\n );\n setDocument({ ...document, state: 'created' });\n navigate('/app/documents');\n });\n };\n\n const handleChangeTab = (event, value) => {\n setTab(value);\n };\n\n const handleChangeIndex = (index) => {\n setTab(index);\n };\n\n const editorChange = (name, value) => {\n setDocument({ ...document, [name]: value });\n };\n\n const documentIcon = ({ state }) => {\n switch (state) {\n case 'draft':\n return ;\n case 'pending':\n return ;\n case 'wip':\n return ;\n case 'error':\n return ;\n case 'created':\n return ;\n default:\n return '';\n }\n };\n\n const documentColor = ({ state }) => {\n switch (state) {\n case 'draft':\n return 'info';\n case 'pending':\n return 'warning';\n case 'wip':\n return 'warning';\n case 'error':\n return 'error';\n case 'created':\n return 'success';\n default:\n return 'success';\n }\n };\n\n useEffect(() => {\n if (id) fetchDocument().then(({ data }) => setDocument({ ...document, ...data }));\n }, [id]);\n\n return (\n \n \n \n \n }\n onClick={updateDocument}\n >\n Save\n \n }\n onClick={generateDocument}\n >\n Publish\n \n \n \n \n \n \n \n \n \n \n \n \n \n editorChange('payload', value)}\n name=\"payload\"\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n highlightActiveLine: true,\n showLineNumbers: false,\n }}\n />\n \n \n \n \n \n \n \n \n Invalid data Payload. }\n />\n \n \n \n \n );\n};\nexport default DocumentNew;\n","import React, { useState } from 'react';\nimport { IconButton, ListItemIcon, Menu, MenuItem } from '@mui/material';\n/* eslint-disable-next-line */\nimport { useNavigate } from 'react-router';\nimport useAxios from 'axios-hooks';\nimport MoreVertIcon from '@mui/icons-material/MoreVert';\nimport EditIcon from '@mui/icons-material/Edit';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport { useFeedback } from '../../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK, ERROR_FEEDBACK } from '../../../../utilities/feedback';\nimport AlertBox from '../../../../components/AlertBox';\n\nconst Actions = ({ id, refetch }) => {\n const [anchorEl, setAnchorEl] = useState(null);\n const [open, setOpen] = useState(false);\n const isMenuOpen = Boolean(anchorEl);\n const [, setFeedback] = useFeedback();\n const navigate = useNavigate();\n\n const handleMenuOpen = (event) => {\n setAnchorEl(event.currentTarget);\n };\n\n const handleMenuClose = () => {\n setAnchorEl(null);\n };\n\n const [, destroyWebhook] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/webhook_endpoints/${id}`,\n method: 'DELETE',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const deleteWebhook = () => {\n destroyWebhook()\n .then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Webhook removed',\n })\n );\n refetch();\n })\n .catch((response) =>\n setFeedback(\n ERROR_FEEDBACK({\n message: response.message,\n })\n )\n );\n setOpen(false);\n };\n\n return (\n <>\n setOpen(false)}\n submit={deleteWebhook}\n title=\"Delete\"\n text=\"Do you want to remove this Webhook ?\"\n canceltext=\"Cancel\"\n submitText=\"Delete\"\n />\n \n \n \n \n navigate(`/app/webhook_endpoints/${id}/edit`)}>\n \n \n \n Edit\n \n setOpen(true)}>\n \n \n \n Delete\n \n \n >\n );\n};\nexport default Actions;\n","import React, { useState } from 'react';\nimport {\n styled,\n Box,\n Button,\n Container,\n Alert,\n TableHead,\n TableBody,\n TableRow,\n TableCell,\n TableSortLabel,\n TableContainer,\n Table,\n TablePagination,\n} from '@mui/material';\nimport { visuallyHidden } from '@mui/utils';\nimport AddIcon from '@mui/icons-material/Add';\nimport useAxios from 'axios-hooks';\n/* eslint-disable-next-line */\nimport { useNavigate } from 'react-router';\nimport Title from '../../../components/Title';\nimport Actions from '../components/Actions';\nimport Loader from '../../../components/Loader';\n\nconst Action = styled(Container)(({ theme }) => ({\n marginBottom: '14px',\n textAlign: 'end',\n padding: theme.spacing(1),\n [theme.breakpoints.down('md')]: {\n textAlign: 'start',\n },\n [theme.breakpoints.up('md')]: {\n textAlign: 'end',\n },\n}));\n\nconst WebhooksList = () => {\n const navigate = useNavigate();\n const [order, setOrder] = useState('desc');\n const [orderBy, setOrderBy] = useState('updated_at');\n const [page, setPage] = useState(0);\n const [rowsPerPage, setRowsPerPage] = useState(5);\n const [{ data, loading, error }, refetch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}//webhook_endpoints`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const headCells = [\n {\n id: 'target_url',\n numeric: false,\n disablePadding: false,\n label: 'Target URL',\n },\n {\n id: 'app_name',\n numeric: false,\n disablePadding: false,\n label: 'Application',\n },\n {\n id: 'action',\n numeric: true,\n disablePadding: false,\n label: 'Actions',\n },\n ];\n\n /* eslint-disable-next-line */\n const descendingComparator = (a, b, orderBy) => {\n if (b[orderBy] < a[orderBy]) {\n return -1;\n }\n if (b[orderBy] > a[orderBy]) {\n return 1;\n }\n return 0;\n };\n\n /* eslint-disable-next-line */\n const getComparator = (order, orderBy) => {\n return order === 'desc'\n ? (a, b) => descendingComparator(a, b, orderBy)\n : (a, b) => -descendingComparator(a, b, orderBy);\n };\n\n const stableSort = (array, comparator) => {\n const stabilizedThis = array.map((el, index) => [el, index]);\n stabilizedThis.sort((a, b) => {\n /* eslint-disable-next-line */\n const order = comparator(a[0], b[0]);\n if (order !== 0) {\n return order;\n }\n return a[1] - b[1];\n });\n return stabilizedThis.map((el) => el[0]);\n };\n\n const handleChangePage = (event, newPage) => {\n setPage(newPage);\n };\n\n const handleChangeRowsPerPage = (event) => {\n setRowsPerPage(parseInt(event.target.value, 10));\n setPage(0);\n };\n\n const handleRequestSort = (event, property) => {\n const isAsc = orderBy === property && order === 'asc';\n setOrder(isAsc ? 'desc' : 'asc');\n setOrderBy(property);\n };\n\n const createSortHandler = (property) => (event) => {\n handleRequestSort(event, property);\n };\n\n return (\n \n \n \n }\n onClick={() => navigate('/app/webhook_endpoints/new')}\n >\n Create a webhook\n \n \n {error && {error} }\n {loading && }\n {!loading && (\n \n {data.length === 0 && (\n \n Get started, use your first Webhook\n \n )}\n \n \n \n \n {headCells.map((headCell) => (\n \n \n {headCell.label}\n {orderBy === headCell.id ? (\n \n {order === 'desc' ? 'sorted descending' : 'sorted ascending'}\n \n ) : null}\n \n \n ))}\n \n \n \n {stableSort(data, getComparator(order, orderBy))\n .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)\n .map((row) => {\n return (\n \n {row.target_url} \n {row.app_name} \n \n \n \n \n );\n })}\n \n
\n \n \n \n )}\n \n );\n};\nexport default WebhooksList;\n","import React, { useState, useEffect } from 'react';\nimport {\n Container,\n Box,\n Grid,\n TextField,\n Button,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n FormHelperText,\n} from '@mui/material';\nimport { useParams } from 'react-router-dom';\n/* eslint-disable-next-line */\nimport { useNavigate } from 'react-router';\nimport useAxios from 'axios-hooks';\nimport SaveIcon from '@mui/icons-material/Save';\nimport { useFeedback } from '../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK } from '../../../utilities/feedback';\nimport Title from '../../../components/Title';\nimport 'ace-builds/src-noconflict/mode-html';\nimport 'ace-builds/src-noconflict/theme-xcode';\nimport 'ace-builds/src-noconflict/ext-language_tools';\nimport '@react-pdf-viewer/core/lib/styles/index.css';\n\nconst style = {\n root: {\n marginTop: '40px',\n },\n};\n\nconst WebhookNew = () => {\n const { id } = useParams();\n const navigate = useNavigate();\n const [, setFeedback] = useFeedback();\n const [webhook, setWebhook] = useState({\n target_url: '',\n app_id: null,\n });\n const [errors, setErrors] = useState({\n target_url: '',\n app_id: '',\n });\n\n const [, executePost] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/webhook_endpoints`,\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n manual: true,\n }\n );\n\n const [, executePatch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/webhook_endpoints/${id}`,\n method: 'PATCH',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const [{ data }] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/apps`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const [, fetchWebhook] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/webhook_endpoints/${id}/edit`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const createWebhook = () => {\n executePost({ data: webhook })\n .then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Webhook created',\n })\n );\n navigate('/app/webhook_endpoints');\n })\n .catch((error) => {\n setErrors(error.response.data);\n });\n };\n\n const updateWebhook = () => {\n executePatch({ data: webhook })\n .then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Webhook updated',\n })\n );\n navigate('/app/webhook_endpoints');\n })\n .catch((error) => {\n setErrors(error.response.data);\n });\n };\n\n const createOrUpdate = () => (id ? updateWebhook() : createWebhook());\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setWebhook({ ...webhook, [name]: value });\n };\n\n const checkForm = webhook.target_url !== '' && webhook.app !== null;\n\n useEffect(() => {\n /* eslint-disable-next-line */\n if (id) fetchWebhook().then(({ data }) => setWebhook({ ...webhook, ...data }));\n }, [id]);\n\n return (\n \n \n \n \n \n \n \n \n \n \n Application \n \n {data &&\n data.map((row) => {\n return {row.name} ;\n })}\n \n {errors.app_id} \n \n \n \n }\n onClick={() => createOrUpdate()}\n >\n Save\n \n \n \n \n \n );\n};\nexport default WebhookNew;\n","import React, { useState } from 'react';\nimport { IconButton, ListItemIcon, Menu, MenuItem } from '@mui/material';\nimport MoreVertIcon from '@mui/icons-material/MoreVert';\nimport EditIcon from '@mui/icons-material/Edit';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport { useNavigate } from 'react-router';\nimport useAxios from 'axios-hooks';\nimport { usePlan } from '../../../../hooks/usePlan';\nimport { useFeedback } from '../../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK, ERROR_FEEDBACK } from '../../../../utilities/feedback';\nimport AlertBox from '../../../../components/AlertBox';\n\nconst Actions = ({ id, refetch }) => {\n const [anchorEl, setAnchorEl] = useState(null);\n const [open, setOpen] = useState(false);\n const [plan, setPlan] = usePlan();\n const isMenuOpen = Boolean(anchorEl);\n const [, setFeedback] = useFeedback();\n const navigate = useNavigate();\n\n const handleMenuOpen = (event) => {\n setAnchorEl(event.currentTarget);\n };\n\n const handleMenuClose = () => {\n setAnchorEl(null);\n };\n\n const [, destroyApp] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/apps/${id}`,\n method: 'DELETE',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const deleteApp = () => {\n destroyApp()\n .then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'App removed',\n })\n );\n setPlan({ ...plan, app_counter: plan.app_counter - 1 });\n refetch();\n })\n .catch((err) =>\n setFeedback(\n ERROR_FEEDBACK({\n message: err.response.data.error,\n })\n )\n );\n setOpen(false);\n };\n\n return (\n <>\n setOpen(false)}\n submit={deleteApp}\n title=\"Are you sur ?\"\n text=\"Do you want to remove this app ?\"\n canceltext=\"Cancel\"\n submitText=\"Delete\"\n />\n \n \n \n \n navigate(`/app/apps/${id}/edit`)}>\n \n \n \n Edit\n \n setOpen(true)}>\n \n \n \n Delete\n \n \n >\n );\n};\nexport default Actions;\n","import React, { useState } from 'react';\nimport {\n styled,\n Box,\n Button,\n Container,\n Alert,\n TableHead,\n TableBody,\n TableRow,\n TableCell,\n TableSortLabel,\n TableContainer,\n Table,\n TablePagination,\n} from '@mui/material';\nimport { visuallyHidden } from '@mui/utils';\nimport Moment from 'react-moment';\nimport AddIcon from '@mui/icons-material/Add';\nimport useAxios from 'axios-hooks';\nimport { useNavigate } from 'react-router';\nimport { usePlan } from '../../../hooks/usePlan';\nimport Title from '../../../components/Title';\nimport Actions from '../components/Actions';\nimport Loader from '../../../components/Loader';\n\nconst Action = styled(Container)(({ theme }) => ({\n marginBottom: '14px',\n textAlign: 'end',\n padding: theme.spacing(1),\n [theme.breakpoints.down('md')]: {\n textAlign: 'start',\n },\n [theme.breakpoints.up('md')]: {\n textAlign: 'end',\n },\n}));\n\nconst AppsList = () => {\n const navigate = useNavigate();\n const [plan] = usePlan();\n const [order, setOrder] = useState('desc');\n const [orderBy, setOrderBy] = useState('updated_at');\n const [page, setPage] = useState(0);\n const [rowsPerPage, setRowsPerPage] = useState(5);\n const [{ data, loading, error }, refetch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/apps`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const headCells = [\n {\n id: 'name',\n numeric: false,\n disablePadding: false,\n label: 'Name',\n },\n {\n id: 'updated_at',\n numeric: false,\n disablePadding: false,\n label: 'updated At',\n },\n {\n id: 'action',\n numeric: true,\n disablePadding: false,\n label: 'Actions',\n },\n ];\n\n /* eslint-disable-next-line */\n const descendingComparator = (a, b, orderBy) => {\n if (b[orderBy] < a[orderBy]) {\n return -1;\n }\n if (b[orderBy] > a[orderBy]) {\n return 1;\n }\n return 0;\n };\n\n /* eslint-disable-next-line */\n const getComparator = (order, orderBy) => {\n return order === 'desc'\n ? (a, b) => descendingComparator(a, b, orderBy)\n : (a, b) => -descendingComparator(a, b, orderBy);\n };\n\n const stableSort = (array, comparator) => {\n const stabilizedThis = array.map((el, index) => [el, index]);\n stabilizedThis.sort((a, b) => {\n /* eslint-disable-next-line */\n const order = comparator(a[0], b[0]);\n if (order !== 0) {\n return order;\n }\n return a[1] - b[1];\n });\n return stabilizedThis.map((el) => el[0]);\n };\n\n const handleChangePage = (event, newPage) => {\n setPage(newPage);\n };\n\n const handleChangeRowsPerPage = (event) => {\n setRowsPerPage(parseInt(event.target.value, 10));\n setPage(0);\n };\n\n const handleRequestSort = (event, property) => {\n const isAsc = orderBy === property && order === 'asc';\n setOrder(isAsc ? 'desc' : 'asc');\n setOrderBy(property);\n };\n\n const createSortHandler = (property) => (event) => {\n handleRequestSort(event, property);\n };\n\n return (\n \n \n \n }\n onClick={() => navigate('/app/apps/new')}\n >\n Create an Application\n \n \n {error && {error} }\n {loading && }\n {!loading && (\n \n {plan.app <= plan.app_counter && (\n \n You are using all your apps slots ({`${plan.app_counter}/${plan.app}`}) . If you\n need more apps, upgrade your account\n \n )}\n \n \n \n \n {headCells.map((headCell) => (\n \n \n {headCell.label}\n {orderBy === headCell.id ? (\n \n {order === 'desc' ? 'sorted descending' : 'sorted ascending'}\n \n ) : null}\n \n \n ))}\n \n \n \n {stableSort(data, getComparator(order, orderBy))\n .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)\n .map((row) => {\n return (\n \n {row.name} \n \n {row.updated_at} \n \n \n \n \n \n );\n })}\n \n
\n \n \n \n )}\n \n );\n};\nexport default AppsList;\n","import React, { useState, useEffect } from 'react';\nimport { Container, Box, Grid, TextField, Button } from '@mui/material';\nimport { useParams } from 'react-router-dom';\nimport { useNavigate } from 'react-router';\nimport 'ace-builds/src-noconflict/mode-html';\nimport 'ace-builds/src-noconflict/theme-xcode';\nimport 'ace-builds/src-noconflict/ext-language_tools';\nimport useAxios from 'axios-hooks';\nimport '@react-pdf-viewer/core/lib/styles/index.css';\nimport SaveIcon from '@mui/icons-material/Save';\nimport { usePlan } from '../../../hooks/usePlan';\nimport Title from '../../../components/Title';\nimport { useFeedback } from '../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK } from '../../../utilities/feedback';\n\nconst style = {\n root: {\n marginTop: '40px',\n },\n};\n\nconst AppNew = () => {\n const { id } = useParams();\n const navigate = useNavigate();\n const [plan, setPlan] = usePlan();\n const [, setFeedback] = useFeedback();\n const [app, setApp] = useState({\n name: '',\n });\n const [errors, setErrors] = useState({\n name: '',\n });\n\n const [, executePost] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/apps`,\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n manual: true,\n }\n );\n\n const [, executePatch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/apps/${id}`,\n method: 'PATCH',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const [, fetchApp] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/apps/${id}/edit`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const createApp = () => {\n executePost({ data: app })\n .then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'App created',\n })\n );\n localStorage.setItem('app', true);\n setPlan({ ...plan, app_counter: plan.app_counter + 1 });\n navigate('/app/apps');\n })\n .catch((error) => {\n setErrors(error.response.data);\n });\n };\n\n const updateApp = () => {\n executePatch({ data: app })\n .then(() => {\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'App updated',\n })\n );\n navigate('/app/apps');\n })\n .catch((error) => {\n setErrors(error.response.data);\n });\n };\n\n const createOrUpdate = () => (id ? updateApp() : createApp());\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setApp({ ...app, [name]: value });\n };\n\n useEffect(() => {\n if (id) fetchApp().then(({ data }) => setApp({ ...app, ...data }));\n }, [id]);\n\n return (\n \n \n \n \n \n \n \n \n }\n onClick={() => createOrUpdate()}\n >\n Save\n \n \n \n \n \n );\n};\nexport default AppNew;\n","import React, { useState, useEffect } from 'react';\nimport {\n TextField,\n Divider,\n Container,\n Box,\n Grid,\n Button,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n Alert,\n} from '@mui/material';\nimport useAxios from 'axios-hooks';\nimport SaveIcon from '@mui/icons-material/Save';\nimport Cookies from 'js-cookie';\nimport AceEditor from 'react-ace';\nimport { useFeedback } from '../../../hooks/useFeedback';\nimport { SUCCESS_FEEDBACK } from '../../../utilities/feedback';\nimport Title from '../../../components/Title';\nimport '@react-pdf-viewer/core/lib/styles/index.css';\n/* eslint-disable-next-line */\nimport \"../../../components/Themes/index.js\";\n\nconst style = {\n root: {\n marginTop: '40px',\n },\n button: {\n marginTop: '20px',\n },\n input: {\n marginBottom: '20px',\n },\n divider: {\n marginTop: '10px',\n marginBottom: '10px',\n },\n};\n\nconst Profil = () => {\n const [, setFeedback] = useFeedback();\n const [profil, setProfil] = useState({\n name: '',\n theme: 'ambiance',\n font_size: 18,\n max_lines: 30,\n });\n const [errors, setErrors] = useState({\n name: '',\n theme: '',\n font_size: '',\n max_lines: '',\n });\n\n const [, executePatch] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/profil`,\n method: 'PATCH',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const [, fetchProfil] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/profil`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n { manual: true }\n );\n\n const updateProfil = () => {\n executePatch({ data: profil })\n .then(() => {\n setErrors({});\n setFeedback(\n SUCCESS_FEEDBACK({\n message: 'Profil updated',\n })\n );\n Cookies.set('theme', profil.theme);\n Cookies.set('font_size', profil.font_size);\n Cookies.set('max_lines', profil.max_lines);\n })\n .catch((error) => {\n setErrors(error.response.data);\n });\n };\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setProfil({ ...profil, [name]: value });\n };\n\n useEffect(() => {\n fetchProfil().then(({ data }) => setProfil({ ...profil, ...data }));\n }, []);\n\n return (\n \n \n \n \n \n \n Your personal API key is : {Cookies.get('api_key')} \n \n \n \n \n \n \n \n Theme \n \n Ambiance \n Chaos \n Chrome \n Clouds Midnight \n Clouds \n Cobalt \n Crimson Editor \n Dawn \n Dracula \n Dreamweaver \n Eclipse \n Github \n Gob \n Gruvbox \n Idel Fingers \n Iplastic \n KR Theme \n Kuroir \n Merbivore Soft \n Merbivore \n Mono Industrial \n Monokai \n Nord Dark \n One Dark \n Pastel On Dark \n Solarized Dark \n Solarized Light \n SQL Server \n Terminal \n Textmate \n Tomorrow Night Blue \n Tomorrow Night Bright \n Tomorrow Night Eighties \n Tomorrow Night \n Tomorrow \n Twilight \n Vibrand Ink \n Xcode \n \n \n }\n onClick={() => updateProfil()}\n >\n Save\n \n \n \n Hello World !\"\n height=\"100px\"\n width=\"100%\"\n onChange={null}\n name=\"sample\"\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n highlightActiveLine: true,\n showLineNumbers: true,\n }}\n />\n \n \n \n \n \n \n \n \n );\n};\nexport default Profil;\n","import React, { useState, useEffect } from 'react';\nimport {\n Chart as ChartJS,\n CategoryScale,\n LinearScale,\n PointElement,\n LineElement,\n Title,\n Tooltip,\n Legend,\n} from 'chart.js';\nimport { Alert } from '@mui/material';\nimport { Line } from 'react-chartjs-2';\nimport useAxios from 'axios-hooks';\nimport Loader from '../../../../components/Loader';\n\nChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend);\n\nconst style = {\n chart: {\n maxHeight: '300px',\n },\n};\n\nconst BarCount = () => {\n const options = {\n responsive: true,\n plugins: {\n legend: {\n position: 'top',\n },\n title: {\n display: true,\n text: 'Documents',\n },\n },\n };\n\n const [labels, setLabels] = useState([]);\n const [dataset, setDataset] = useState({\n labels,\n datasets: [\n {\n label: 'Created',\n data: [],\n borderColor: 'rgb(255, 99, 132)',\n backgroundColor: 'rgba(255, 99, 132, 0.5)',\n },\n ],\n });\n\n const [{ data, loading }] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/stats/count`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n useEffect(() => {\n if (data) {\n const tmpLabels = [];\n const tmpValues = [];\n /* eslint-disable-next-line */\n for (const [key, value] of Object.entries(data)) {\n tmpLabels.push(key);\n tmpValues.push(value);\n }\n setLabels(tmpLabels);\n setDataset((prevChart) => ({\n ...prevChart,\n labels: tmpLabels,\n datasets: [{ ...prevChart.datasets[0], data: tmpValues }],\n }));\n }\n }, [data]);\n\n return (\n <>\n {loading && }\n {!loading && dataset.datasets[0].data.length !== 0 ? (\n \n ) : (\n No data available \n )}\n >\n );\n};\nexport default BarCount;\n","import React, { useState, useEffect, Fragment } from 'react';\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';\nimport { Alert } from '@mui/material';\nimport { Doughnut } from 'react-chartjs-2';\nimport useAxios from 'axios-hooks';\nimport Loader from '../../../../components/Loader';\n\nChartJS.register(ArcElement, Tooltip, Legend);\n\nconst style = {\n chart: {\n maxHeight: '300px',\n },\n};\n\nconst DoughnutTemplate = () => {\n const options = {\n responsive: true,\n plugins: {\n legend: {\n position: 'top',\n },\n title: {\n display: true,\n text: 'Documents by template',\n },\n },\n };\n\n const [dataset, setDataset] = useState({\n labels: [],\n datasets: [\n {\n label: 'Documents by templates',\n data: [],\n backgroundColor: [\n 'rgba(255, 99, 132, 0.2)',\n 'rgba(54, 162, 235, 0.2)',\n 'rgba(255, 206, 86, 0.2)',\n 'rgba(75, 192, 192, 0.2)',\n 'rgba(153, 102, 255, 0.2)',\n 'rgba(255, 159, 64, 0.2)',\n ],\n borderColor: [\n 'rgba(255, 99, 132, 1)',\n 'rgba(54, 162, 235, 1)',\n 'rgba(255, 206, 86, 1)',\n 'rgba(75, 192, 192, 1)',\n 'rgba(153, 102, 255, 1)',\n 'rgba(255, 159, 64, 1)',\n ],\n borderWidth: 1,\n },\n ],\n });\n\n const [{ data, loading }] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/stats/templates`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n useEffect(() => {\n if (data) {\n const tmpLabels = [];\n const tmpValues = [];\n /* eslint-disable-next-line */\n for (const [key, value] of Object.entries(data)) {\n tmpLabels.push(key);\n tmpValues.push(value);\n }\n setDataset((prevChart) => ({\n ...prevChart,\n labels: tmpLabels,\n datasets: [{ ...prevChart.datasets[0], data: tmpValues }],\n }));\n }\n }, [data]);\n\n return (\n <>\n {loading && }\n {!loading && dataset.datasets[0].data.length !== 0 ? (\n \n ) : (\n No data available \n )}\n >\n );\n};\nexport default DoughnutTemplate;\n","import React from 'react';\nimport {\n Card,\n CardContent,\n Grid,\n Typography,\n Alert,\n LinearProgress,\n Box,\n Link,\n} from '@mui/material';\nimport useAxios from 'axios-hooks';\nimport Moment from 'react-moment';\nimport BarCount from './components/BarCount';\nimport DoughnutTemplate from './components/DoughnutTemplate';\n\nconst style = {\n chart: {},\n title: {\n textAlign: 'center',\n },\n counter: {\n textAlign: 'center',\n fontSize: '35px',\n },\n};\n\nconst Statistics = () => {\n const [{ data: templateCounter }] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/stats/templates_count`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const [{ data: documentsCounter }] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/stats/documents_count`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const [{ data: plan }] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/plans`,\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n },\n {\n useCache: false,\n }\n );\n\n const getColor = () => {\n if (plan.document_counter === plan.document) {\n return 'error';\n }\n if ((plan.document_counter / plan.document) * 100 > 80) {\n return 'warning';\n }\n return 'success';\n };\n\n return (\n \n {plan && plan.label === 'AppSumo' && (\n \n \n <>\n You are currently in AppSumo special plan (49€ for one year){` `}\n \n [ Change plan]\n \n >\n \n \n )}\n {!localStorage.getItem('app') && (\n \n Get started, create your first app... \n \n )}\n {plan && plan.label === 'Trial' && (\n \n \n <>\n Your free trial expire at {` `}\n \n \n {` `}\n \n \n [ Upgrade]\n \n >\n \n \n )}\n {plan && plan.label === 'Free' && (\n \n \n <>\n Your free Trial is expired. \n Your have been downgraded to free plan.{` `}\n \n [ Upgrade]\n \n >\n \n \n )}\n \n \n \n \n Templates\n \n \n {/* eslint-disable-next-line */}\n {templateCounter ? templateCounter : 0}\n \n \n \n \n \n \n \n theme.palette.success.main }}\n style={style.title}\n >\n Documents published\n \n theme.palette.success.main }}\n style={style.counter}\n >\n {documentsCounter && documentsCounter.created ? documentsCounter.created : 0}\n \n \n \n \n \n \n \n theme.palette.warning.main }}\n style={style.title}\n >\n Generations in progress\n \n theme.palette.warning.main }}\n style={style.counter}\n >\n {documentsCounter && documentsCounter.pending ? documentsCounter.pending : 0}\n \n \n \n \n \n \n \n \n Documents generated\n \n {plan && (\n \n \n \n \n \n \n {` ${Math.round(plan.document_counter)}/${Math.round(plan.document)}`}\n \n \n \n )}\n \n \n \n \n \n \n \n \n \n \n );\n};\nexport default Statistics;\n","import React from 'react';\nimport {\n Container,\n Grid,\n Card,\n CardHeader,\n CardContent,\n Box,\n Typography,\n CardActions,\n Button,\n GlobalStyles,\n Alert,\n} from '@mui/material';\nimport StarIcon from '@mui/icons-material/StarBorder';\nimport Title from '../../../components/Title';\nimport { usePlan } from '../../../hooks/usePlan';\n\nconst tiers = [\n {\n title: 'Free',\n price: '0',\n description: [\n '1 application',\n 'Unlimited templates',\n '400 documents per month',\n '1 user',\n 'Email support',\n ],\n buttonText: 'Choose this plan',\n buttonVariant: 'outlined',\n },\n {\n title: 'Pro',\n subheader: 'Most popular',\n price: '20',\n description: [\n '5 applications',\n 'Unlimited templates',\n '3 000 documents per month',\n '5 users (coming soon)',\n 'Email and chat support',\n ],\n buttonText: 'Choose this plan',\n buttonVariant: 'contained',\n },\n {\n title: 'Enterprise',\n price: '250',\n description: [\n 'Unlimited application',\n 'Unlimited templates',\n '20 000 documents per month',\n '10 users (coming soon)',\n 'Email and phone support',\n ],\n buttonText: 'Choose this plan',\n buttonVariant: 'outlined',\n },\n];\n\nconst ChoosePlan = () => {\n const [plan] = usePlan();\n\n const upgrade = (choice) => {\n if (choice === 'Pro') {\n window.open('https://buy.stripe.com/5kA3eo9XH1q5b5u8ww', '_blank');\n }\n if (choice === 'Enterprise') {\n window.open('https://buy.stripe.com/bIYcOYfi10m14H6fYZ', '_blank');\n }\n if (choice === 'AppSumo') {\n window.open('https://buy.stripe.com/cN216g2vf4Ch6PefZ0', '_blank');\n }\n };\n\n return (\n <>\n \n \n {plan && plan.label === 'AppSumo' && (\n \n \n You are currently in AppSumo special plan (49€ for one year)\n \n \n )}\n \n \n {tiers.map((tier) => (\n // Enterprise card is full width at sm breakpoint\n \n \n : null}\n subheaderTypographyProps={{\n align: 'center',\n }}\n sx={{\n /* eslint-disable-next-line */\n backgroundColor: (theme) =>\n theme.palette.mode === 'light'\n ? theme.palette.primary.main\n : theme.palette.primary.main,\n }}\n />\n \n \n \n {tier.price}€\n \n \n {tier.title === 'AppSumo' ? '/year' : '/mo'}\n \n \n \n {tier.description.map((line) => (\n \n {line}\n \n ))}\n \n \n \n {tier.title !== 'Free' ? (\n upgrade(tier.title)}\n disabled={tier.title === plan.label}\n >\n {tier.title === plan.label ? 'Current plan' : tier.buttonText}\n \n ) : (\n
\n )}\n \n \n \n ))}\n \n \n >\n );\n};\nexport default ChoosePlan;\n","export default __webpack_public_path__ + \"static/media/success.674167bb.png\";","import React from 'react';\nimport { Typography, Container } from '@mui/material';\nimport success from '../../../assets/success.png';\n\nconst SuccessPlan = () => {\n return (\n \n Your account has been updated ! \n \n Thank you for your subscription. If you have any question,you can contact us at{` `}\n contact@fastpdf.io \n \n \n \n );\n};\nexport default SuccessPlan;\n","import React from 'react';\nimport { Routes, Route } from 'react-router-dom';\nimport TemplatesList from '../../containers/Templates/List';\nimport TemplateNew from '../../containers/Templates/New';\nimport TemplateInit from '../../containers/Templates/Init';\nimport DocumentsList from '../../containers/Documents/List';\nimport DocumentInit from '../../containers/Documents/Init';\nimport DocumentNew from '../../containers/Documents/New';\nimport WebhooksList from '../../containers/Webhooks/List';\nimport WebhookNew from '../../containers/Webhooks/New';\nimport AppsList from '../../containers/Apps/List';\nimport AppNew from '../../containers/Apps/New';\nimport Profil from '../../containers/Users/Profil';\nimport Statistics from '../../containers/Statistics';\nimport ChoosePlan from '../../containers/Plans/Choose';\nimport SuccessPlan from '../../containers/Plans/Success';\n\nconst Routing = () => {\n return (\n \n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n \n );\n};\nexport default Routing;\n","import React from 'react';\nimport {\n styled,\n useTheme,\n Box,\n Drawer as MuiDrawer,\n AppBar as MuiAppBar,\n Toolbar,\n List,\n CssBaseline,\n Typography,\n Divider,\n IconButton,\n ListItem,\n ListItemIcon,\n ListItemText,\n Tooltip,\n} from '@mui/material';\nimport { NavLink } from 'react-router-dom';\nimport { useNavigate } from 'react-router';\nimport MenuIcon from '@mui/icons-material/Menu';\nimport LogoutIcon from '@mui/icons-material/Logout';\nimport ChevronLeftIcon from '@mui/icons-material/ChevronLeft';\nimport ChevronRightIcon from '@mui/icons-material/ChevronRight';\nimport PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';\nimport AccountCircleIcon from '@mui/icons-material/AccountCircle';\nimport AppsIcon from '@mui/icons-material/Apps';\nimport SwapHorizIcon from '@mui/icons-material/SwapHoriz';\nimport NoteAddIcon from '@mui/icons-material/NoteAdd';\nimport DashboardIcon from '@mui/icons-material/Dashboard';\nimport { logout } from '../../services/axios';\nimport Routing from '../../components/Routing';\n\nconst drawerWidth = 240;\n\nconst openedMixin = (theme) => ({\n width: drawerWidth,\n transition: theme.transitions.create('width', {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.enteringScreen,\n }),\n overflowX: 'hidden',\n});\n\nconst closedMixin = (theme) => ({\n transition: theme.transitions.create('width', {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.leavingScreen,\n }),\n overflowX: 'hidden',\n width: `calc(${theme.spacing(7)} + 1px)`,\n [theme.breakpoints.up('sm')]: {\n width: `calc(${theme.spacing(9)} + 1px)`,\n },\n});\n\nconst DrawerHeader = styled('div')(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n padding: theme.spacing(0, 1),\n // necessary for content to be below app bar\n ...theme.mixins.toolbar,\n}));\n\nconst AppBar = styled(MuiAppBar, {\n shouldForwardProp: (prop) => prop !== 'open',\n})(({ theme, open }) => ({\n zIndex: theme.zIndex.drawer + 1,\n transition: theme.transitions.create(['width', 'margin'], {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.leavingScreen,\n }),\n ...(open && {\n marginLeft: drawerWidth,\n width: `calc(100% - ${drawerWidth}px)`,\n transition: theme.transitions.create(['width', 'margin'], {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.enteringScreen,\n }),\n }),\n}));\n\nconst Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })(\n ({ theme, open }) => ({\n width: drawerWidth,\n flexShrink: 0,\n whiteSpace: 'nowrap',\n boxSizing: 'border-box',\n ...(open && {\n ...openedMixin(theme),\n '& .MuiDrawer-paper': openedMixin(theme),\n }),\n ...(!open && {\n ...closedMixin(theme),\n '& .MuiDrawer-paper': closedMixin(theme),\n }),\n })\n);\n\nconst styles = {\n navlink: {\n textDecoration: 'none',\n color: 'unset',\n },\n};\n\nconst Layout = () => {\n const theme = useTheme();\n const navigate = useNavigate();\n const [open, setOpen] = React.useState(false);\n\n const submitLogout = () => {\n logout();\n navigate('/login');\n };\n\n const handleDrawerOpen = () => {\n setOpen(true);\n };\n\n const handleDrawerClose = () => {\n setOpen(false);\n };\n\n return (\n \n \n \n \n \n \n \n \n FastPDF.io\n \n \n navigate('/app/profil')}\n edge=\"end\"\n sx={{\n marginLeft: '36px',\n }}\n >\n \n \n \n \n \n \n \n \n \n \n \n \n \n {theme.direction === 'rtl' ? : }\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n );\n};\nexport default Layout;\n","import React from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { useFeedback } from '../../hooks/useFeedback';\n\nconst Feedback = () => {\n const [{ open, severity, message }, setFeedback] = useFeedback();\n\n return (\n {\n setFeedback((prevFeedback) => ({ ...prevFeedback, open: false }));\n }}\n >\n {message} \n \n );\n};\n\nexport default Feedback;\n","import React, { useState } from 'react';\nimport {\n Avatar,\n Button,\n CssBaseline,\n TextField,\n Container,\n Typography,\n Alert,\n Collapse,\n CircularProgress,\n Link,\n Box,\n styled,\n Grid,\n} from '@mui/material';\nimport LockOutlinedIcon from '@mui/icons-material/LockOutlined';\nimport useAxios from 'axios-hooks';\nimport Cookies from 'js-cookie';\nimport { useNavigate } from 'react-router';\nimport { usePlan } from '../../../hooks/usePlan';\n\nconst style = {\n avatar: {\n margin: 'auto',\n marginTop: '20px',\n marginBottom: '10px',\n backgroundColor: '#9c27b0',\n },\n typography: {\n marginBottom: '10px',\n },\n submit: {\n marginTop: '20px',\n },\n register: {\n marginTop: '20px',\n display: 'block',\n textDecoration: 'none',\n },\n};\n\nconst Root = styled(Box)(({ theme }) => ({\n margin: 'auto',\n width: '50%',\n textAlign: 'center',\n [theme.breakpoints.down('md')]: {\n width: '90%',\n },\n [theme.breakpoints.up('md')]: {\n width: '30%',\n },\n}));\n\nconst Login = () => {\n const [auth, setAuth] = useState({ email: '', password: '' });\n const [, setPlan] = usePlan();\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const navigate = useNavigate();\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setAuth({ ...auth, [name]: value });\n };\n\n const [, fetchLogin] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/login`,\n method: 'POST',\n },\n { manual: true }\n );\n\n const login = () => {\n setError('');\n setLoading(true);\n fetchLogin({ data: auth }).then((result) => {\n setLoading(false);\n if (result.data.error) {\n setError(result.data.error);\n } else {\n Cookies.set('token', result.data.token);\n Cookies.set('theme', result.data.theme);\n Cookies.set('api_key', result.data.api_key);\n setPlan({\n label: result.data.plan.label,\n app: parseInt(result.data.plan.app, 10),\n app_counter: parseInt(result.data.plan.app_counter, 10),\n document: parseInt(result.data.plan.document, 10),\n document_counter: parseInt(result.data.plan.document_counter, 10),\n });\n if (result.data.app !== false) {\n localStorage.setItem('app', result.data.app);\n }\n navigate('/app/');\n }\n });\n };\n\n return (\n \n \n \n \n \n \n Authentication \n \n {error} \n \n \n \n \n \n \n \n Register\n \n \n \n \n Forgot password ?\n \n \n \n \n \n );\n};\nexport default Login;\n","import React, { useState } from 'react';\nimport {\n Avatar,\n Button,\n CssBaseline,\n TextField,\n Container,\n Typography,\n CircularProgress,\n Link,\n Box,\n styled,\n} from '@mui/material';\nimport LockOutlinedIcon from '@mui/icons-material/LockOutlined';\nimport useAxios from 'axios-hooks';\nimport Cookies from 'js-cookie';\nimport { useNavigate } from 'react-router';\nimport { usePlan } from '../../../hooks/usePlan';\n\nconst style = {\n avatar: {\n margin: 'auto',\n marginTop: '20px',\n marginBottom: '10px',\n backgroundColor: '#9c27b0',\n },\n typography: {\n marginBottom: '10px',\n },\n submit: {\n marginTop: '20px',\n },\n login: {\n marginTop: '20px',\n display: 'block',\n textDecoration: 'none',\n },\n};\n\nconst Root = styled(Box)(({ theme }) => ({\n margin: 'auto',\n width: '50%',\n textAlign: 'center',\n [theme.breakpoints.down('md')]: {\n width: '90%',\n },\n [theme.breakpoints.up('md')]: {\n width: '30%',\n },\n}));\n\nconst Register = () => {\n const [register, setRegister] = useState({ email: '', password: '', appsumo: '' });\n const [, setPlan] = usePlan();\n const [errors, setErrors] = useState({\n email: '',\n password: '',\n password_confirmation: '',\n appsumo: '',\n });\n const [loading, setLoading] = useState(false);\n const navigate = useNavigate();\n\n const handleChange = (e) => {\n const { name, value } = e.target;\n setRegister({ ...register, [name]: value });\n };\n\n const [, postRegister] = useAxios(\n {\n url: `${process.env.REACT_APP_API_URL}/register`,\n method: 'POST',\n },\n { manual: true }\n );\n\n const registration = () => {\n setErrors('');\n setLoading(true);\n postRegister({ data: register })\n .then((result) => {\n setLoading(false);\n Cookies.set('token', result.data.token);\n Cookies.set('theme', result.data.theme);\n Cookies.set('api_key', result.data.api_key);\n setPlan({\n label: result.data.plan.label,\n app: parseInt(result.data.plan.app, 10),\n app_counter: parseInt(result.data.plan.app_counter, 10),\n document: parseInt(result.data.plan.document, 10),\n document_counter: parseInt(result.data.plan.document_counter, 10),\n });\n navigate('/app/');\n })\n .catch((error) => {\n setLoading(false);\n setErrors(error.response.data);\n });\n };\n\n return (\n \n \n \n \n \n \n Registration \n \n \n \n \n Already a account ?\n \n \n \n );\n};\nexport default Register;\n","export default __webpack_public_path__ + \"static/media/picture1.7294f3c0.png\";","export default __webpack_public_path__ + \"static/media/picture2.e9bafad9.png\";","export default __webpack_public_path__ + \"static/media/picture3.05a8e4ca.png\";","export default __webpack_public_path__ + \"static/media/picture4.dca3fb58.png\";","export default __webpack_public_path__ + \"static/media/logo.d91cb8c6.png\";","import * as React from 'react';\nimport AppBar from '@mui/material/AppBar';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Card from '@mui/material/Card';\nimport CardActions from '@mui/material/CardActions';\nimport CardContent from '@mui/material/CardContent';\nimport CardHeader from '@mui/material/CardHeader';\nimport CssBaseline from '@mui/material/CssBaseline';\nimport Grid from '@mui/material/Grid';\nimport StarIcon from '@mui/icons-material/StarBorder';\nimport Toolbar from '@mui/material/Toolbar';\nimport Typography from '@mui/material/Typography';\nimport Link from '@mui/material/Link';\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport Container from '@mui/material/Container';\nimport Image from 'material-ui-image';\nimport List from '@mui/material/List';\nimport ListItem from '@mui/material/ListItem';\nimport PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';\nimport ApiIcon from '@mui/icons-material/Api';\nimport FlipCameraAndroidIcon from '@mui/icons-material/FlipCameraAndroid';\nimport QueryStatsIcon from '@mui/icons-material/QueryStats';\nimport { Avatar, ListItemText, ListItemAvatar, Stack, Divider } from '@mui/material';\nimport { purple } from '@mui/material/colors';\nimport { useNavigate } from 'react-router-dom';\nimport { useMediaQuery, useTheme } from '@material-ui/core';\nimport topImage from '../../assets/picture1.png';\nimport feature1 from '../../assets/picture2.png';\nimport feature2 from '../../assets/picture3.png';\nimport feature3 from '../../assets/picture4.png';\nimport logo from '../../assets/logo.png';\n\nconst tiers = [\n {\n title: 'Free',\n price: '0',\n description: [\n '1 application',\n 'Unlimited templates',\n '400 documents per month',\n '1 user',\n 'Email support',\n ],\n buttonText: 'Get started for free',\n buttonVariant: 'outlined',\n },\n {\n title: 'Pro',\n subheader: 'Most popular',\n price: '20',\n description: [\n '5 applications',\n 'Unlimited templates',\n '3 000 documents per month',\n '5 users (coming soon)',\n 'Email and chat support',\n ],\n buttonText: '30 days free trial',\n buttonVariant: 'contained',\n },\n {\n title: 'Enterprise',\n price: '250',\n description: [\n 'Unlimited application',\n 'Unlimited templates',\n '20 000 documents per month',\n '10 users (coming soon)',\n 'Email and phone support',\n ],\n buttonText: 'Contact us',\n buttonVariant: 'outlined',\n },\n];\n\n/* const footers = [\n {\n title: 'Company',\n description: ['Team', 'History', 'Contact us', 'Locations'],\n },\n {\n title: 'Features',\n description: ['Cool stuff', 'Random feature', 'Team feature', 'Developer stuff', 'Another one'],\n },\n {\n title: 'Resources',\n description: ['Resource', 'Resource name', 'Another resource', 'Final resource'],\n },\n {\n title: 'Legal',\n description: ['Privacy policy', 'Terms of use'],\n },\n]; */\n\nconst style = {\n logo: {\n maxHeight: '95px',\n },\n logo_block: {\n marginTop: '-45px',\n },\n mainValue: {\n marginBottom: '50px',\n },\n secondaryValue: {\n marginTop: '25px',\n },\n feature: {\n marginTop: '10px',\n },\n title: {\n marginTop: '20px',\n fontWeight: 'bold',\n },\n img: {\n width: '90%',\n MozBoxShadow: '10px 10px 5px #ccc',\n WebkitBoxShadow: '10px 10px 5px #ccc',\n boxShadow: '10px 10px 5px #ccc',\n MozBorderRadius: '25px',\n WebkitBorderRadius: '25px',\n borderRadius: '5px',\n marginBottom: '10px',\n },\n};\n\nconst Homepage = () => {\n const navigate = useNavigate();\n const theme = useTheme();\n const matches = useMediaQuery(theme.breakpoints.down('sm'));\n\n return (\n <>\n \n \n `1px solid ${theme.palette.divider}` }}\n >\n \n \n {matches ? 'FastPdf.io' : ''}\n \n \n \n Login\n \n \n Get Started for FREE\n \n \n \n \n {!matches && (\n \n \n \n )}\n \n \n \n \n Automate your PDF\n \n generation\n \n \n \n \n FastPDF.io allow you generate PDF files from pre-defined templates and JSON data.\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n \n navigate('/register')}\n >\n Get started for free\n \n navigate('/docs')}>\n Read documentation\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Features\n \n \n \n \n \n \n \n User friendly interface\n \n \n Create and manage PDF templates from HTML/CSS or with\n {` `}our editor to reduce development and support costs (low code).\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n A simple API\n \n \n Use our REST API with JSON data and create dynamic documents in few secondes.\n \n \n \n \n \n \n Live preview\n \n \n Don't waste your time... Use realtime preview and make awesome PDF in few\n minutes.\n \n \n \n \n \n \n \n \n \n Pricing\n \n \n \n Free trial. No credit card required\n \n \n \n \n {tiers.map((tier) => (\n // Enterprise card is full width at sm breakpoint\n \n \n : null}\n subheaderTypographyProps={{\n align: 'center',\n }}\n sx={{\n /* eslint-disable-next-line */\n backgroundColor: (theme) =>\n theme.palette.mode === 'light'\n ? theme.palette.primary.main\n : theme.palette.primary.main,\n }}\n />\n \n \n \n {tier.price}€\n \n \n /mo\n \n \n \n {tier.description.map((line) => (\n \n {line}\n \n ))}\n \n \n \n navigate('/register')}\n >\n {tier.buttonText}\n \n \n \n \n ))}\n \n \n \n {/* Footer */}\n `1px solid ${theme.palette.divider}`,\n mt: 8,\n py: [3, 6],\n }}\n >\n {/* \n {footers.map((footer) => (\n \n \n {footer.title}\n \n \n {footer.description.map((item) => (\n \n \n {item}\n \n \n ))}\n \n \n ))}\n */}\n \n {'Copyright © '}\n \n FastPDF.io\n {' '}\n {new Date().getFullYear()}\n {'.'}\n \n \n {/* End footer */}\n >\n );\n};\nexport default Homepage;\n","import React from 'react';\nimport { Typography, Container, Button } from '@mui/material';\nimport { useNavigate } from 'react-router';\n\nconst style = {\n root: {\n marginTop: '20px',\n marginBottom: '20px',\n },\n h3: {\n borderBottom: '1px solid #1976d2',\n marginBottom: '20px',\n },\n};\n\nconst Account = () => {\n const navigate = useNavigate();\n return (\n <>\n \n \n Getting started\n \n \n \n \n Create your acount\n \n \n To create an account, go to the Register page and fill in you email and password.\n \n \n Once your account created, fill in your credentials in the Sign in page to get\n access to your dashboard.\n \n \n \n \n Create your first app\n \n \n In your dashboard you can create apps that will regroup your templates and documents. To\n create an app, click on Applications in sidebar menu, click on{` `}\n Create an application button and give a name to your app. Then click on{` `}\n Save button.\n \n \n \n navigate('/docs/templates')}\n variant=\"contained\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n Creating templates >\n \n \n >\n );\n};\nexport default Account;\n","export default __webpack_public_path__ + \"static/media/01.c9c6d41d.png\";","export default __webpack_public_path__ + \"static/media/02.0a64c9c4.png\";","export default __webpack_public_path__ + \"static/media/03.9c071748.png\";","import React, { useEffect } from 'react';\nimport { Typography, Container, Button, ListItem, List } from '@mui/material';\nimport { useNavigate } from 'react-router';\nimport img01 from '../../../assets/docs/01.png';\nimport img02 from '../../../assets/docs/02.png';\nimport img03 from '../../../assets/docs/03.png';\n\nconst style = {\n root: {\n marginTop: '20px',\n marginBottom: '20px',\n },\n h3: {\n borderBottom: '1px solid #1976d2',\n marginBottom: '20px',\n },\n img: {\n width: '100%',\n MozBoxShadow: '10px 10px 5px #ccc',\n WebkitBoxShadow: '10px 10px 5px #ccc',\n boxShadow: '10px 10px 5px #ccc',\n MozBorderRadius: '25px',\n WebkitBorderRadius: '25px',\n borderRadius: '5px',\n marginBottom: '10px',\n },\n};\n\nconst Templates = () => {\n const navigate = useNavigate();\n\n useEffect(() => {\n window.scrollTo(0, 0);\n }, []);\n\n return (\n <>\n \n \n Creating templates\n \n \n \n \n Creating a template\n \n \n To create a template, go to the Template page and click on{` `}\n Create a template .\n \n \n Select a application, give a name and choose a template's mode\n \n \n \n \n \n Simple VS advanced mode\n \n \n Simple Mode provide a WYSIWYG component for generating simple PDF template. But you can\n use a JSON payload to provide dynamic data into your template.\n \n \n Advanced Mode is composed of four components : \n \n A HTML editor to structure your PDF \n A CSS editor to style your PDF \n a JSON payload to provide dynamic data in your PDF \n \n A settings component to customize PDF rendering (margins, orientation etc...)\n \n
\n \n \n \n \n Two actions are possible\n \n You can enable/disable preview \n Save template and see live preview \n \n \n navigate('/docs')}\n variant=\"outlined\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n < Creating Account\n \n navigate('/docs/html')}\n variant=\"contained\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n Dynamic data >\n \n \n >\n );\n};\nexport default Templates;\n","export default __webpack_public_path__ + \"static/media/04.94c465ae.png\";","import React, { useEffect } from 'react';\nimport { Typography, Container, Button, ListItem, List } from '@mui/material';\nimport AceEditor from 'react-ace';\nimport { useNavigate } from 'react-router';\nimport img04 from '../../../assets/docs/04.png';\n\nconst style = {\n root: {\n marginTop: '20px',\n marginBottom: '20px',\n },\n h3: {\n borderBottom: '1px solid #1976d2',\n marginBottom: '20px',\n },\n img: {\n width: '100%',\n MozBoxShadow: '10px 10px 5px #ccc',\n WebkitBoxShadow: '10px 10px 5px #ccc',\n boxShadow: '10px 10px 5px #ccc',\n MozBorderRadius: '25px',\n WebkitBorderRadius: '25px',\n borderRadius: '5px',\n marginBottom: '10px',\n },\n};\n\nconst Html = () => {\n const navigate = useNavigate();\n\n useEffect(() => {\n window.scrollTo(0, 0);\n }, []);\n\n return (\n <>\n \n \n HTML editor and Dynamic data\n \n \n \n \n Define your HTML Body\n \n \n The core of a template is HTML. You can structure your document by defining paragraphs\n with <p> or headings with <h1> , <h2> , …. You can\n use <div> , <span> or <img> elements.\n \n You can use lot of HTML tags. \n \n \n \n Dynamic Data with Liquid syntax\n \n \n You can use{` `}\n \n Liquid syntax\n \n {` `}\n to insert dynamic data in your template. Liquid syntax allow you to :\n \n \n Insert content in your template \n Add conditions \n Display list if items \n Use powerful transformations \n
\n \n To add sample data in your template, use Sample data tab\n \n \n \n \n Sample data example\n \n \n We declare variables in a JSON structure :\n \n \n \n Then we use this information in template by calling a variable with @data prefix\n \n Hello {{ @data.name }}\\nMy email is {{ @data.email }}
\"}\n maxLines={Infinity}\n readOnly\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n highlightActiveLine: true,\n showLineNumbers: true,\n }}\n />\n \n You can see result in live preview at the right.\n \n \n \n Full Liquid documentation\n \n \n If you want to go further, you can read the full documenation at{` `}\n \n https://shopify.github.io/liquid/\n \n .\n \n \n \n navigate('/docs/templates')}\n variant=\"outlined\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n < Creating templates\n \n navigate('/docs/styling')}\n variant=\"contained\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n Styling your PDF >\n \n \n >\n );\n};\nexport default Html;\n","export default __webpack_public_path__ + \"static/media/05.e009c0b0.png\";","export default __webpack_public_path__ + \"static/media/06.8bf41973.png\";","import React, { useEffect } from 'react';\nimport { Typography, Container, Button, Box } from '@mui/material';\nimport AceEditor from 'react-ace';\nimport { useNavigate } from 'react-router';\nimport img05 from '../../../assets/docs/05.png';\nimport img06 from '../../../assets/docs/06.png';\n\nconst style = {\n root: {\n marginTop: '20px',\n marginBottom: '20px',\n },\n h3: {\n borderBottom: '1px solid #1976d2',\n marginBottom: '20px',\n },\n img: {\n width: '100%',\n MozBoxShadow: '10px 10px 5px #ccc',\n WebkitBoxShadow: '10px 10px 5px #ccc',\n boxShadow: '10px 10px 5px #ccc',\n MozBorderRadius: '25px',\n WebkitBorderRadius: '25px',\n borderRadius: '5px',\n marginBottom: '10px',\n },\n};\n\nconst Styling = () => {\n const navigate = useNavigate();\n\n useEffect(() => {\n window.scrollTo(0, 0);\n }, []);\n\n return (\n <>\n \n \n Styling your template\n \n \n \n \n Define your CSS style\n \n \n You can style your documents using CSS3 syntax.\n \n \n \n \n You can see result in live preview at the right.\n \n \n \n \n \n Import UI library\n \n \n \n You can import your own CSS file with simply use the @import instruction. It's\n working with font, external css files, backgrounds images etc...\n \n \n \n \n And use it in the HTML editor \n \n Hello {{ data.name }}\\nMy email is {{ @data.email }}
\\nThis is a material button :
\\n\\n
\\n Button \\n \"}\n minLines={10}\n width=\"100%\"\n readOnly\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n highlightActiveLine: true,\n showLineNumbers: true,\n }}\n />\n \n \n \n \n \n navigate('/docs/html')}\n variant=\"outlined\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n < Creating template\n \n navigate('/docs/api')}\n variant=\"contained\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n Using REST API >\n \n \n >\n );\n};\nexport default Styling;\n","import React, { useEffect } from 'react';\nimport { Typography, Container, Button, Alert, List, ListItem } from '@mui/material';\nimport AceEditor from 'react-ace';\nimport { useNavigate } from 'react-router';\n\nconst style = {\n root: {\n marginTop: '20px',\n marginBottom: '20px',\n },\n h3: {\n borderBottom: '1px solid #1976d2',\n marginBottom: '20px',\n },\n alert: {\n marginTop: '10px',\n marginBottom: '10px',\n },\n img: {\n width: '100%',\n MozBoxShadow: '10px 10px 5px #ccc',\n WebkitBoxShadow: '10px 10px 5px #ccc',\n boxShadow: '10px 10px 5px #ccc',\n MozBorderRadius: '25px',\n WebkitBorderRadius: '25px',\n borderRadius: '5px',\n marginBottom: '10px',\n },\n};\n\nconst Api = () => {\n const navigate = useNavigate();\n\n useEffect(() => {\n window.scrollTo(0, 0);\n }, []);\n\n return (\n <>\n \n \n Generating a document with REST API\n \n \n \n \n Get your API key and Template ID\n \n \n For using our API, you need your [API_KEY] and [TEMPLATE_ID] . This\n informations are available in your profil and template's list.\n \n \n Generate a document\n \n \n To generate a document, use this endpoint:{` `}\n https://api.fastpdf.io/api/documents/generate \n {` `}with HTTP POST request. This is a cURL example (with a data payload).\n \n \n \n {/* eslint-disable-next-line */}\n Don't forget to replace [TEMPLATE_ID] and [API_KEY] by your own credentials\n \n \n \n \n API response will look like this :\n \n \n \n \n \n PDF generation is asyncronous.\n \n \n You need to check if your document is ready. For that, call this API endpoint to get your\n document state.\n \n \n A document can have differentes states \n \n \n Draft \n {` `} : Document is a draft\n \n \n Pending \n {` `} : Document is in queue for generation\n \n \n Wip \n {` `} : Document generation in progress\n \n \n Created \n {` `} : PDF document created\n \n \n Error \n {` `} : PDF document generation failed\n \n
\n \n \n navigate('/docs/styling')}\n variant=\"outlined\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n < Styling your template\n \n navigate('/docs/webhook')}\n variant=\"contained\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n Use Webhook >\n \n \n >\n );\n};\nexport default Api;\n","import React, { useEffect } from 'react';\nimport { Typography, Container, Button, Alert } from '@mui/material';\nimport { useNavigate } from 'react-router';\nimport AceEditor from 'react-ace';\n\nconst style = {\n root: {\n marginTop: '20px',\n marginBottom: '20px',\n },\n h3: {\n borderBottom: '1px solid #1976d2',\n marginBottom: '20px',\n },\n img: {\n width: '100%',\n MozBoxShadow: '10px 10px 5px #ccc',\n WebkitBoxShadow: '10px 10px 5px #ccc',\n boxShadow: '10px 10px 5px #ccc',\n MozBorderRadius: '25px',\n WebkitBorderRadius: '25px',\n borderRadius: '5px',\n marginBottom: '10px',\n },\n};\n\nconst Webhook = () => {\n const navigate = useNavigate();\n\n useEffect(() => {\n window.scrollTo(0, 0);\n }, []);\n\n return (\n <>\n \n \n Setting a Webhook\n \n \n \n \n Configure a Webhook\n \n \n Documents generation is asyncronous. So you can configure webhooks to get notified when a\n document's generation is done.\n \n \n Go to the Webhook page and set a target URL. Then click on Save button.\n \n \n That all... When your document is ready, your webhooks will be called using POST request\n with a Content-type: application/json
header with all document's\n informations.\n \n Your webhooks must generate a 200 OK response. \n \n \n \n Testing your Webhook\n \n \n JSON content in your webhooks look like this :\n \n \n \n \n navigate('/docs/api')}\n variant=\"outlined\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n < Using REST API\n \n navigate('/register')}\n variant=\"contained\"\n color=\"secondary\"\n sx={{ margin: '10px' }}\n >\n Create a account ?\n \n \n >\n );\n};\nexport default Webhook;\n","import React from 'react';\nimport {\n Container,\n Box,\n GlobalStyles,\n CssBaseline,\n AppBar,\n Toolbar,\n Typography,\n Link,\n Button,\n Grid,\n List,\n ListItem,\n} from '@mui/material';\nimport { Routes, Route } from 'react-router-dom';\nimport Account from './Account';\nimport Templates from './Templates';\nimport Html from './Html';\nimport Styling from './Styling';\nimport Api from './Api';\nimport Webhook from './Webhook';\n\nconst Documentation = () => {\n return (\n \n \n \n `1px solid ${theme.palette.divider}` }}\n >\n \n \n \n FastPDF.io\n \n \n \n \n Login\n \n \n Get Started for FREE\n \n \n \n \n \n \n \n \n } />\n } />\n } />\n } />\n } />\n } />\n \n \n \n \n Documentation\n \n \n \n \n Getting started\n \n \n \n \n Creating templates\n \n \n \n \n Dynamic data\n \n \n \n \n Styling your PDF\n \n \n \n \n Using REST API\n \n \n \n \n Using Webhook\n \n \n
\n \n \n \n \n );\n};\nexport default Documentation;\n","import React, { useState } from 'react';\nimport axios from 'axios';\nimport {\n TextField,\n Button,\n Container,\n Typography,\n CssBaseline,\n CircularProgress,\n Avatar,\n Link,\n Box,\n styled,\n} from '@mui/material';\nimport Alert from '@mui/material/Alert';\nimport HelpIcon from '@mui/icons-material/HelpOutline';\n\nconst style = {\n avatar: {\n margin: 'auto',\n marginTop: '20px',\n marginBottom: '10px',\n backgroundColor: '#9c27b0',\n },\n typography: {\n marginBottom: '10px',\n },\n submit: {\n marginTop: '20px',\n },\n register: {\n marginTop: '20px',\n display: 'block',\n textDecoration: 'none',\n },\n};\n\nconst Root = styled(Box)(({ theme }) => ({\n margin: 'auto',\n width: '50%',\n textAlign: 'center',\n [theme.breakpoints.down('md')]: {\n width: '90%',\n },\n [theme.breakpoints.up('md')]: {\n width: '30%',\n },\n}));\n\nconst ForgotForm = () => {\n const [email, setEmail] = useState('');\n const [emailSent, setEmailSent] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const submitEmail = () => {\n setLoading(true);\n axios.post(`${process.env.REACT_APP_API_URL}/password/forgot`, { email }).finally(() => {\n setLoading(false);\n setEmailSent(true);\n });\n };\n\n return (\n \n \n \n \n \n \n Forgot password ? \n {emailSent === false && (\n \n )}\n {emailSent && (\n \n If your account exists, you will receive an email with instructions for reset your\n password.\n \n )}\n \n \n Go back\n \n \n \n \n );\n};\nexport default ForgotForm;\n","import React, { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n TextField,\n CircularProgress,\n Avatar,\n Button,\n Container,\n CssBaseline,\n Typography,\n Link,\n Collapse,\n} from '@mui/material';\nimport Alert from '@mui/material/Alert';\nimport HelpIcon from '@mui/icons-material/HelpOutline';\nimport axios from 'axios';\n\nconst style = {\n root: {\n margin: 'auto',\n width: '50%',\n textAlign: 'center',\n },\n avatar: {\n margin: 'auto',\n marginTop: '20px',\n marginBottom: '10px',\n },\n typography: {\n marginBottom: '10px',\n },\n submit: {\n marginTop: '20px',\n },\n register: {\n marginTop: '20px',\n display: 'block',\n textDecoration: 'none',\n },\n alert: {\n marginBottom: '20px',\n },\n};\n\nconst ResetForm = () => {\n const { token } = useParams();\n const [password, setPassword] = useState('');\n const [passwordConfirmation, setPasswordConfirmation] = useState('');\n const [showError, setShowError] = useState(false);\n const [loading, setLoading] = useState(false);\n const [showSuccess, setShowSuccess] = useState(false);\n\n const submitPassword = () => {\n setLoading(true);\n if (password !== passwordConfirmation) {\n setShowError(true);\n setLoading(false);\n } else {\n const params = {\n password,\n token,\n };\n\n axios\n .post(`${process.env.REACT_APP_API_URL}/password/reset`, params)\n .then((_response) => {\n setShowSuccess(true);\n setShowError(false);\n })\n .catch((_e) => {\n setShowError(false);\n })\n .finally(() => {\n setLoading(false);\n });\n }\n };\n\n return (\n \n \n \n \n \n \n Reset your password \n {showError && (\n \n \n Password confirmation is incorrect\n \n \n )}\n {showSuccess && (\n \n Your password has been reset.\n \n )}\n {showSuccess === false && (\n \n )}\n \n \n Login page\n \n \n \n \n );\n};\nexport default ResetForm;\n","import React from 'react';\nimport { BrowserRouter as Router, Routes, Route } from 'react-router-dom';\nimport { Helmet } from 'react-helmet';\nimport './App.css';\nimport './services/axios';\nimport Layout from './containers/Layout';\nimport { FeedbackProvider } from './contexts/FeedbackContext';\nimport { PlanProvider } from './contexts/PlanContext';\nimport Feedback from './components/Feedback';\nimport Login from './containers/Authentification/Login';\nimport Register from './containers/Authentification/Register';\nimport Homepage from './containers/Homepage';\nimport Documentation from './containers/Documentation';\nimport ForgotForm from './containers/Authentification/ForgotForm';\nimport ResetForm from './containers/Authentification/ResetForm';\nimport logo from './assets/logo.png';\n\nexport default function App() {\n return (\n \n \n \n FastPDF.io - Automate your PDF generation \n \n \n \n \n \n \n {/* */}\n \n \n \n \n \n } />\n } />\n } />\n } />\n } />\n } />\n } />\n \n \n \n \n \n );\n}\n","const reportWebVitals = (onPerfEntry) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n};\n\nexport default reportWebVitals;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport reportWebVitals from './reportWebVitals';\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n"],"sourceRoot":""}