mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-19 14:09:31 +02:00
chore: use monaco editor
This commit is contained in:
37
.idea/workspace.xml
generated
37
.idea/workspace.xml
generated
@@ -4,17 +4,24 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="docs: translation docs">
|
||||
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="fix: json comparison">
|
||||
<change afterPath="$PROJECT_DIR$/src/components/input/ToolCodeInput.tsx" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/components/Navbar/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/Navbar/index.tsx" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/components/input/LineNumberInput.tsx" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/tools/json/json-comparison/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/json/json-comparison/index.tsx" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ChangesViewManager">
|
||||
<option name="groupingKeys">
|
||||
<option value="directory" />
|
||||
</option>
|
||||
</component>
|
||||
<component name="Git.Merge.Settings">
|
||||
<option name="BRANCH" value="origin/main" />
|
||||
</component>
|
||||
@@ -272,7 +279,7 @@
|
||||
"Vitest.replaceText function (regexp mode).should return the original text when passed an invalid regexp.executor": "Run",
|
||||
"Vitest.replaceText function.executor": "Run",
|
||||
"Vitest.timeBetweenDates.executor": "Run",
|
||||
"git-widget-placeholder": "#190 on fork/AshAnand34/en-hi-translation",
|
||||
"git-widget-placeholder": "#197 on fork/bhavesh158/json-compare",
|
||||
"ignore.virus.scanning.warn.message": "true",
|
||||
"kotlin-language-version-configured": "true",
|
||||
"last_opened_file_path": "C:/Users/Ibrahima/IdeaProjects/omni-tools",
|
||||
@@ -519,14 +526,6 @@
|
||||
<workItem from="1752493585622" duration="11629000" />
|
||||
<workItem from="1752507105323" duration="9008000" />
|
||||
</task>
|
||||
<task id="LOCAL-00184" summary="refactor: lib">
|
||||
<option name="closed" value="true" />
|
||||
<created>1743644942488</created>
|
||||
<option name="number" value="00184" />
|
||||
<option name="presentableId" value="LOCAL-00184" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1743644942488</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00185" summary="fix: path">
|
||||
<option name="closed" value="true" />
|
||||
<created>1743645074051</created>
|
||||
@@ -911,7 +910,15 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1752515675314</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="233" />
|
||||
<task id="LOCAL-00233" summary="fix: json comparison">
|
||||
<option name="closed" value="true" />
|
||||
<created>1752803825523</created>
|
||||
<option name="number" value="00233" />
|
||||
<option name="presentableId" value="LOCAL-00233" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1752803825523</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="234" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@@ -958,7 +965,6 @@
|
||||
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
||||
<option name="CHECK_NEW_TODO" value="false" />
|
||||
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
||||
<MESSAGE value="chore: new logo and font" />
|
||||
<MESSAGE value="chore: white logo" />
|
||||
<MESSAGE value="chore: png icon" />
|
||||
<MESSAGE value="fix: remove xml viewer" />
|
||||
@@ -983,7 +989,8 @@
|
||||
<MESSAGE value="fix: translation related behaviors" />
|
||||
<MESSAGE value="feat: password generator to test translation" />
|
||||
<MESSAGE value="docs: translation docs" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="docs: translation docs" />
|
||||
<MESSAGE value="fix: json comparison" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="fix: json comparison" />
|
||||
</component>
|
||||
<component name="VgoProject">
|
||||
<integration-enabled>false</integration-enabled>
|
||||
|
37
package-lock.json
generated
37
package-lock.json
generated
@@ -15,6 +15,7 @@
|
||||
"@ffmpeg/util": "^0.12.2",
|
||||
"@imgly/background-removal": "^1.6.0",
|
||||
"@jimp/types": "^1.6.0",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@mui/icons-material": "^5.15.20",
|
||||
"@mui/material": "^5.15.20",
|
||||
"@playwright/test": "^1.45.0",
|
||||
@@ -2104,6 +2105,29 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@monaco-editor/loader": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz",
|
||||
"integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"state-local": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@monaco-editor/react": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz",
|
||||
"integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@monaco-editor/loader": "^1.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"monaco-editor": ">= 0.25.0 < 1",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/base": {
|
||||
"version": "5.0.0-beta.40",
|
||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz",
|
||||
@@ -8902,6 +8926,13 @@
|
||||
"ufo": "^1.5.3"
|
||||
}
|
||||
},
|
||||
"node_modules/monaco-editor": {
|
||||
"version": "0.52.2",
|
||||
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
|
||||
"integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/morsee": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/morsee/-/morsee-1.0.9.tgz",
|
||||
@@ -11271,6 +11302,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/state-local": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
|
||||
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/std-env": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz",
|
||||
|
@@ -35,6 +35,7 @@
|
||||
"@ffmpeg/util": "^0.12.2",
|
||||
"@imgly/background-removal": "^1.6.0",
|
||||
"@jimp/types": "^1.6.0",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@mui/icons-material": "^5.15.20",
|
||||
"@mui/material": "^5.15.20",
|
||||
"@playwright/test": "^1.45.0",
|
||||
|
@@ -1,127 +0,0 @@
|
||||
import { Box, styled, TextField } from '@mui/material';
|
||||
import React, { useContext, useRef } from 'react';
|
||||
import { CustomSnackBarContext } from '../../contexts/CustomSnackBarContext';
|
||||
import InputHeader from '../InputHeader';
|
||||
import InputFooter from './InputFooter';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const LineNumberWrapper = styled(Box)(({ theme }) => ({
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
'.line-numbers': {
|
||||
whiteSpace: 'pre',
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: '40px',
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
borderRight: `1px solid ${theme.palette.divider}`,
|
||||
textAlign: 'right',
|
||||
paddingRight: '8px',
|
||||
paddingTop: '16px', // Align with TextField content
|
||||
paddingBottom: '8px',
|
||||
color: theme.palette.text.secondary,
|
||||
userSelect: 'none',
|
||||
fontSize: '14px',
|
||||
lineHeight: '1.5em',
|
||||
fontFamily: 'monospace',
|
||||
zIndex: 1,
|
||||
overflow: 'hidden'
|
||||
},
|
||||
'.MuiTextField-root': {
|
||||
position: 'relative',
|
||||
'& .MuiInputBase-root': {
|
||||
paddingLeft: '48px',
|
||||
fontFamily: 'monospace',
|
||||
fontSize: '14px',
|
||||
lineHeight: '1.5em'
|
||||
},
|
||||
'& .MuiInputBase-input': {
|
||||
lineHeight: '1.5em'
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
export default function LineNumberInput({
|
||||
value,
|
||||
onChange,
|
||||
title = 'Input text',
|
||||
placeholder
|
||||
}: {
|
||||
title?: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
placeholder?: string;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { showSnackBar } = useContext(CustomSnackBarContext);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleCopy = () => {
|
||||
navigator.clipboard
|
||||
.writeText(value)
|
||||
.then(() => showSnackBar(t('toolTextInput.copied'), 'success'))
|
||||
.catch((err) => {
|
||||
showSnackBar(t('toolTextInput.copyFailed', { error: err }), 'error');
|
||||
});
|
||||
};
|
||||
|
||||
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = event.target.files?.[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const text = e.target?.result;
|
||||
if (typeof text === 'string') {
|
||||
onChange(text);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
};
|
||||
|
||||
const handleImportClick = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
// Generate line numbers based on the content
|
||||
const lineCount = value.split('\n').length;
|
||||
const lineNumbers = Array.from({ length: lineCount }, (_, i) => i + 1).join(
|
||||
'\n'
|
||||
);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<InputHeader title={title || t('toolTextInput.input')} />
|
||||
<LineNumberWrapper>
|
||||
<pre className="line-numbers">{lineNumbers}</pre>
|
||||
<TextField
|
||||
value={value}
|
||||
onChange={(event) => onChange(event.target.value)}
|
||||
fullWidth
|
||||
multiline
|
||||
rows={10}
|
||||
placeholder={placeholder || t('toolTextInput.placeholder')}
|
||||
sx={{
|
||||
'&.MuiTextField-root': {
|
||||
backgroundColor: 'background.paper'
|
||||
}
|
||||
}}
|
||||
inputProps={{
|
||||
'data-testid': 'text-input'
|
||||
}}
|
||||
/>
|
||||
</LineNumberWrapper>
|
||||
<InputFooter handleCopy={handleCopy} handleImport={handleImportClick} />
|
||||
<input
|
||||
type="file"
|
||||
accept="*"
|
||||
ref={fileInputRef}
|
||||
style={{ display: 'none' }}
|
||||
onChange={handleFileChange}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
73
src/components/input/ToolCodeInput.tsx
Normal file
73
src/components/input/ToolCodeInput.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React, { useContext, useRef } from 'react';
|
||||
import { CustomSnackBarContext } from '../../contexts/CustomSnackBarContext';
|
||||
import InputHeader from '../InputHeader';
|
||||
import InputFooter from './InputFooter';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Editor from '@monaco-editor/react';
|
||||
import { globalInputHeight } from '../../config/uiConfig';
|
||||
|
||||
export default function ToolCodeInput({
|
||||
value,
|
||||
onChange,
|
||||
title = 'Input text',
|
||||
language
|
||||
}: {
|
||||
title?: string;
|
||||
value: string;
|
||||
language: string;
|
||||
onChange: (value: string) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { showSnackBar } = useContext(CustomSnackBarContext);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleCopy = () => {
|
||||
navigator.clipboard
|
||||
.writeText(value)
|
||||
.then(() => showSnackBar(t('toolTextInput.copied'), 'success'))
|
||||
.catch((err) => {
|
||||
showSnackBar(t('toolTextInput.copyFailed', { error: err }), 'error');
|
||||
});
|
||||
};
|
||||
|
||||
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = event.target.files?.[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const text = e.target?.result;
|
||||
if (typeof text === 'string') {
|
||||
onChange(text);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
};
|
||||
|
||||
const handleImportClick = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<InputHeader title={title || t('toolTextInput.input')} />
|
||||
<Box height={globalInputHeight}>
|
||||
<Editor
|
||||
height={'87%'}
|
||||
language={language}
|
||||
value={value}
|
||||
onChange={(value) => onChange(value ?? '')}
|
||||
/>
|
||||
<InputFooter handleCopy={handleCopy} handleImport={handleImportClick} />
|
||||
<input
|
||||
type="file"
|
||||
accept="*"
|
||||
ref={fileInputRef}
|
||||
style={{ display: 'none' }}
|
||||
onChange={handleFileChange}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
@@ -1,42 +1,10 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
import LineNumberInput from '@components/input/LineNumberInput';
|
||||
import ToolCodeInput from '@components/input/ToolCodeInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import { compareJson } from './service';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import { Box, Grid, styled } from '@mui/material';
|
||||
|
||||
const StyledContainer = styled(Box)({
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
minHeight: '500px',
|
||||
marginBottom: '20px'
|
||||
});
|
||||
|
||||
const StyledGrid = styled(Grid)({
|
||||
flex: 1,
|
||||
'& .MuiGrid-item': {
|
||||
height: '100%'
|
||||
}
|
||||
});
|
||||
|
||||
const StyledInputWrapper = styled(Box)({
|
||||
height: '100%',
|
||||
'& > div': {
|
||||
height: '100%',
|
||||
'& textarea': {
|
||||
height: '100% !important',
|
||||
minHeight: '450px',
|
||||
resize: 'none',
|
||||
fontSize: '14px',
|
||||
lineHeight: '1.5',
|
||||
padding: '12px'
|
||||
}
|
||||
}
|
||||
});
|
||||
import { Grid } from '@mui/material';
|
||||
|
||||
type InitialValuesType = {};
|
||||
|
||||
@@ -73,8 +41,8 @@ export default function JsonComparison({ title }: ToolComponentProps) {
|
||||
compareInputs();
|
||||
}, [input1, input2]);
|
||||
|
||||
const handleInput1Change = (value: string) => {
|
||||
setInput1(value);
|
||||
const handleInput1Change = (value: string | undefined) => {
|
||||
setInput1(value ?? '');
|
||||
};
|
||||
|
||||
const handleInput2Change = (value: string) => {
|
||||
@@ -90,39 +58,31 @@ export default function JsonComparison({ title }: ToolComponentProps) {
|
||||
getGroups={null}
|
||||
compute={() => {}}
|
||||
inputComponent={
|
||||
<StyledContainer>
|
||||
<StyledGrid container spacing={2}>
|
||||
<Grid item xs={4}>
|
||||
<StyledInputWrapper>
|
||||
<LineNumberInput
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} md={6} lg={4}>
|
||||
<ToolCodeInput
|
||||
title="First JSON"
|
||||
value={input1}
|
||||
onChange={handleInput1Change}
|
||||
placeholder="Paste your first JSON here..."
|
||||
language={'json'}
|
||||
/>
|
||||
</StyledInputWrapper>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<StyledInputWrapper>
|
||||
<LineNumberInput
|
||||
<Grid item xs={12} md={6} lg={4}>
|
||||
<ToolCodeInput
|
||||
title="Second JSON"
|
||||
language={'json'}
|
||||
value={input2}
|
||||
onChange={handleInput2Change}
|
||||
placeholder="Paste your second JSON here..."
|
||||
/>
|
||||
</StyledInputWrapper>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<StyledInputWrapper>
|
||||
<Grid item xs={12} md={12} lg={4}>
|
||||
<ToolTextResult
|
||||
title="Differences"
|
||||
value={result}
|
||||
extension={'txt'}
|
||||
/>
|
||||
</StyledInputWrapper>
|
||||
</Grid>
|
||||
</StyledGrid>
|
||||
</StyledContainer>
|
||||
</Grid>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
Reference in New Issue
Block a user