diff --git a/src/main/ipc/index.ts b/src/main/ipc/index.ts
index 848e0e5..505b885 100644
--- a/src/main/ipc/index.ts
+++ b/src/main/ipc/index.ts
@@ -374,14 +374,23 @@ export function registerIpcHandlers(): void {
})
ipcMain.handle('projects:add', async (_event, project) => {
- return projectService.addProject(project)
+ const result = await projectService.addProject(project)
+ // Trigger Nginx reload
+ await ipcMain.emit('services:reload', null, 'nginx')
+ return result
})
ipcMain.handle('projects:remove', async (_event, id) => {
- return projectService.removeProject(id)
+ const result = projectService.removeProject(id)
+ // Trigger Nginx reload
+ await ipcMain.emit('services:reload', null, 'nginx')
+ return result
})
ipcMain.handle('projects:update', async (_event, project) => {
- return projectService.updateProject(project)
+ const result = projectService.updateProject(project)
+ // Trigger Nginx reload
+ await ipcMain.emit('services:reload', null, 'nginx')
+ return result
})
// Config management
@@ -390,7 +399,60 @@ export function registerIpcHandlers(): void {
})
ipcMain.handle('config:save', async (_event, config: any) => {
- return { success: true, settings: configService.updateSettings(config) }
+ const settings = configService.updateSettings(config)
+ return { success: true, settings }
+ })
+
+ // Nginx Config Management
+ ipcMain.handle('nginx:config:get', async () => {
+ const configPath = path.join(configService.getBasePath(), 'generated_configs', 'nginx.conf')
+ if (fs.existsSync(configPath)) {
+ return fs.readFileSync(configPath, 'utf8')
+ }
+ return ''
+ })
+
+ ipcMain.handle('nginx:config:save', async (_event, content) => {
+ const configPath = path.join(configService.getBasePath(), 'generated_configs', 'nginx.conf')
+ fs.writeFileSync(configPath, content)
+ // Reload Nginx after save
+ await ipcMain.emit('services:reload', null, 'nginx')
+ return { success: true }
+ })
+
+ ipcMain.handle('nginx:config:test', async () => {
+ try {
+ const binDir = path.join(configService.getBasePath(), 'bin', 'nginx')
+ const nginxVersions = fs.readdirSync(binDir).filter(f => fs.statSync(path.join(binDir, f)).isDirectory())
+ const activeVersion = nginxVersions[0]
+ if (!activeVersion) throw new Error('Nginx not found')
+
+ const nginxPrefix = path.join(binDir, activeVersion)
+ const binPath = path.join(nginxPrefix, 'nginx.exe')
+ const configPath = path.join(configService.getBasePath(), 'generated_configs', 'nginx.conf')
+
+ const success = await processManager.runOnce(binPath, ['-t', '-p', nginxPrefix, '-c', configPath], 'nginx')
+ return { success, message: success ? 'Configuration test successful' : 'Configuration test failed' }
+ } catch (error: any) {
+ return { success: false, message: error.message }
+ }
+ })
+
+ // Project Nginx Config
+ ipcMain.handle('project:nginx:get', async (_event, host) => {
+ const configPath = path.join(configService.getBasePath(), 'generated_configs', 'projects', `${host}.conf`)
+ if (fs.existsSync(configPath)) {
+ return fs.readFileSync(configPath, 'utf8')
+ }
+ return ''
+ })
+
+ ipcMain.handle('project:nginx:save', async (_event, host, content) => {
+ const configPath = path.join(configService.getBasePath(), 'generated_configs', 'projects', `${host}.conf`)
+ fs.writeFileSync(configPath, content)
+ // Reload Nginx after save
+ await ipcMain.emit('services:reload', null, 'nginx')
+ return { success: true }
})
// phpMyAdmin
diff --git a/src/preload/index.ts b/src/preload/index.ts
index a8bb2e9..03e3857 100644
--- a/src/preload/index.ts
+++ b/src/preload/index.ts
@@ -35,7 +35,8 @@ const api = {
const listener = (_event, msg) => callback(msg)
electronAPI.ipcRenderer.on('mysql:import:log', listener)
return () => electronAPI.ipcRenderer.removeListener('mysql:import:log', listener)
- }
+ },
+ invoke: (channel: string, ...args: any[]) => electronAPI.ipcRenderer.invoke(channel, ...args)
}
// Use `contextBridge` APIs to expose Electron APIs to
diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx
index a24db7b..83d00d2 100644
--- a/src/renderer/src/App.tsx
+++ b/src/renderer/src/App.tsx
@@ -132,6 +132,11 @@ function App(): JSX.Element {
const [pmaLoading, setPmaLoading] = useState(false)
const [pmaProgress, setPmaProgress] = useState(0)
const [isMySqlWizardOpen, setIsMySqlWizardOpen] = useState(false)
+ const [isNginxConfigOpen, setIsNginxConfigOpen] = useState(false)
+ const [nginxConfig, setNginxConfig] = useState('')
+ const [isProjectNginxConfigOpen, setIsProjectNginxConfigOpen] = useState(false)
+ const [projectNginxConfig, setProjectNginxConfig] = useState('')
+ const [selectedProjectHost, setSelectedProjectHost] = useState('')
const fetchStatus = async () => {
if (window.api && window.api.getServiceStatus) {
@@ -442,9 +447,74 @@ function App(): JSX.Element {
const handleRemoveProject = async (id: string) => {
if (!window.api) return
- await window.api.removeProject(id)
- setNotification({ open: true, message: 'Proje silindi.', severity: 'success' })
- fetchProjects()
+ const result = await Swal.fire({
+ title: 'Emin misiniz?',
+ text: "Bu projeyi silmek istediğinize emin misiniz? Nginx ayarları otomatik olarak güncellenecektir.",
+ icon: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#ff4444',
+ cancelButtonColor: '#3085d6',
+ confirmButtonText: 'Evet, sil!',
+ cancelButtonText: 'İptal',
+ background: '#1e1e1e',
+ color: '#fff'
+ })
+
+ if (result.isConfirmed) {
+ await window.api.removeProject(id)
+ setNotification({ open: true, message: 'Proje silindi. Nginx yeniden yüklendi.', severity: 'success' })
+ fetchProjects()
+ }
+ }
+
+ const handleOpenNginxConfig = async () => {
+ if (window.api && window.api.invoke) {
+ const config = await window.api.invoke('nginx:config:get')
+ setNginxConfig(config)
+ setIsNginxConfigOpen(true)
+ }
+ }
+
+ const handleSaveNginxConfig = async () => {
+ if (window.api && window.api.invoke) {
+ const result = await window.api.invoke('nginx:config:save', nginxConfig)
+ if (result.success) {
+ setNotification({ open: true, message: 'Nginx yapılandırması kaydedildi ve yeniden yüklendi.', severity: 'success' })
+ setIsNginxConfigOpen(false)
+ }
+ }
+ }
+
+ const handleTestNginxConfig = async () => {
+ if (window.api && window.api.invoke) {
+ const result = await window.api.invoke('nginx:config:test')
+ Swal.fire({
+ title: result.success ? 'Başarılı' : 'Hata',
+ text: result.message,
+ icon: result.success ? 'success' : 'error',
+ background: '#1e1e1e',
+ color: '#fff'
+ })
+ }
+ }
+
+ const handleOpenProjectNginxConfig = async (host: string) => {
+ if (window.api && window.api.invoke) {
+ const config = await window.api.invoke('project:nginx:get', host)
+ setProjectNginxConfig(config)
+ setSelectedProjectHost(host)
+ setIsProjectNginxConfigOpen(true)
+ }
+ }
+
+ const handleSaveProjectNginxConfig = async () => {
+ if (window.api && window.api.invoke) {
+ const result = await window.api.invoke('project:nginx:save', selectedProjectHost, projectNginxConfig)
+ if (result.success) {
+ setNotification({ open: true, message: `${selectedProjectHost} için Nginx yapılandırması kaydedildi.`, severity: 'success' })
+ setIsProjectNginxConfigOpen(false)
+ }
+ }
}
const handleDownloadPhp = async (id: string) => {
@@ -814,6 +884,14 @@ function App(): JSX.Element {
handleOpenLogs('nginx')} title="Hata Logları" size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}>
+
+
+
{
window.api.invoke('services:reload', 'nginx').then((res: any) => {
@@ -1055,6 +1133,11 @@ function App(): JSX.Element {
+
+ handleOpenProjectNginxConfig(project.host)} sx={{ color: 'rgba(255,255,255,0.4)', '&:hover': { color: '#39A7FF' } }}>
+
+
+
handleRemoveProject(project.id)} sx={{ color: 'rgba(255,255,255,0.4)', '&:hover': { color: '#ff4444' } }}>
@@ -1309,7 +1392,127 @@ function App(): JSX.Element {
onClose={() => setIsMySqlWizardOpen(false)}
mySqlVersions={mySqlVersions}
/>
-
+
+
+
+
+
>
)
}