feat: add Nginx configuration editor component and integrate it into the main application interface

This commit is contained in:
Ümit Tunç
2026-03-30 07:41:51 +03:00
parent 702fe9cad0
commit 98295e38ef
4 changed files with 95 additions and 42 deletions
+28
View File
@@ -15,12 +15,15 @@
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^6.0.0",
"@mui/material": "^6.0.0",
"@types/prismjs": "^1.26.6",
"axios": "^1.14.0",
"decompress": "^4.2.1",
"i18next": "^23.1.0",
"prismjs": "^1.30.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^13.0.0",
"react-simple-code-editor": "^0.14.1",
"sweetalert2": "^11.26.24"
},
"devDependencies": {
@@ -2478,6 +2481,12 @@
"xmlbuilder": ">=11.0.1"
}
},
"node_modules/@types/prismjs": {
"version": "1.26.6",
"resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.6.tgz",
"integrity": "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==",
"license": "MIT"
},
"node_modules/@types/prop-types": {
"version": "15.7.15",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
@@ -7778,6 +7787,15 @@
"node": ">=6.0.0"
}
},
"node_modules/prismjs": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
"integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -7949,6 +7967,16 @@
"node": ">=0.10.0"
}
},
"node_modules/react-simple-code-editor": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/react-simple-code-editor/-/react-simple-code-editor-0.14.1.tgz",
"integrity": "sha512-BR5DtNRy+AswWJECyA17qhUDvrrCZ6zXOCfkQY5zSmb96BVUbpVAv03WpcjcwtCwiLbIANx3gebHOcXYn1EHow==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+3
View File
@@ -27,12 +27,15 @@
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^6.0.0",
"@mui/material": "^6.0.0",
"@types/prismjs": "^1.26.6",
"axios": "^1.14.0",
"decompress": "^4.2.1",
"i18next": "^23.1.0",
"prismjs": "^1.30.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^13.0.0",
"react-simple-code-editor": "^0.14.1",
"sweetalert2": "^11.26.24"
},
"devDependencies": {
+7 -42
View File
@@ -64,7 +64,6 @@ import {
OpenInNew as OpenIcon,
Edit as EditIcon,
Folder as FolderIcon,
Storage as MySQLIcon,
Language as HostIcon,
Launch as LaunchIcon,
Handyman as ToolsIcon,
@@ -73,6 +72,7 @@ import {
import Swal from 'sweetalert2'
import { useTranslation } from 'react-i18next'
import MySqlImportWizard from './components/MySqlImportWizard'
import NginxCodeEditor from './components/NginxCodeEditor'
declare global {
interface Window {
@@ -108,7 +108,6 @@ function App(): JSX.Element {
const [phpVersions, setPhpVersions] = useState<any[]>([])
const [mySqlVersions, setMySqlVersions] = useState<any[]>([])
const [nginxVersions, setNginxVersions] = useState<any[]>([])
const [loadingVersions, setLoadingVersions] = useState(false)
const [isProjectDialogOpen, setIsProjectDialogOpen] = useState(false)
const slugify = (text: string) => text.toLowerCase().trim().replace(/[^\w\s-]/g, '').replace(/[\s_-]+/g, '-').replace(/^-+|-+$/g, '');
const [newProject, setNewProject] = useState<any>({ name: '', path: '', phpVersion: '', mySqlVersion: '', host: 'localhost' })
@@ -187,14 +186,6 @@ function App(): JSX.Element {
}
}
const handleRefreshVersions = async () => {
setLoadingVersions(true)
try {
await Promise.all([fetchPhpVersions(), fetchMySqlVersions(), fetchNginxVersions()])
} finally {
setLoadingVersions(false)
}
}
useEffect(() => {
if (isProjectDialogOpen && !newProject.id) {
@@ -671,7 +662,7 @@ function App(): JSX.Element {
<Typography variant="body2" color="text.secondary">Gereken PHP sürümlerini buradan indirebilir ve yönetebilirsiniz.</Typography>
</Box>
<List sx={{ maxHeight: 500, overflow: 'auto' }}>
{phpVersions.length === 0 && !loadingVersions && (
{phpVersions.length === 0 && (
<ListItem><ListItemText primary="Yükleniyor veya liste boş..." /></ListItem>
)}
{phpVersions.map((v) => (
@@ -712,7 +703,7 @@ function App(): JSX.Element {
<Typography variant="body2" color="text.secondary">Farklı MySQL sürümlerini indirebilir ve sunucunuzda kullanabilirsiniz.</Typography>
</Box>
<List sx={{ maxHeight: 500, overflow: 'auto' }}>
{mySqlVersions.length === 0 && !loadingVersions && (
{mySqlVersions.length === 0 && (
<ListItem><ListItemText primary="Yükleniyor veya liste boş..." /></ListItem>
)}
{mySqlVersions.map((v) => (
@@ -1417,22 +1408,9 @@ function App(): JSX.Element {
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)', mb: 2, display: 'block' }}>
Dikkat: Hatalı yapılandırma Nginx'in çalışmasını durdurabilir. Değişiklik yapmadan önce test edin.
</Typography>
<TextField
fullWidth
multiline
rows={20}
<NginxCodeEditor
value={nginxConfig}
onChange={(e) => setNginxConfig(e.target.value)}
sx={{
'& .MuiInputBase-root': {
fontFamily: 'monospace',
fontSize: '0.875rem',
color: '#fff'
},
'& .MuiOutlinedInput-notchedOutline': {
borderColor: 'rgba(255,255,255,0.1)'
}
}}
onChange={(val) => setNginxConfig(val)}
/>
</DialogContent>
<DialogActions sx={{ p: 2, gap: 1 }}>
@@ -1481,22 +1459,9 @@ function App(): JSX.Element {
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)', mb: 2, display: 'block' }}>
İpucu: Bu yapılandırma sadece {selectedProjectHost} projesi için geçerlidir.
</Typography>
<TextField
fullWidth
multiline
rows={20}
<NginxCodeEditor
value={projectNginxConfig}
onChange={(e) => setProjectNginxConfig(e.target.value)}
sx={{
'& .MuiInputBase-root': {
fontFamily: 'monospace',
fontSize: '0.875rem',
color: '#fff'
},
'& .MuiOutlinedInput-notchedOutline': {
borderColor: 'rgba(255,255,255,0.1)'
}
}}
onChange={(val) => setProjectNginxConfig(val)}
/>
</DialogContent>
<DialogActions sx={{ p: 2, gap: 1 }}>
@@ -0,0 +1,57 @@
import React from 'react'
import Editor from 'react-simple-code-editor'
import Prism from 'prismjs'
import 'prismjs/components/prism-nginx'
import 'prismjs/themes/prism-tomorrow.css'
interface NginxCodeEditorProps {
value: string
onChange: (value: string) => void
}
const NginxCodeEditor: React.FC<NginxCodeEditorProps> = ({ value, onChange }) => {
return (
<div style={{
borderRadius: '4px',
overflow: 'hidden',
border: '1px solid rgba(255,255,255,0.1)',
backgroundColor: '#1e1e1e',
fontFamily: '"Fira code", "Fira Mono", monospace',
fontSize: '14px',
minHeight: '300px'
}}>
<Editor
value={value}
onValueChange={code => onChange(code)}
highlight={code => Prism.highlight(code, Prism.languages.nginx, 'nginx')}
padding={15}
style={{
fontFamily: '"Fira code", "Fira Mono", monospace',
fontSize: 14,
minHeight: '400px',
outline: 'none'
}}
textareaClassName="nginx-editor-textarea"
preClassName="nginx-editor-pre"
/>
<style>{`
.nginx-editor-textarea {
outline: none !important;
}
.nginx-editor-pre {
pointer-events: none;
}
.token.comment { color: #6a9955; }
.token.directive { color: #569cd6; font-weight: bold; }
.token.variable { color: #9cdcfe; }
.token.string { color: #ce9178; }
.token.number { color: #b5cea8; }
.token.boolean { color: #569cd6; }
.token.operator { color: #d4d4d4; }
.token.punctuation { color: #d4d4d4; }
`}</style>
</div>
)
}
export default NginxCodeEditor