fix: text split try catch

This commit is contained in:
Ibrahima G. Coulibaly
2024-06-21 22:35:56 +01:00
parent 8b58361e1f
commit 94aa86e4db
7 changed files with 161 additions and 57 deletions

38
package-lock.json generated
View File

@@ -15,6 +15,7 @@
"@types/lodash": "^4.17.5", "@types/lodash": "^4.17.5",
"formik": "^2.4.6", "formik": "^2.4.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"notistack": "^3.0.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.23.1", "react-router-dom": "^6.23.1",
@@ -4393,6 +4394,14 @@
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
"dev": true "dev": true
}, },
"node_modules/goober": {
"version": "2.1.14",
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz",
"integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==",
"peerDependencies": {
"csstype": "^3.0.10"
}
},
"node_modules/gopd": { "node_modules/gopd": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@@ -5417,6 +5426,35 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/notistack": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/notistack/-/notistack-3.0.1.tgz",
"integrity": "sha512-ntVZXXgSQH5WYfyU+3HfcXuKaapzAJ8fBLQ/G618rn3yvSzEbnOB8ZSOwhX+dAORy/lw+GC2N061JA0+gYWTVA==",
"dependencies": {
"clsx": "^1.1.0",
"goober": "^2.0.33"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=6.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/notistack"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/notistack/node_modules/clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
"engines": {
"node": ">=6"
}
},
"node_modules/npm-run-path": { "node_modules/npm-run-path": {
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",

View File

@@ -29,6 +29,7 @@
"@types/lodash": "^4.17.5", "@types/lodash": "^4.17.5",
"formik": "^2.4.6", "formik": "^2.4.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"notistack": "^3.0.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.23.1", "react-router-dom": "^6.23.1",

View File

@@ -1,26 +1,41 @@
import { BrowserRouter, useRoutes } from 'react-router-dom' import { BrowserRouter, useRoutes } from 'react-router-dom';
import routesConfig from '../config/routesConfig' import routesConfig from '../config/routesConfig';
import Navbar from './Navbar' import Navbar from './Navbar';
import { Suspense } from 'react' import { Suspense } from 'react';
import Loading from './Loading' import Loading from './Loading';
import { ThemeProvider } from '@mui/material' import { ThemeProvider } from '@mui/material';
import theme from '../config/muiConfig' import theme from '../config/muiConfig';
import { CustomSnackBarProvider } from '../contexts/CustomSnackBarContext';
import { SnackbarProvider } from 'notistack';
const AppRoutes = () => { const AppRoutes = () => {
return useRoutes(routesConfig) return useRoutes(routesConfig);
} };
function App() { function App() {
return ( return (
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<BrowserRouter> <SnackbarProvider
<Navbar /> maxSnack={5}
<Suspense fallback={<Loading />}> anchorOrigin={{
<AppRoutes /> vertical: 'bottom',
</Suspense> horizontal: 'right'
</BrowserRouter> }}
classes={{
containerRoot: 'bottom-0 right-0 mb-52 md:mb-68 mr-8 lg:mr-80 z-99'
}}
>
<CustomSnackBarProvider>
<BrowserRouter>
<Navbar />
<Suspense fallback={<Loading />}>
<AppRoutes />
</Suspense>
</BrowserRouter>
</CustomSnackBarProvider>
</SnackbarProvider>
</ThemeProvider> </ThemeProvider>
) );
} }
export default App export default App;

View File

@@ -1,11 +1,17 @@
import Typography from '@mui/material/Typography' import Typography from '@mui/material/Typography';
import { Box, Stack, TextField } from '@mui/material' import { Box, Stack, TextField } from '@mui/material';
import Button from '@mui/material/Button' import Button from '@mui/material/Button';
import DownloadIcon from '@mui/icons-material/Download' import DownloadIcon from '@mui/icons-material/Download';
import ContentPasteIcon from '@mui/icons-material/ContentPaste' import ContentPasteIcon from '@mui/icons-material/ContentPaste';
import React from 'react' import React from 'react';
export default function ToolTextResult({ title = 'Result', value }: { title?: string; value: string }) { export default function ToolTextResult({
title = 'Result',
value
}: {
title?: string;
value: string;
}) {
return ( return (
<Box> <Box>
<Typography fontSize={30} color={'primary'}> <Typography fontSize={30} color={'primary'}>
@@ -17,5 +23,5 @@ export default function ToolTextResult({ title = 'Result', value }: { title?: st
<Button startIcon={<ContentPasteIcon />}>Copy to clipboard</Button> <Button startIcon={<ContentPasteIcon />}>Copy to clipboard</Button>
</Stack> </Stack>
</Box> </Box>
) );
} }

View File

@@ -1,4 +1,4 @@
import { createTheme } from '@mui/material' import { createTheme } from '@mui/material';
const theme = createTheme({ const theme = createTheme({
typography: { typography: {
@@ -6,7 +6,8 @@ const theme = createTheme({
textTransform: 'none' textTransform: 'none'
} }
}, },
palette: { background: { default: '#ebf5ff' } } palette: { background: { default: '#ebf5ff' } },
}) zIndex: { snackbar: 100000 }
});
export default theme export default theme;

View File

@@ -0,0 +1,35 @@
import { createContext, FC, ReactNode } from 'react';
import { Zoom } from '@mui/material';
import { useSnackbar } from 'notistack';
type CustomSnackBarContext = {
showSnackBar: (message: string, type: 'error' | 'success') => void;
};
// eslint-disable-next-line @typescript-eslint/no-redeclare
export const CustomSnackBarContext = createContext<CustomSnackBarContext>(
{} as CustomSnackBarContext
);
interface Props {
children: ReactNode;
}
export const CustomSnackBarProvider: FC<Props> = ({ children }) => {
const { enqueueSnackbar } = useSnackbar();
const showSnackBar = (message: string, type: 'error' | 'success') => {
enqueueSnackbar(message, {
variant: type,
anchorOrigin: {
vertical: 'top',
horizontal: 'right'
},
TransitionComponent: Zoom
});
};
return (
<CustomSnackBarContext.Provider value={{ showSnackBar }}>
{children}
</CustomSnackBarContext.Provider>
);
};

View File

@@ -3,13 +3,14 @@ import ToolLayout from '../../../components/ToolLayout';
import { Box, Stack, TextField } from '@mui/material'; import { Box, Stack, TextField } from '@mui/material';
import Grid from '@mui/material/Grid'; import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import React, { useEffect, useRef, useState } from 'react'; import React, { useContext, useEffect, useRef, useState } from 'react';
import ToolTextInput from '../../../components/input/ToolTextInput'; import ToolTextInput from '../../../components/input/ToolTextInput';
import ToolTextResult from '../../../components/result/ToolTextResult'; import ToolTextResult from '../../../components/result/ToolTextResult';
import { Field, Formik, FormikProps, useFormikContext } from 'formik'; import { Field, Formik, FormikProps, useFormikContext } from 'formik';
import * as Yup from 'yup'; import * as Yup from 'yup';
import ToolOptions from '../../../components/ToolOptions'; import ToolOptions from '../../../components/ToolOptions';
import { splitIntoChunks, splitTextByLength } from './service'; import { splitIntoChunks, splitTextByLength } from './service';
import { CustomSnackBarContext } from '../../../contexts/CustomSnackBarContext';
type SplitOperatorType = 'symbol' | 'regex' | 'length' | 'chunks'; type SplitOperatorType = 'symbol' | 'regex' | 'length' | 'chunks';
const initialValues = { const initialValues = {
@@ -142,38 +143,45 @@ export default function SplitText() {
const [input, setInput] = useState<string>(''); const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>(''); const [result, setResult] = useState<string>('');
const formRef = useRef<FormikProps<typeof initialValues>>(null); const formRef = useRef<FormikProps<typeof initialValues>>(null);
const { showSnackBar } = useContext(CustomSnackBarContext);
const FormikListenerComponent = () => { const FormikListenerComponent = () => {
const { values } = useFormikContext<typeof initialValues>(); const { values } = useFormikContext<typeof initialValues>();
useEffect(() => { useEffect(() => {
const { try {
splitSeparatorType, const {
outputSeparator, splitSeparatorType,
charBeforeChunk, outputSeparator,
charAfterChunk, charBeforeChunk,
chunksValue, charAfterChunk,
symbolValue, chunksValue,
regexValue, symbolValue,
lengthValue regexValue,
} = values; lengthValue
let splitText; } = values;
switch (splitSeparatorType) { let splitText;
case 'symbol': switch (splitSeparatorType) {
splitText = input.split(symbolValue); case 'symbol':
break; splitText = input.split(symbolValue);
case 'regex': break;
splitText = input.split(new RegExp(regexValue)); case 'regex':
break; splitText = input.split(new RegExp(regexValue));
case 'length': break;
splitText = splitTextByLength(input, Number(lengthValue)); case 'length':
break; splitText = splitTextByLength(input, Number(lengthValue));
case 'chunks': break;
splitText = splitIntoChunks(input, Number(chunksValue)).map( case 'chunks':
(chunk) => `${charBeforeChunk}${chunk}${charAfterChunk}` splitText = splitIntoChunks(input, Number(chunksValue)).map(
); (chunk) => `${charBeforeChunk}${chunk}${charAfterChunk}`
);
}
const res = splitText.join(outputSeparator);
setResult(res);
} catch (exception: unknown) {
if (exception instanceof Error)
showSnackBar(exception.message, 'error');
} }
const res = splitText.join(outputSeparator);
setResult(res);
}, [values, input]); }, [values, input]);
return null; // This component doesn't render anything return null; // This component doesn't render anything