mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-09 17:19:33 +02:00
fix: text split try catch
This commit is contained in:
38
package-lock.json
generated
38
package-lock.json
generated
@@ -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",
|
||||||
|
@@ -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",
|
||||||
|
@@ -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;
|
||||||
|
@@ -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>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
35
src/contexts/CustomSnackBarContext.tsx
Normal file
35
src/contexts/CustomSnackBarContext.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
};
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user