feat: implement ProcessManager service for lifecycle management and add UI components for dashboard monitoring
This commit is contained in:
@@ -1,12 +1,16 @@
|
|||||||
<VirtualHost *:{{PORT}}>
|
# Subdirectory Alias for {{HOST}}
|
||||||
ServerName {{HOST}}
|
Alias /{{HOST}} "{{PATH}}"
|
||||||
DocumentRoot "{{PATH}}"
|
|
||||||
|
|
||||||
<Directory "{{PATH}}">
|
<Directory "{{PATH}}">
|
||||||
Options Indexes FollowSymLinks ExecCGI
|
Options Indexes FollowSymLinks ExecCGI
|
||||||
AllowOverride All
|
AllowOverride All
|
||||||
Require all granted
|
Require all granted
|
||||||
|
|
||||||
|
# --- 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
|
# Passing Authorization header to PHP
|
||||||
CGIPassAuth On
|
CGIPassAuth On
|
||||||
|
|
||||||
@@ -15,19 +19,18 @@
|
|||||||
|
|
||||||
# PHP Handling via mod_actions and CGI
|
# PHP Handling via mod_actions and CGI
|
||||||
<FilesMatch "\.php$">
|
<FilesMatch "\.php$">
|
||||||
SetHandler application/x-httpd-php-{{HOST}}
|
SetHandler application/x-httpd-php-alias-{{HOST}}
|
||||||
</FilesMatch>
|
</FilesMatch>
|
||||||
|
|
||||||
# Action maps the handler to the binary via the ScriptAlias URL
|
# Action maps the handler to the binary via the ScriptAlias URL
|
||||||
Action application/x-httpd-php-{{HOST}} "{{PHP_BIN_URL}}/php-cgi.exe"
|
Action application/x-httpd-php-alias-{{HOST}} "{{PHP_BIN_URL}}/php-cgi.exe"
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
# ScriptAlias definition for the project's PHP CGI binary
|
# ScriptAlias definition for the project's PHP CGI binary
|
||||||
ScriptAlias {{PHP_BIN_URL}}/ "{{PHP_DIR}}/"
|
ScriptAlias {{PHP_BIN_URL}}/ "{{PHP_DIR}}/"
|
||||||
|
|
||||||
<Directory "{{PHP_DIR}}">
|
<Directory "{{PHP_DIR}}">
|
||||||
AllowOverride None
|
AllowOverride None
|
||||||
Options None
|
Options None
|
||||||
Require all granted
|
Require all granted
|
||||||
</Directory>
|
</Directory>
|
||||||
</VirtualHost>
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<VirtualHost *:{{PORT}}>
|
||||||
|
ServerName {{HOST}}
|
||||||
|
DocumentRoot "{{PATH}}"
|
||||||
|
|
||||||
|
<Directory "{{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
|
||||||
|
<FilesMatch "\.php$">
|
||||||
|
SetHandler application/x-httpd-php-{{HOST}}
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
# Action maps the handler to the binary via the ScriptAlias URL
|
||||||
|
Action application/x-httpd-php-{{HOST}} "{{PHP_BIN_URL}}/php-cgi.exe"
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
# ScriptAlias definition for the project's PHP CGI binary
|
||||||
|
ScriptAlias {{PHP_BIN_URL}}/ "{{PHP_DIR}}/"
|
||||||
|
|
||||||
|
<Directory "{{PHP_DIR}}">
|
||||||
|
AllowOverride None
|
||||||
|
Options None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
</VirtualHost>
|
||||||
+4
-1
@@ -11,5 +11,8 @@
|
|||||||
"4.4.9": 9009,
|
"4.4.9": 9009,
|
||||||
"3.0.x (latest)": 9010
|
"3.0.x (latest)": 9010
|
||||||
},
|
},
|
||||||
"mariadb": {}
|
"mariadb": {
|
||||||
|
"11.4.2": 3306,
|
||||||
|
"10.11.8": 3307
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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",
|
"service": "php:5.6.40",
|
||||||
"action": "start",
|
"action": "start",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import pidusage from 'pidusage'
|
|||||||
import { configService } from './ConfigService'
|
import { configService } from './ConfigService'
|
||||||
import { serviceEventLogger } from './ServiceEventLogger'
|
import { serviceEventLogger } from './ServiceEventLogger'
|
||||||
import { t } from '../utils/i18n'
|
import { t } from '../utils/i18n'
|
||||||
|
import { portMappingService } from './PortMappingService'
|
||||||
|
|
||||||
export class ProcessManager {
|
export class ProcessManager {
|
||||||
private processes: Map<string, ChildProcess> = new Map()
|
private processes: Map<string, ChildProcess> = new Map()
|
||||||
@@ -341,12 +342,13 @@ export class ProcessManager {
|
|||||||
return !!(child && child.pid)
|
return !!(child && child.pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getStatuses(): Promise<Record<string, { status: string; cpu?: number; memory?: number }>> {
|
async getStatuses(): Promise<Record<string, { status: string; cpu?: number; memory?: number, port?: string | number }>> {
|
||||||
const statuses: Record<string, { status: string; cpu?: number; memory?: number }> = {}
|
const statuses: Record<string, { status: string; cpu?: number; memory?: number, port?: string | number }> = {}
|
||||||
|
|
||||||
// Add all tracked states first
|
// Add all tracked states first
|
||||||
for (const [name, state] of this.states.entries()) {
|
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())
|
const entries = Array.from(this.processes.entries())
|
||||||
@@ -358,7 +360,8 @@ export class ProcessManager {
|
|||||||
statuses[name] = {
|
statuses[name] = {
|
||||||
status: currentState === 'stopping' ? 'stopping' : 'running',
|
status: currentState === 'stopping' ? 'stopping' : 'running',
|
||||||
cpu: Math.round(stats.cpu * 10) / 10,
|
cpu: Math.round(stats.cpu * 10) / 10,
|
||||||
memory: stats.memory
|
memory: stats.memory,
|
||||||
|
port: this.getServicePort(name)
|
||||||
}
|
}
|
||||||
if (currentState !== 'stopping' && currentState !== 'starting') {
|
if (currentState !== 'stopping' && currentState !== 'starting') {
|
||||||
this.states.set(name, 'running')
|
this.states.set(name, 'running')
|
||||||
@@ -381,12 +384,27 @@ export class ProcessManager {
|
|||||||
// Ensure defaults are present
|
// Ensure defaults are present
|
||||||
const defaultServices = ['nginx', 'apache', 'mariadb']
|
const defaultServices = ['nginx', 'apache', 'mariadb']
|
||||||
defaultServices.forEach(s => {
|
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
|
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) {
|
private async checkErrorLogs(name: string) {
|
||||||
if (!this.logDir) return
|
if (!this.logDir) return
|
||||||
const logPaths: Record<string, string> = {
|
const logPaths: Record<string, string> = {
|
||||||
|
|||||||
@@ -69,8 +69,10 @@ export default function DashboardDetails({
|
|||||||
if (!serviceId) return null;
|
if (!serviceId) return null;
|
||||||
if (serviceId === 'nginx') return 'nginx';
|
if (serviceId === 'nginx') return 'nginx';
|
||||||
if (serviceId === 'apache') return 'apache';
|
if (serviceId === 'apache') return 'apache';
|
||||||
if (serviceId.startsWith('php:')) return 'php';
|
if (serviceId.includes(':') || serviceId.includes('-')) {
|
||||||
if (serviceId.startsWith('mariadb:')) return 'mariadb';
|
const type = serviceId.includes(':') ? serviceId.split(':')[0] : serviceId.split('-')[0];
|
||||||
|
return type.toLowerCase();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -181,6 +183,24 @@ export default function DashboardDetails({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const currentStatus = status[serviceId] || { status: 'stopped' };
|
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 isRunning = currentStatus.status === 'running';
|
||||||
|
|
||||||
const serviceProjects = projects.filter(p => {
|
const serviceProjects = projects.filter(p => {
|
||||||
@@ -247,13 +267,13 @@ export default function DashboardDetails({
|
|||||||
|
|
||||||
<Box sx={{ borderBottom: 1, borderColor: 'rgba(255,255,255,0.05)', px: 3 }}>
|
<Box sx={{ borderBottom: 1, borderColor: 'rgba(255,255,255,0.05)', px: 3 }}>
|
||||||
<Tabs value={activeTab} onChange={(_e, v) => setActiveTab(v)}>
|
<Tabs value={activeTab} onChange={(_e, v) => setActiveTab(v)}>
|
||||||
<Tab label={t('common.overview', 'Genel Bakış')} />
|
<Tab label={t('dashboard.overview')} />
|
||||||
<Tab label={t('dashboard.service_settings', 'Servis Ayarları')} />
|
<Tab label={t('dashboard.service_settings')} />
|
||||||
{(serviceId === 'nginx' || serviceId === 'apache' || serviceType === 'php') && (
|
{(serviceId === 'nginx' || serviceId === 'apache' || serviceType === 'php') && (
|
||||||
<Tab label={t('dashboard.project_settings', 'Proje Ayarları')} />
|
<Tab label={t('dashboard.project_settings')} />
|
||||||
)}
|
)}
|
||||||
<Tab label={t('diagnostics.logs', 'Hata Logları')} />
|
<Tab label={t('diagnostics.logs')} />
|
||||||
<Tab label={t('projects.title', 'Projeler')} />
|
<Tab label={t('projects.title')} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -261,35 +281,26 @@ export default function DashboardDetails({
|
|||||||
{activeTab === 0 && (
|
{activeTab === 0 && (
|
||||||
<Grid container spacing={4}>
|
<Grid container spacing={4}>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid item xs={12} md={6}>
|
||||||
<Typography variant="subtitle2" sx={{ fontWeight: 800, mb: 2, color: 'primary.main' }}>SYSTEM STATS</Typography>
|
<Typography variant="subtitle2" sx={{ fontWeight: 800, mb: 2, color: 'primary.main' }}>{t('dashboard.system_stats')}</Typography>
|
||||||
<Paper sx={{ p: 3, bgcolor: 'rgba(0,0,0,0.2)', borderRadius: 3, border: '1px solid rgba(255,255,255,0.05)' }}>
|
<Paper sx={{ p: 3, bgcolor: 'rgba(0,0,0,0.2)', borderRadius: 3, border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||||
<ResourceMonitor cpu={currentStatus.cpu} memory={currentStatus.memory} />
|
<ResourceMonitor cpu={currentStatus.cpu} memory={currentStatus.memory} />
|
||||||
</Paper>
|
</Paper>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid item xs={12} md={6}>
|
||||||
<Typography variant="subtitle2" sx={{ fontWeight: 800, mb: 2, color: 'primary.main' }}>SERVICE INFO</Typography>
|
<Typography variant="subtitle2" sx={{ fontWeight: 800, mb: 2, color: 'primary.main' }}>{t('dashboard.service_info')}</Typography>
|
||||||
<Paper sx={{ p: 3, bgcolor: 'rgba(0,0,0,0.2)', borderRadius: 3, border: '1px solid rgba(255,255,255,0.05)' }}>
|
<Paper sx={{ p: 3, bgcolor: 'rgba(0,0,0,0.2)', borderRadius: 3, border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<Typography variant="body2" sx={{ opacity: 0.5 }}>Port</Typography>
|
<Typography variant="body2" sx={{ opacity: 0.5 }}>{t('common.port')}</Typography>
|
||||||
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
||||||
{currentStatus.port || (() => {
|
{getPort()}
|
||||||
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';
|
|
||||||
})()}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Divider sx={{ borderColor: 'rgba(255,255,255,0.05)' }} />
|
<Divider sx={{ borderColor: 'rgba(255,255,255,0.05)' }} />
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<Typography variant="body2" sx={{ opacity: 0.5 }}>Status</Typography>
|
<Typography variant="body2" sx={{ opacity: 0.5 }}>{t('common.status')}</Typography>
|
||||||
<Typography variant="body2" sx={{ fontWeight: 600, color: isRunning ? 'success.main' : 'error.main' }}>
|
<Typography variant="body2" sx={{ fontWeight: 600, color: isRunning ? 'success.main' : 'error.main' }}>
|
||||||
{currentStatus.status.toUpperCase()}
|
{(isRunning ? t('common.running') : t('common.stopped')).toUpperCase()}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
Typography,
|
Typography,
|
||||||
List,
|
List,
|
||||||
ListItemButton,
|
ListItemButton,
|
||||||
Chip,
|
|
||||||
CircularProgress
|
CircularProgress
|
||||||
} from '@mui/material'
|
} from '@mui/material'
|
||||||
import {
|
import {
|
||||||
@@ -62,6 +61,11 @@ export default function DashboardSidebar({
|
|||||||
<Typography variant="body2" noWrap sx={{ fontWeight: 600 }}>
|
<Typography variant="body2" noWrap sx={{ fontWeight: 600 }}>
|
||||||
{label}
|
{label}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
{isRunning && status[serviceKey] && (
|
||||||
|
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)', display: 'block', fontSize: '0.65rem', mt: -0.5 }}>
|
||||||
|
Port: {status[serviceKey].port || '?'} | CPU: {Math.round(status[serviceKey].cpu || 0)}% | RAM: {Math.round((status[serviceKey].memory || 0) / (1024 * 1024))}MB
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
width: 10,
|
width: 10,
|
||||||
|
|||||||
@@ -56,7 +56,13 @@
|
|||||||
"start_all": "Alle starten",
|
"start_all": "Alle starten",
|
||||||
"stop_all": "Alle stoppen",
|
"stop_all": "Alle stoppen",
|
||||||
"all_started": "Alle Dienste wurden gestartet.",
|
"all_started": "Alle Dienste wurden gestartet.",
|
||||||
"all_stopped": "Alle Dienste wurden gestoppt."
|
"all_stopped": "Alle Dienste wurden gestoppt.",
|
||||||
|
"overview": "Übersicht",
|
||||||
|
"service_settings": "Service-Einstellungen",
|
||||||
|
"project_settings": "Projekt-Einstellungen",
|
||||||
|
"select_service": "Bitte wählen Sie einen Dienst aus",
|
||||||
|
"system_stats": "SYSTEMSTATISTIKEN",
|
||||||
|
"service_info": "SERVICEINFO"
|
||||||
},
|
},
|
||||||
"projects": {
|
"projects": {
|
||||||
"title": "Meine Projekte",
|
"title": "Meine Projekte",
|
||||||
|
|||||||
@@ -61,7 +61,13 @@
|
|||||||
"start_all": "Start All",
|
"start_all": "Start All",
|
||||||
"stop_all": "Stop All",
|
"stop_all": "Stop All",
|
||||||
"all_started": "All services started.",
|
"all_started": "All services started.",
|
||||||
"all_stopped": "All services stopped."
|
"all_stopped": "All services stopped.",
|
||||||
|
"overview": "Overview",
|
||||||
|
"service_settings": "Service Settings",
|
||||||
|
"project_settings": "Project Settings",
|
||||||
|
"select_service": "Please select a service",
|
||||||
|
"system_stats": "SYSTEM STATS",
|
||||||
|
"service_info": "SERVICE INFO"
|
||||||
},
|
},
|
||||||
"projects": {
|
"projects": {
|
||||||
"title": "My Projects",
|
"title": "My Projects",
|
||||||
|
|||||||
@@ -50,7 +50,8 @@
|
|||||||
"reset_confirm_text": "{{service}} verilerini sıfırlamak istiyor musunuz? Bu işlem tüm verileri siler ve temiz kurulum yapar.",
|
"reset_confirm_text": "{{service}} verilerini sıfırlamak istiyor musunuz? Bu işlem tüm verileri siler ve temiz kurulum yapar.",
|
||||||
"reset_btn": "Evet, Sıfırla",
|
"reset_btn": "Evet, Sıfırla",
|
||||||
"operating": "İşlem devam ediyor...",
|
"operating": "İşlem devam ediyor...",
|
||||||
"please_wait": "Lütfen bekleyin..."
|
"please_wait": "Lütfen bekleyin...",
|
||||||
|
"status": "Durum"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Özet",
|
"title": "Özet",
|
||||||
@@ -61,7 +62,13 @@
|
|||||||
"start_all": "Tümünü Başlat",
|
"start_all": "Tümünü Başlat",
|
||||||
"stop_all": "Tümünü Durdur",
|
"stop_all": "Tümünü Durdur",
|
||||||
"all_started": "Tüm servisler başlatıldı.",
|
"all_started": "Tüm servisler başlatıldı.",
|
||||||
"all_stopped": "Tüm servisler durduruldu."
|
"all_stopped": "Tüm servisler durduruldu.",
|
||||||
|
"overview": "Genel Bakış",
|
||||||
|
"service_settings": "Servis Ayarları",
|
||||||
|
"project_settings": "Proje Ayarları",
|
||||||
|
"select_service": "Lütfen bir servis seçin",
|
||||||
|
"system_stats": "SİSTEM İSTATİSTİKLERİ",
|
||||||
|
"service_info": "SERVİS BİLGİLERİ"
|
||||||
},
|
},
|
||||||
"projects": {
|
"projects": {
|
||||||
"title": "Projelerim",
|
"title": "Projelerim",
|
||||||
|
|||||||
Reference in New Issue
Block a user