From e7be5c1c197b664cc9cbec9490ffa31a12f2bd31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Cmit=20Tun=C3=A7?= Date: Fri, 3 Apr 2026 06:55:32 +0300 Subject: [PATCH] feat: implement ProcessManager service for lifecycle management and add UI components for dashboard monitoring --- config/apache_project.conf.template | 65 +++++----- config/apache_project.conf.template.bak | 33 +++++ port_mappings.json | 5 +- service_events.json | 115 ++++++++++++++++++ src/main/services/ProcessManager.ts | 28 ++++- .../components/Dashboard/DashboardDetails.tsx | 55 +++++---- .../components/Dashboard/DashboardSidebar.tsx | 6 +- src/renderer/src/locales/de.json | 8 +- src/renderer/src/locales/en.json | 8 +- src/renderer/src/locales/tr.json | 11 +- 10 files changed, 270 insertions(+), 64 deletions(-) create mode 100644 config/apache_project.conf.template.bak diff --git a/config/apache_project.conf.template b/config/apache_project.conf.template index aaad8f8..7c781d4 100644 --- a/config/apache_project.conf.template +++ b/config/apache_project.conf.template @@ -1,33 +1,36 @@ - - ServerName {{HOST}} - DocumentRoot "{{PATH}}" +# Subdirectory Alias for {{HOST}} +Alias /{{HOST}} "{{PATH}}" - - Options Indexes FollowSymLinks ExecCGI - AllowOverride All - Require all granted - - # Passing Authorization header to PHP - CGIPassAuth On - - # Directory index handling - DirectoryIndex index.php index.html - - # PHP Handling via mod_actions and CGI - - SetHandler application/x-httpd-php-{{HOST}} - - - # Action maps the handler to the binary via the ScriptAlias URL - Action application/x-httpd-php-{{HOST}} "{{PHP_BIN_URL}}/php-cgi.exe" - - - # ScriptAlias definition for the project's PHP CGI binary - ScriptAlias {{PHP_BIN_URL}}/ "{{PHP_DIR}}/" + + Options Indexes FollowSymLinks ExecCGI + AllowOverride All + Require all granted - - AllowOverride None - Options None - Require all granted - - \ No newline at end of file + # --- KRİTİK EKLEME BURASI --- + # PHP'ye php.ini dosyasını {{PHP_DIR}} klasöründe aramasını söyler + SetEnv PHPRC "{{PHP_DIR}}" + # ---------------------------- + + # Passing Authorization header to PHP + CGIPassAuth On + + # Directory index handling + DirectoryIndex index.php index.html + + # PHP Handling via mod_actions and CGI + + SetHandler application/x-httpd-php-alias-{{HOST}} + + + # Action maps the handler to the binary via the ScriptAlias URL + Action application/x-httpd-php-alias-{{HOST}} "{{PHP_BIN_URL}}/php-cgi.exe" + + +# ScriptAlias definition for the project's PHP CGI binary +ScriptAlias {{PHP_BIN_URL}}/ "{{PHP_DIR}}/" + + + AllowOverride None + Options None + Require all granted + \ No newline at end of file diff --git a/config/apache_project.conf.template.bak b/config/apache_project.conf.template.bak new file mode 100644 index 0000000..aaad8f8 --- /dev/null +++ b/config/apache_project.conf.template.bak @@ -0,0 +1,33 @@ + + ServerName {{HOST}} + DocumentRoot "{{PATH}}" + + + Options Indexes FollowSymLinks ExecCGI + AllowOverride All + Require all granted + + # Passing Authorization header to PHP + CGIPassAuth On + + # Directory index handling + DirectoryIndex index.php index.html + + # PHP Handling via mod_actions and CGI + + SetHandler application/x-httpd-php-{{HOST}} + + + # Action maps the handler to the binary via the ScriptAlias URL + Action application/x-httpd-php-{{HOST}} "{{PHP_BIN_URL}}/php-cgi.exe" + + + # ScriptAlias definition for the project's PHP CGI binary + ScriptAlias {{PHP_BIN_URL}}/ "{{PHP_DIR}}/" + + + AllowOverride None + Options None + Require all granted + + \ No newline at end of file diff --git a/port_mappings.json b/port_mappings.json index 7896836..49bbccc 100644 --- a/port_mappings.json +++ b/port_mappings.json @@ -11,5 +11,8 @@ "4.4.9": 9009, "3.0.x (latest)": 9010 }, - "mariadb": {} + "mariadb": { + "11.4.2": 3306, + "10.11.8": 3307 + } } \ No newline at end of file diff --git a/service_events.json b/service_events.json index db5a278..2752594 100644 --- a/service_events.json +++ b/service_events.json @@ -1,4 +1,119 @@ [ + { + "service": "php:5.6.40", + "action": "start", + "status": "success", + "id": "zhj5uo002", + "timestamp": 1775188480028 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "lnxl5gj0x", + "timestamp": 1775188480010 + }, + { + "service": "php:8.2.30", + "action": "start", + "status": "success", + "id": "d7pzpblst", + "timestamp": 1775188479993 + }, + { + "service": "php:8.5.4", + "action": "start", + "status": "success", + "id": "9v9w3li68", + "timestamp": 1775188479975 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "q2w07qros", + "timestamp": 1775188479689 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "2p8k4gdxd", + "timestamp": 1775188479666 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "pvto9aq7v", + "timestamp": 1775188478980 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "cozuqx8yf", + "timestamp": 1775188478919 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "n6kxec3vz", + "timestamp": 1775187974649 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "nt1xnmbop", + "timestamp": 1775187970713 + }, + { + "service": "apache", + "action": "stop", + "status": "info", + "id": "cf6yzeo2h", + "timestamp": 1775187970709 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "kcijsqygj", + "timestamp": 1775187963197 + }, + { + "service": "php:7.4.33", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "9f03j1ihl", + "timestamp": 1775187959015 + }, + { + "service": "php:7.4.33", + "action": "stop", + "status": "info", + "id": "meezjpt0j", + "timestamp": 1775187959002 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "4zl8frca6", + "timestamp": 1775187929780 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "bjo67q9pj", + "timestamp": 1775187928384 + }, { "service": "php:5.6.40", "action": "start", diff --git a/src/main/services/ProcessManager.ts b/src/main/services/ProcessManager.ts index 3d4a1c0..978289a 100644 --- a/src/main/services/ProcessManager.ts +++ b/src/main/services/ProcessManager.ts @@ -6,6 +6,7 @@ import pidusage from 'pidusage' import { configService } from './ConfigService' import { serviceEventLogger } from './ServiceEventLogger' import { t } from '../utils/i18n' +import { portMappingService } from './PortMappingService' export class ProcessManager { private processes: Map = new Map() @@ -341,12 +342,13 @@ export class ProcessManager { return !!(child && child.pid) } - async getStatuses(): Promise> { - const statuses: Record = {} + async getStatuses(): Promise> { + const statuses: Record = {} // Add all tracked states first for (const [name, state] of this.states.entries()) { - statuses[name] = { status: state } + const port = this.getServicePort(name) + statuses[name] = { status: state, port } } const entries = Array.from(this.processes.entries()) @@ -358,7 +360,8 @@ export class ProcessManager { statuses[name] = { status: currentState === 'stopping' ? 'stopping' : 'running', cpu: Math.round(stats.cpu * 10) / 10, - memory: stats.memory + memory: stats.memory, + port: this.getServicePort(name) } if (currentState !== 'stopping' && currentState !== 'starting') { this.states.set(name, 'running') @@ -381,12 +384,27 @@ export class ProcessManager { // Ensure defaults are present const defaultServices = ['nginx', 'apache', 'mariadb'] defaultServices.forEach(s => { - if (!statuses[s]) statuses[s] = { status: this.states.get(s) || 'stopped' } + if (!statuses[s]) statuses[s] = { status: this.states.get(s) || 'stopped', port: this.getServicePort(s) } }) return statuses } + private getServicePort(name: string): string | number | undefined { + const settings = configService.getSettings() + if (name === 'nginx') return settings.nginxPort + if (name === 'apache') return settings.apachePort + if (name.startsWith('php:')) { + const version = name.split(':')[1] + return portMappingService.getPhpPort(version) + } + if (name.startsWith('mariadb:')) { + const version = name.split(':')[1] + return portMappingService.getMariaDbPort(version) + } + return undefined + } + private async checkErrorLogs(name: string) { if (!this.logDir) return const logPaths: Record = { diff --git a/src/renderer/src/components/Dashboard/DashboardDetails.tsx b/src/renderer/src/components/Dashboard/DashboardDetails.tsx index 14c403d..3bb84c6 100644 --- a/src/renderer/src/components/Dashboard/DashboardDetails.tsx +++ b/src/renderer/src/components/Dashboard/DashboardDetails.tsx @@ -69,8 +69,10 @@ export default function DashboardDetails({ if (!serviceId) return null; if (serviceId === 'nginx') return 'nginx'; if (serviceId === 'apache') return 'apache'; - if (serviceId.startsWith('php:')) return 'php'; - if (serviceId.startsWith('mariadb:')) return 'mariadb'; + if (serviceId.includes(':') || serviceId.includes('-')) { + const type = serviceId.includes(':') ? serviceId.split(':')[0] : serviceId.split('-')[0]; + return type.toLowerCase(); + } return null; }; @@ -181,6 +183,24 @@ export default function DashboardDetails({ } const currentStatus = status[serviceId] || { status: 'stopped' }; + + const getPort = () => { + if (currentStatus.port) return currentStatus.port; + // Fallback for stopped services or missing data + if (serviceId === 'nginx') return settings.nginxPort; + if (serviceId === 'apache') return settings.apachePort; + if (serviceType === 'php') { + const version = serviceId.includes(':') ? serviceId.split(':')[1] : serviceId.split('-')[1]; + return version ? '...' : settings.phpPort; + } + if (serviceType === 'mariadb' || serviceType === 'mysql') { + const version = serviceId.includes(':') ? serviceId.split(':')[1] : serviceId.split('-')[1]; + if (version && settings.mariaDbPorts && settings.mariaDbPorts[version]) return settings.mariaDbPorts[version]; + if (version) return '...'; + return settings.mariaDbPort; + } + return 'n/a'; + }; const isRunning = currentStatus.status === 'running'; const serviceProjects = projects.filter(p => { @@ -247,13 +267,13 @@ export default function DashboardDetails({ setActiveTab(v)}> - - + + {(serviceId === 'nginx' || serviceId === 'apache' || serviceType === 'php') && ( - + )} - - + + @@ -261,35 +281,26 @@ export default function DashboardDetails({ {activeTab === 0 && ( - SYSTEM STATS + {t('dashboard.system_stats')} - SERVICE INFO + {t('dashboard.service_info')} - Port + {t('common.port')} - {currentStatus.port || (() => { - if (serviceId === 'nginx') return settings.nginxPort; - if (serviceId === 'apache') return settings.apachePort; - if (serviceType === 'php') return settings.phpPort; - if (serviceType === 'mariadb') { - const verId = serviceId.split(':')[1]; - return (settings.mariaDbPorts && settings.mariaDbPorts[verId]) || settings.mariaDbPort; - } - return 'n/a'; - })()} + {getPort()} - Status + {t('common.status')} - {currentStatus.status.toUpperCase()} + {(isRunning ? t('common.running') : t('common.stopped')).toUpperCase()} diff --git a/src/renderer/src/components/Dashboard/DashboardSidebar.tsx b/src/renderer/src/components/Dashboard/DashboardSidebar.tsx index 660fe24..6036449 100644 --- a/src/renderer/src/components/Dashboard/DashboardSidebar.tsx +++ b/src/renderer/src/components/Dashboard/DashboardSidebar.tsx @@ -3,7 +3,6 @@ import { Typography, List, ListItemButton, - Chip, CircularProgress } from '@mui/material' import { @@ -62,6 +61,11 @@ export default function DashboardSidebar({ {label} + {isRunning && status[serviceKey] && ( + + Port: {status[serviceKey].port || '?'} | CPU: {Math.round(status[serviceKey].cpu || 0)}% | RAM: {Math.round((status[serviceKey].memory || 0) / (1024 * 1024))}MB + + )}