Add all files
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Admin\Resources;
|
||||
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Admin\Resources\UptimeServerResource\Pages;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Models\UptimeServer;
|
||||
|
||||
class UptimeServerResource extends Resource
|
||||
{
|
||||
protected static ?string $model = UptimeServer::class;
|
||||
|
||||
// No icon to avoid errors
|
||||
// protected static ?string $navigationIcon = 'ri-home';
|
||||
// protected static ?string $activeNavigationIcon = 'ri-home-fill';
|
||||
|
||||
|
||||
protected static ?string $navigationGroup = 'Server Uptimes';
|
||||
|
||||
protected static ?string $navigationLabel = 'Servers';
|
||||
protected static ?string $navigationIcon = 'heroicon-o-clock';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Section::make('Server Information')
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('name')
|
||||
->label('Server Name')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->placeholder('Enter the name of the server'),
|
||||
|
||||
Forms\Components\Select::make('server_type')
|
||||
->label('Fetch Type')
|
||||
->required()
|
||||
->options([
|
||||
'ip' => 'IP Address',
|
||||
'subdomain' => 'Subdomain',
|
||||
])
|
||||
->default('ip')
|
||||
->placeholder('Select server type'),
|
||||
|
||||
Forms\Components\TextInput::make('ip_address')
|
||||
->label('IP Address / Subdomain')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->placeholder('Enter IP address or subdomain'),
|
||||
|
||||
Forms\Components\TextInput::make('location')
|
||||
->label('Server Location')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->placeholder('Enter server location (e.g., Columbus, Ohio)'),
|
||||
|
||||
Forms\Components\Toggle::make('is_active')
|
||||
->label('Active')
|
||||
->default(true)
|
||||
->helperText('Enable or disable uptime monitoring for this server'),
|
||||
])->columns(2),
|
||||
|
||||
// Credit Section
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('name')
|
||||
->label('Server Name')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
Tables\Columns\TextColumn::make('ip_address')
|
||||
->label('IP/Subdomain')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
Tables\Columns\TextColumn::make('location')
|
||||
->label('Location')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
Tables\Columns\IconColumn::make('status')
|
||||
->label('Status')
|
||||
->boolean()
|
||||
->trueIcon('ri-checkbox-circle-line')
|
||||
->falseIcon('ri-close-circle-line')
|
||||
->trueColor('success')
|
||||
->falseColor('danger')
|
||||
->sortable(),
|
||||
|
||||
Tables\Columns\TextColumn::make('uptime_percentage')
|
||||
->label('Uptime')
|
||||
->suffix('%')
|
||||
->numeric(
|
||||
decimalPlaces: 2,
|
||||
decimalSeparator: '.',
|
||||
thousandsSeparator: ',',
|
||||
)
|
||||
->sortable(),
|
||||
|
||||
Tables\Columns\TextColumn::make('last_check')
|
||||
->label('Last Check')
|
||||
->dateTime()
|
||||
->sortable(),
|
||||
|
||||
Tables\Columns\IconColumn::make('is_active')
|
||||
->label('Active')
|
||||
->boolean()
|
||||
->sortable(),
|
||||
])
|
||||
->filters([
|
||||
Tables\Filters\SelectFilter::make('status')
|
||||
->options([
|
||||
'online' => 'Online',
|
||||
'offline' => 'Offline',
|
||||
]),
|
||||
Tables\Filters\TernaryFilter::make('is_active')
|
||||
->label('Active Status'),
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\Action::make('check_status')
|
||||
->label('Check Status')
|
||||
->icon('ri-refresh-line')
|
||||
->action(function (UptimeServer $record) {
|
||||
// This will be implemented in the service
|
||||
$record->update([
|
||||
'last_check' => now(),
|
||||
]);
|
||||
}),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListUptimeServers::route('/'),
|
||||
'create' => Pages\CreateUptimeServer::route('/create'),
|
||||
'edit' => Pages\EditUptimeServer::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Admin\Resources\UptimeServerResource\Pages;
|
||||
|
||||
use Paymenter\Extensions\Others\UptimeLab\Admin\Resources\UptimeServerResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateUptimeServer extends CreateRecord
|
||||
{
|
||||
protected static string $resource = UptimeServerResource::class;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Admin\Resources\UptimeServerResource\Pages;
|
||||
|
||||
use Paymenter\Extensions\Others\UptimeLab\Admin\Resources\UptimeServerResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditUptimeServer extends EditRecord
|
||||
{
|
||||
protected static string $resource = UptimeServerResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Admin\Resources\UptimeServerResource\Pages;
|
||||
|
||||
use Paymenter\Extensions\Others\UptimeLab\Admin\Resources\UptimeServerResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListUptimeServers extends ListRecords
|
||||
{
|
||||
protected static string $resource = UptimeServerResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Services\UptimeMonitoringService;
|
||||
|
||||
class CheckUptimeCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'uptime:check {--server= : Check specific server by ID}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Check uptime status of all servers or a specific server';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$monitoringService = new UptimeMonitoringService();
|
||||
|
||||
if ($serverId = $this->option('server')) {
|
||||
$this->checkSpecificServer($serverId, $monitoringService);
|
||||
} else {
|
||||
$this->checkAllServers($monitoringService);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all active servers
|
||||
*/
|
||||
private function checkAllServers(UptimeMonitoringService $monitoringService): void
|
||||
{
|
||||
$this->info('Starting uptime check for all active servers...');
|
||||
|
||||
try {
|
||||
$monitoringService->checkAllServers();
|
||||
$this->info('Uptime check completed successfully!');
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Uptime check failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a specific server
|
||||
*/
|
||||
private function checkSpecificServer(string $serverId, UptimeMonitoringService $monitoringService): void
|
||||
{
|
||||
$this->info("Starting uptime check for server ID: {$serverId}...");
|
||||
|
||||
try {
|
||||
$server = \Paymenter\Extensions\Others\UptimeLab\Models\UptimeServer::find($serverId);
|
||||
|
||||
if (!$server) {
|
||||
$this->error("Server with ID {$serverId} not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
$checkResult = $monitoringService->checkServerStatus($server);
|
||||
$monitoringService->updateServerStatus($server, $checkResult);
|
||||
|
||||
$status = $checkResult['online'] ? 'ONLINE' : 'OFFLINE';
|
||||
$responseTime = $checkResult['response_time'] ? $checkResult['response_time'] . 'ms' : 'N/A';
|
||||
|
||||
$this->info("Server: {$server->name}");
|
||||
$this->info("Status: {$status}");
|
||||
$this->info("Response Time: {$responseTime}");
|
||||
$this->info("Uptime check completed successfully!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Uptime check failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Models\UptimeServer;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Services\UptimeMonitoringService;
|
||||
|
||||
class TestUptimeCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'uptime:test {--server= : Test specific server by ID}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Test uptime monitoring functionality';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('=== Uptime Lab Extension Test ===');
|
||||
|
||||
// Test database connection
|
||||
$this->testDatabaseConnection();
|
||||
|
||||
// Test server models
|
||||
$this->testServerModels();
|
||||
|
||||
// Test monitoring service
|
||||
$this->testMonitoringService();
|
||||
|
||||
$this->info('=== Test completed ===');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test database connection and tables
|
||||
*/
|
||||
private function testDatabaseConnection(): void
|
||||
{
|
||||
$this->info('Testing database connection...');
|
||||
|
||||
try {
|
||||
$count = UptimeServer::count();
|
||||
$this->info("✓ Database connected. Found {$count} servers.");
|
||||
} catch (\Exception $e) {
|
||||
$this->error('✗ Database connection failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test server models
|
||||
*/
|
||||
private function testServerModels(): void
|
||||
{
|
||||
$this->info('Testing server models...');
|
||||
|
||||
try {
|
||||
$servers = UptimeServer::all();
|
||||
|
||||
if ($servers->count() > 0) {
|
||||
$this->info('✓ Server models working correctly.');
|
||||
$this->table(
|
||||
['ID', 'Name', 'IP', 'Status', 'Uptime'],
|
||||
$servers->map(function ($server) {
|
||||
return [
|
||||
$server->id,
|
||||
$server->name,
|
||||
$server->ip_address,
|
||||
$server->status,
|
||||
$server->uptime_percentage . '%'
|
||||
];
|
||||
})
|
||||
);
|
||||
} else {
|
||||
$this->warn('⚠ No servers found in database.');
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->error('✗ Server models test failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test monitoring service
|
||||
*/
|
||||
private function testMonitoringService(): void
|
||||
{
|
||||
$this->info('Testing monitoring service...');
|
||||
|
||||
try {
|
||||
$monitoringService = new UptimeMonitoringService();
|
||||
|
||||
if ($serverId = $this->option('server')) {
|
||||
$server = UptimeServer::find($serverId);
|
||||
if ($server) {
|
||||
$this->testSpecificServer($server, $monitoringService);
|
||||
} else {
|
||||
$this->error("Server with ID {$serverId} not found.");
|
||||
}
|
||||
} else {
|
||||
$this->testAllServers($monitoringService);
|
||||
}
|
||||
|
||||
$this->info('✓ Monitoring service working correctly.');
|
||||
} catch (\Exception $e) {
|
||||
$this->error('✗ Monitoring service test failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a specific server
|
||||
*/
|
||||
private function testSpecificServer(UptimeServer $server, UptimeMonitoringService $monitoringService): void
|
||||
{
|
||||
$this->info("Testing server: {$server->name} ({$server->ip_address})");
|
||||
|
||||
$checkResult = $monitoringService->checkServerStatus($server);
|
||||
|
||||
$this->table(
|
||||
['Property', 'Value'],
|
||||
[
|
||||
['Status', $checkResult['online'] ? 'Online' : 'Offline'],
|
||||
['Response Time', $checkResult['response_time'] ? $checkResult['response_time'] . 'ms' : 'N/A'],
|
||||
['Check Time', $checkResult['check_time'] ? $checkResult['check_time'] . 'ms' : 'N/A'],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all servers
|
||||
*/
|
||||
private function testAllServers(UptimeMonitoringService $monitoringService): void
|
||||
{
|
||||
$this->info('Testing all active servers...');
|
||||
|
||||
$servers = UptimeServer::where('is_active', true)->get();
|
||||
|
||||
if ($servers->count() > 0) {
|
||||
$this->info("Found {$servers->count()} active servers to test.");
|
||||
|
||||
$progressBar = $this->output->createProgressBar($servers->count());
|
||||
$progressBar->start();
|
||||
|
||||
foreach ($servers as $server) {
|
||||
try {
|
||||
$checkResult = $monitoringService->checkServerStatus($server);
|
||||
$monitoringService->updateServerStatus($server, $checkResult);
|
||||
} catch (\Exception $e) {
|
||||
$this->error("\nError checking server {$server->name}: " . $e->getMessage());
|
||||
}
|
||||
|
||||
$progressBar->advance();
|
||||
}
|
||||
|
||||
$progressBar->finish();
|
||||
$this->newLine();
|
||||
$this->info('✓ All servers tested successfully.');
|
||||
} else {
|
||||
$this->warn('⚠ No active servers found to test.');
|
||||
}
|
||||
}
|
||||
}
|
||||
52
extensions/Others/UptimeLab/Livewire/Uptime/Index.php
Normal file
52
extensions/Others/UptimeLab/Livewire/Uptime/Index.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Livewire\Uptime;
|
||||
|
||||
use Livewire\Component;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Models\UptimeServer;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Services\UptimeMonitoringService;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public $servers = [];
|
||||
public $isRefreshing = false;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->loadServers();
|
||||
}
|
||||
|
||||
public function loadServers()
|
||||
{
|
||||
$this->servers = UptimeServer::where('is_active', true)
|
||||
->orderBy('name')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function refreshStatus()
|
||||
{
|
||||
$this->isRefreshing = true;
|
||||
|
||||
try {
|
||||
$monitoringService = new UptimeMonitoringService();
|
||||
$monitoringService->checkAllServers();
|
||||
|
||||
$this->loadServers();
|
||||
|
||||
$this->dispatch('status-refreshed');
|
||||
} catch (\Exception $e) {
|
||||
// Handle error
|
||||
} finally {
|
||||
$this->isRefreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('uptime-lab::index', [
|
||||
'servers' => $this->servers,
|
||||
])->layoutData([
|
||||
'sidebar' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
61
extensions/Others/UptimeLab/Models/UptimeServer.php
Normal file
61
extensions/Others/UptimeLab/Models/UptimeServer.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class UptimeServer extends Model
|
||||
{
|
||||
protected $table = 'ext_uptime_servers';
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'ip_address',
|
||||
'server_type',
|
||||
'location',
|
||||
'is_active',
|
||||
'status',
|
||||
'uptime_percentage',
|
||||
'last_online',
|
||||
'last_offline',
|
||||
'last_check',
|
||||
'response_time',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'is_active' => 'boolean',
|
||||
'last_online' => 'datetime',
|
||||
'last_offline' => 'datetime',
|
||||
'last_check' => 'datetime',
|
||||
'uptime_percentage' => 'decimal:2',
|
||||
];
|
||||
|
||||
public function getFormattedLastOnlineAttribute()
|
||||
{
|
||||
if (!$this->last_online) {
|
||||
return 'Never';
|
||||
}
|
||||
|
||||
return $this->last_online->diffForHumans();
|
||||
}
|
||||
|
||||
public function getFormattedLastOfflineAttribute()
|
||||
{
|
||||
if (!$this->last_offline) {
|
||||
return 'Never';
|
||||
}
|
||||
|
||||
return $this->last_offline->diffForHumans();
|
||||
}
|
||||
|
||||
public function getStatusColorAttribute()
|
||||
{
|
||||
return $this->status === 'online' ? 'green' : 'red';
|
||||
}
|
||||
|
||||
public function getStatusIconAttribute()
|
||||
{
|
||||
return $this->status === 'online' ? 'ri-checkbox-circle-line' : 'ri-close-circle-line';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Livewire\Livewire;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Livewire\Uptime\Index;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Console\Commands\CheckUptimeCommand;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Console\Commands\TestUptimeCommand;
|
||||
|
||||
class UptimeLabServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
// Load routes
|
||||
$this->loadRoutesFrom(__DIR__ . '/../routes/web.php');
|
||||
|
||||
// Load views
|
||||
$this->loadViewsFrom(__DIR__ . '/../resources/views', 'uptime');
|
||||
|
||||
// Load language files
|
||||
$this->loadTranslationsFrom(__DIR__ . '/../lang', 'uptime');
|
||||
|
||||
// Register Livewire components
|
||||
Livewire::component('uptime.index', Index::class);
|
||||
|
||||
// Register console commands
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->commands([
|
||||
CheckUptimeCommand::class,
|
||||
TestUptimeCommand::class,
|
||||
]);
|
||||
}
|
||||
|
||||
// Publish assets if needed
|
||||
$this->publishes([
|
||||
__DIR__ . '/../resources/views' => resource_path('views/vendor/uptime'),
|
||||
], 'uptime-views');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../lang' => resource_path('lang/vendor/uptime'),
|
||||
], 'uptime-lang');
|
||||
}
|
||||
}
|
||||
311
extensions/Others/UptimeLab/Services/UptimeMonitoringService.php
Normal file
311
extensions/Others/UptimeLab/Services/UptimeMonitoringService.php
Normal file
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab\Services;
|
||||
|
||||
use Paymenter\Extensions\Others\UptimeLab\Models\UptimeServer;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UptimeMonitoringService
|
||||
{
|
||||
/**
|
||||
* Check the status of a server
|
||||
*/
|
||||
public function checkServerStatus(UptimeServer $server): array
|
||||
{
|
||||
$startTime = microtime(true);
|
||||
$isOnline = false;
|
||||
$responseTime = null;
|
||||
|
||||
try {
|
||||
if ($server->server_type === 'ip') {
|
||||
$result = $this->pingServer($server->ip_address);
|
||||
$isOnline = $result['online'];
|
||||
$responseTime = $result['response_time'];
|
||||
} else {
|
||||
// For subdomains, try HTTP first, then fallback to ping if HTTP fails
|
||||
$result = $this->httpCheck($server->ip_address);
|
||||
$isOnline = $result['online'];
|
||||
$responseTime = $result['response_time'];
|
||||
|
||||
// If HTTP fails, try ping as fallback for subdomains
|
||||
if (!$isOnline) {
|
||||
Log::info('HTTP check failed for subdomain, trying ping as fallback: ' . $server->ip_address);
|
||||
$pingResult = $this->pingServer($server->ip_address);
|
||||
if ($pingResult['online']) {
|
||||
$isOnline = true;
|
||||
$responseTime = $pingResult['response_time'];
|
||||
Log::info('Ping fallback successful for subdomain: ' . $server->ip_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$endTime = microtime(true);
|
||||
$totalTime = round(($endTime - $startTime) * 1000, 2);
|
||||
|
||||
return [
|
||||
'online' => $isOnline,
|
||||
'response_time' => $responseTime,
|
||||
'check_time' => $totalTime,
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Uptime check failed for server: ' . $server->name, [
|
||||
'error' => $e->getMessage(),
|
||||
'server_id' => $server->id,
|
||||
'server_type' => $server->server_type,
|
||||
'ip_address' => $server->ip_address,
|
||||
]);
|
||||
|
||||
return [
|
||||
'online' => false,
|
||||
'response_time' => null,
|
||||
'check_time' => null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping an IP address or domain
|
||||
*/
|
||||
private function pingServer(string $ip): array
|
||||
{
|
||||
$command = "ping -c 1 -W 5 " . escapeshellarg($ip) . " 2>&1";
|
||||
$output = shell_exec($command);
|
||||
|
||||
if (preg_match('/time=(\d+\.?\d*)\s*ms/', $output, $matches)) {
|
||||
return [
|
||||
'online' => true,
|
||||
'response_time' => (int) $matches[1],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'online' => false,
|
||||
'response_time' => null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check HTTP response for subdomains
|
||||
*/
|
||||
private function httpCheck(string $domain): array
|
||||
{
|
||||
try {
|
||||
// Remove any protocol prefix if present
|
||||
$cleanDomain = preg_replace('/^https?:\/\//', '', $domain);
|
||||
|
||||
// Try HTTP first
|
||||
$response = Http::timeout(10)
|
||||
->withHeaders([
|
||||
'User-Agent' => 'Paymenter-UptimeLab/1.0',
|
||||
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
])
|
||||
->get('http://' . $cleanDomain);
|
||||
|
||||
if ($response->successful()) {
|
||||
$responseTime = $this->calculateResponseTime($response);
|
||||
return [
|
||||
'online' => true,
|
||||
'response_time' => $responseTime,
|
||||
];
|
||||
}
|
||||
|
||||
// If HTTP fails, try HTTPS
|
||||
$httpsResponse = Http::timeout(10)
|
||||
->withHeaders([
|
||||
'User-Agent' => 'Paymenter-UptimeLab/1.0',
|
||||
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
])
|
||||
->get('https://' . $cleanDomain);
|
||||
|
||||
if ($httpsResponse->successful()) {
|
||||
$responseTime = $this->calculateResponseTime($httpsResponse);
|
||||
return [
|
||||
'online' => true,
|
||||
'response_time' => $responseTime,
|
||||
];
|
||||
}
|
||||
|
||||
// If both HTTP and HTTPS fail, check if domain resolves
|
||||
if (gethostbyname($cleanDomain) !== $cleanDomain) {
|
||||
// Domain resolves but HTTP/HTTPS failed
|
||||
return [
|
||||
'online' => false,
|
||||
'response_time' => null,
|
||||
];
|
||||
}
|
||||
|
||||
// Domain doesn't resolve
|
||||
return [
|
||||
'online' => false,
|
||||
'response_time' => null,
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::warning('HTTP check failed for domain: ' . $domain, [
|
||||
'error' => $e->getMessage(),
|
||||
'domain' => $domain,
|
||||
]);
|
||||
|
||||
// Try DNS resolution as fallback
|
||||
if (gethostbyname($cleanDomain) !== $cleanDomain) {
|
||||
return [
|
||||
'online' => false, // Domain resolves but HTTP failed
|
||||
'response_time' => null,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'online' => false,
|
||||
'response_time' => null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate response time from HTTP response
|
||||
*/
|
||||
private function calculateResponseTime($response): ?int
|
||||
{
|
||||
try {
|
||||
// Try to get response time from handler stats
|
||||
if (method_exists($response, 'handlerStats')) {
|
||||
$stats = $response->handlerStats();
|
||||
if (isset($stats['total_time_us'])) {
|
||||
return (int) ($stats['total_time_us'] / 1000); // Convert to milliseconds
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: estimate response time based on current time
|
||||
return null;
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update server status
|
||||
*/
|
||||
public function updateServerStatus(UptimeServer $server, array $checkResult): void
|
||||
{
|
||||
$wasOnline = $server->status === 'online';
|
||||
$isOnline = $checkResult['online'];
|
||||
|
||||
$server->update([
|
||||
'status' => $isOnline ? 'online' : 'offline',
|
||||
'last_check' => now(),
|
||||
'response_time' => $checkResult['response_time'],
|
||||
]);
|
||||
|
||||
// Update last online/offline timestamps
|
||||
if ($isOnline && !$wasOnline) {
|
||||
$server->update(['last_online' => now()]);
|
||||
} elseif (!$isOnline && $wasOnline) {
|
||||
$server->update(['last_offline' => now()]);
|
||||
}
|
||||
|
||||
// Calculate uptime percentage (simplified calculation)
|
||||
$this->calculateUptimePercentage($server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate uptime percentage
|
||||
*/
|
||||
private function calculateUptimePercentage(UptimeServer $server): void
|
||||
{
|
||||
// Calculate uptime based on server status and monitoring history
|
||||
$now = now();
|
||||
$uptimePercentage = 0;
|
||||
|
||||
if ($server->status === 'online') {
|
||||
// Server is currently online
|
||||
if ($server->last_offline) {
|
||||
// Server has been offline before, calculate based on recent performance
|
||||
$lastOfflineTime = $server->last_offline;
|
||||
$timeSinceOffline = $now->diffInHours($lastOfflineTime);
|
||||
|
||||
if ($timeSinceOffline > 24) {
|
||||
// If server has been online for more than 24 hours, give high uptime
|
||||
$uptimePercentage = 99.5;
|
||||
} elseif ($timeSinceOffline > 12) {
|
||||
// If server has been online for more than 12 hours
|
||||
$uptimePercentage = 98.0;
|
||||
} elseif ($timeSinceOffline > 6) {
|
||||
// If server has been online for more than 6 hours
|
||||
$uptimePercentage = 96.0;
|
||||
} elseif ($timeSinceOffline > 1) {
|
||||
// If server has been online for more than 1 hour
|
||||
$uptimePercentage = 92.0;
|
||||
} else {
|
||||
// Server just came back online
|
||||
$uptimePercentage = 85.0;
|
||||
}
|
||||
} else {
|
||||
// Server has never been offline (new server or always online)
|
||||
$uptimePercentage = 99.9;
|
||||
}
|
||||
} else {
|
||||
// Server is currently offline
|
||||
if ($server->last_online) {
|
||||
// Server was online before, calculate based on downtime
|
||||
$lastOnlineTime = $server->last_online;
|
||||
$timeSinceOnline = $now->diffInHours($lastOnlineTime);
|
||||
|
||||
if ($timeSinceOnline < 1) {
|
||||
// Server just went offline
|
||||
$uptimePercentage = 95.0;
|
||||
} elseif ($timeSinceOnline < 6) {
|
||||
// Server has been offline for a few hours
|
||||
$uptimePercentage = 85.0;
|
||||
} elseif ($timeSinceOnline < 24) {
|
||||
// Server has been offline for a day
|
||||
$uptimePercentage = 70.0;
|
||||
} else {
|
||||
// Server has been offline for a long time
|
||||
$uptimePercentage = 50.0;
|
||||
}
|
||||
} else {
|
||||
// Server has never been online
|
||||
$uptimePercentage = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure percentage is between 0 and 100
|
||||
$uptimePercentage = max(0, min(100, $uptimePercentage));
|
||||
|
||||
$server->update([
|
||||
'uptime_percentage' => round($uptimePercentage, 2),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all active servers
|
||||
*/
|
||||
public function checkAllServers(): void
|
||||
{
|
||||
$servers = UptimeServer::where('is_active', true)->get();
|
||||
|
||||
foreach ($servers as $server) {
|
||||
try {
|
||||
$checkResult = $this->checkServerStatus($server);
|
||||
$this->updateServerStatus($server, $checkResult);
|
||||
|
||||
Log::info('Server status checked', [
|
||||
'server' => $server->name,
|
||||
'status' => $checkResult['online'] ? 'online' : 'offline',
|
||||
'response_time' => $checkResult['response_time'],
|
||||
'server_type' => $server->server_type,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to check server: ' . $server->name, [
|
||||
'error' => $e->getMessage(),
|
||||
'server_id' => $server->id,
|
||||
]);
|
||||
}
|
||||
|
||||
// Add a small delay between checks to avoid overwhelming the system
|
||||
usleep(200000); // 0.1 second delay
|
||||
}
|
||||
}
|
||||
}
|
||||
101
extensions/Others/UptimeLab/UptimeLab.php
Normal file
101
extensions/Others/UptimeLab/UptimeLab.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Others\UptimeLab;
|
||||
|
||||
use App\Classes\Extension\Extension;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\HtmlString;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Admin\Resources\UptimeServerResource;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Models\UptimeServer;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
|
||||
class UptimeLab extends Extension
|
||||
{
|
||||
/**
|
||||
* Get all the configuration for the extension
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function getConfig($values = [])
|
||||
{
|
||||
try {
|
||||
return [
|
||||
[
|
||||
'name' => 'Uptime Monitoring',
|
||||
'type' => 'placeholder',
|
||||
'label' => new HtmlString('Uptime Lab extension is now active. You can manage servers in the <a class="text-primary-600" href="' . UptimeServerResource::getUrl() . '">Uptime Lab</a> admin section.'),
|
||||
],
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
return [
|
||||
[
|
||||
'name' => 'Uptime Monitoring',
|
||||
'type' => 'placeholder',
|
||||
'label' => new HtmlString('Uptime Lab extension is now active. You\'ll need to enable this extension above to get started.'),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the extension is enabled
|
||||
*/
|
||||
public function enabled()
|
||||
{
|
||||
// Run migrations
|
||||
Artisan::call('migrate', ['--path' => 'extensions/Others/UptimeLab/database/migrations/2025_01_01_000001_create_ext_uptime_servers_table.php', '--force' => true]);
|
||||
|
||||
// Run seeder to populate sample data
|
||||
try {
|
||||
Artisan::call('db:seed', ['--class' => 'Paymenter\\Extensions\\Others\\UptimeLab\\Database\\Seeders\\UptimeServerSeeder', '--force' => true]);
|
||||
} catch (\Exception $e) {
|
||||
// Seeder might fail if data already exists, which is fine
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the extension is booted
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
// Register routes
|
||||
require __DIR__ . '/routes/web.php';
|
||||
View::addNamespace('uptime-lab', __DIR__ . '/resources/views');
|
||||
|
||||
// Register Livewire components
|
||||
\Livewire\Livewire::component('uptime.index', \Paymenter\Extensions\Others\UptimeLab\Livewire\Uptime\Index::class);
|
||||
// Add navigation menu item to dashboard - no icon to avoid errors
|
||||
Event::listen('navigation.dashboard', function () {
|
||||
return [
|
||||
'name' => new HtmlString('
|
||||
<span class="relative" style="left: -2px;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 99.54" style="width:20px;height:20px;vertical-align:middle; " >
|
||||
<style type="text/css"><![CDATA[
|
||||
.st0{fill:currentcolor;}
|
||||
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#6BBE66;}
|
||||
]]></style>
|
||||
<g>
|
||||
<path class="st0" d="M73.12,0c6.73,0,13.16,1.34,19.03,3.77c6.09,2.52,11.57,6.22,16.16,10.81l0,0c4.58,4.58,8.28,10.06,10.8,16.17 c2.43,5.87,3.77,12.3,3.77,19.02c0,6.73-1.34,13.16-3.77,19.03c-2.52,6.09-6.22,11.57-10.81,16.16l0,0 c-4.58,4.58-10.06,8.28-16.17,10.8c-5.87,2.43-12.3,3.77-19.02,3.77c-6.73,0-13.16-1.34-19.03-3.77 c-6.09-2.52-11.57-6.22-16.15-10.8l-0.01-0.01c-4.59-4.59-8.28-10.07-10.8-16.15c-0.78-1.89-1.45-3.83-2-5.82 c1.04,0.1,2.1,0.15,3.17,0.15c2.03,0,4.01-0.18,5.94-0.53c0.32,0.96,0.67,1.91,1.05,2.84c2.07,5,5.11,9.5,8.89,13.28 c3.78,3.78,8.29,6.82,13.28,8.89c4.81,1.99,10.1,3.1,15.66,3.1s10.84-1.1,15.66-3.1c5-2.07,9.5-5.11,13.28-8.89 c3.78-3.78,6.82-8.29,8.89-13.28c1.99-4.81,3.1-10.1,3.1-15.66s-1.1-10.84-3.1-15.66c-2.07-5-5.11-9.5-8.89-13.28 s-8.29-6.82-13.28-8.89c-4.81-1.99-10.1-3.1-15.66-3.1s-10.84,1.1-15.66,3.1c-0.43,0.18-0.86,0.37-1.28,0.56 c-1.64-2.58-3.62-4.92-5.89-6.95c1.24-0.64,2.51-1.23,3.8-1.77C59.97,1.34,66.39,0,73.12,0L73.12,0L73.12,0z M67.41,26.11 c0-1.22,0.5-2.32,1.29-3.12c0.8-0.8,1.9-1.29,3.12-1.29c1.22,0,2.32,0.49,3.12,1.29c0.8,0.8,1.29,1.9,1.29,3.12v23.22l17.35,10.29 c1.04,0.62,1.74,1.61,2.02,2.7c0.28,1.09,0.15,2.29-0.47,3.33v0.01l0,0c-0.62,1.04-1.61,1.74-2.7,2.02s-2.29,0.15-3.33-0.47h-0.01 l0,0L69.68,55.7c-0.67-0.37-1.22-0.91-1.62-1.55c-0.41-0.67-0.65-1.46-0.65-2.3V26.11L67.41,26.11L67.41,26.11z"/>
|
||||
</g>
|
||||
</svg></span></span><span>
|
||||
Uptime</span>
|
||||
'),
|
||||
'route' => 'uptime.index',
|
||||
'priority' => 32,
|
||||
'spa' => true,
|
||||
'params' => [],
|
||||
'active' => request()->routeIs('uptime.index'),
|
||||
];
|
||||
});
|
||||
// Add admin navigation - no icon to avoid errors
|
||||
Event::listen('admin.navigation', function () {
|
||||
return [
|
||||
'name' => 'Uptime Lab',
|
||||
'group' => 'Extensions',
|
||||
'priority' => 10,
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
32
extensions/Others/UptimeLab/composer.json
Normal file
32
extensions/Others/UptimeLab/composer.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "paymenter/uptime-lab",
|
||||
"description": "A comprehensive server uptime monitoring extension for Paymenter",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paymenter Team",
|
||||
"email": "support@paymenter.org"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"laravel/framework": "^10.0",
|
||||
"filament/filament": "^3.0",
|
||||
"livewire/livewire": "^3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Paymenter\\Extensions\\Others\\UptimeLab\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Paymenter\\Extensions\\Others\\UptimeLab\\Providers\\UptimeLabServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('ext_uptime_servers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('ip_address');
|
||||
$table->string('server_type')->default('ip'); // ip or subdomain
|
||||
$table->string('location');
|
||||
$table->string('type')->default('Production'); // Production, Staging, Development
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->string('status')->default('offline'); // online, offline
|
||||
$table->decimal('uptime_percentage', 5, 2)->default(0.00);
|
||||
$table->timestamp('last_online')->nullable();
|
||||
$table->timestamp('last_offline')->nullable();
|
||||
$table->timestamp('last_check')->nullable();
|
||||
$table->integer('response_time')->nullable(); // in milliseconds
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('ext_uptime_servers');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Models\UptimeServer;
|
||||
|
||||
class UptimeServerSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$servers = [
|
||||
[
|
||||
'name' => 'Web Server 01',
|
||||
'ip_address' => '192.168.1.10',
|
||||
'server_type' => 'ip',
|
||||
'location' => 'Jakarta, Indonesia',
|
||||
'is_active' => true,
|
||||
'status' => 'online',
|
||||
'uptime_percentage' => 99.8,
|
||||
'last_online' => now(),
|
||||
'last_offline' => now()->subHours(6),
|
||||
'last_check' => now(),
|
||||
'response_time' => 15,
|
||||
],
|
||||
[
|
||||
'name' => 'Main Database Server',
|
||||
'ip_address' => '192.168.1.20',
|
||||
'server_type' => 'ip',
|
||||
'location' => 'Surabaya, Indonesia',
|
||||
'is_active' => true,
|
||||
'status' => 'offline',
|
||||
'uptime_percentage' => 100.0,
|
||||
'last_online' => now()->subHours(5),
|
||||
'last_offline' => now(),
|
||||
'last_check' => now(),
|
||||
'response_time' => null,
|
||||
],
|
||||
[
|
||||
'name' => 'API Gateway',
|
||||
'ip_address' => 'api.example.com',
|
||||
'server_type' => 'subdomain',
|
||||
'location' => 'Bandung, Indonesia',
|
||||
'is_active' => true,
|
||||
'status' => 'online',
|
||||
'uptime_percentage' => 99.9,
|
||||
'last_online' => now()->subHours(6),
|
||||
'last_offline' => now()->subHours(5),
|
||||
'last_check' => now(),
|
||||
'response_time' => 25,
|
||||
],
|
||||
[
|
||||
'name' => 'Load Balancer',
|
||||
'ip_address' => '192.168.1.40',
|
||||
'server_type' => 'ip',
|
||||
'location' => 'Jakarta, Indonesia',
|
||||
'is_active' => true,
|
||||
'status' => 'online',
|
||||
'uptime_percentage' => 99.99,
|
||||
'last_online' => now(),
|
||||
'last_offline' => now()->subHours(6),
|
||||
'last_check' => now(),
|
||||
'response_time' => 8,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($servers as $serverData) {
|
||||
UptimeServer::create($serverData);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
extensions/Others/UptimeLab/lang/en/uptime.php
Normal file
36
extensions/Others/UptimeLab/lang/en/uptime.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'dashboard' => 'Uptime',
|
||||
'servers' => 'Servers',
|
||||
'add_server' => 'Add Server',
|
||||
'server_name' => 'Server Name',
|
||||
'ip_address' => 'IP Address',
|
||||
'subdomain' => 'Subdomain',
|
||||
'server_type' => 'Server Type',
|
||||
'location' => 'Location',
|
||||
'status' => 'Status',
|
||||
'online' => 'Online',
|
||||
'offline' => 'Offline',
|
||||
'uptime' => 'Uptime',
|
||||
'last_check' => 'Last Check',
|
||||
'last_online' => 'Last Online',
|
||||
'last_offline' => 'Last Offline',
|
||||
'response_time' => 'Response Time',
|
||||
'active' => 'Active',
|
||||
'inactive' => 'Inactive',
|
||||
'view_details' => 'View Details',
|
||||
'refresh' => 'Refresh',
|
||||
'no_servers' => 'No servers configured',
|
||||
'contact_admin' => 'Contact your administrator to add servers for monitoring.',
|
||||
'auto_refresh' => 'Status updates automatically every 30 seconds',
|
||||
'server_monitoring_dashboard' => 'SERVER MONITORING DASHBOARD',
|
||||
'check_status' => 'Check Status',
|
||||
'uptime_lab' => 'Uptime Lab',
|
||||
'server_information' => 'Server Information',
|
||||
'enter_server_name' => 'Enter the name of the server',
|
||||
'select_server_type' => 'Select server type',
|
||||
'enter_ip_subdomain' => 'Enter IP address or subdomain',
|
||||
'enter_location' => 'Enter server location (e.g., Jakarta, Indonesia)',
|
||||
'enable_disable_monitoring' => 'Enable or disable uptime monitoring for this server',
|
||||
];
|
||||
@@ -0,0 +1,29 @@
|
||||
<div class="text-center py-4">
|
||||
<div class="inline-block">
|
||||
<span class="text-lg font-bold bg-gradient-to-r from-blue-500 via-purple-500 to-blue-600 bg-clip-text text-transparent animate-gradient-x">
|
||||
Created By Farrdevx
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@keyframes gradient-x {
|
||||
0%, 100% {
|
||||
background-size: 200% 200%;
|
||||
background-position: left center;
|
||||
}
|
||||
50% {
|
||||
background-size: 200% 200%;
|
||||
background-position: right center;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-gradient-x {
|
||||
animation: gradient-x 3s ease-in-out infinite;
|
||||
background-size: 200% 200%;
|
||||
}
|
||||
|
||||
.bg-gradient-to-r {
|
||||
background: linear-gradient(to right, #3b82f6, #8b5cf6, #3b82f6);
|
||||
}
|
||||
</style>
|
||||
167
extensions/Others/UptimeLab/resources/views/index.blade.php
Normal file
167
extensions/Others/UptimeLab/resources/views/index.blade.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<div class="w-full">
|
||||
<!-- Custom CSS for animations -->
|
||||
<style>
|
||||
@keyframes status-pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 0.7;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes status-ping {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
75%, 100% {
|
||||
transform: scale(1.5);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.status-online {
|
||||
animation: status-pulse 2s ease-in-out infinite;
|
||||
box-shadow: 0 0 10px rgba(34, 197, 94, 0.5);
|
||||
}
|
||||
|
||||
.status-offline {
|
||||
animation: status-ping 1.5s ease-in-out infinite;
|
||||
box-shadow: 0 0 10px rgba(239, 68, 68, 0.5);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Header -->
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-8">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold ">Services Availability</h1>
|
||||
</div>
|
||||
<div class="mt-4 sm:mt-0">
|
||||
<button
|
||||
wire:click="refreshStatus"
|
||||
wire:loading.attr="disabled"
|
||||
class="inline-flex items-center px-4 py-2 bg-gray-600 hover:bg-gray-700 text-white rounded-lg transition-colors duration-200 disabled:opacity-50"
|
||||
>
|
||||
<svg wire:loading.remove class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
|
||||
</svg>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<svg wire:loading fill="currentColor" stroke="currentColor" viewBox="0 0 128 128" class="w-4 h-4 mr-2"><g><path stroke-width="5" d="M31.6 8.98a4.02 4.02 0 0 0 1.7 5.3l6.12 3.22a52.56 52.56 0 1 0 63.13 10.73L96 33.97a43.88 43.88 0 1 1-53-8.5l-3.65 7.4a4.02 4.02 0 0 0 1.72 5.3 3.73 3.73 0 0 0 5.13-1.67l7.66-15.63a4.18 4.18 0 0 0-1.75-5.4L36.74 7.32a3.73 3.73 0 0 0-5.13 1.66z" fill="currentColor" stroke="currentColor"/><animateTransform attributeName="transform" type="rotate" from="0 64 64" to="360 64 64" dur="1000ms" repeatCount="indefinite"></animateTransform></g></svg>
|
||||
|
||||
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Server Status Cards -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 gap-6">
|
||||
@forelse($servers as $server)
|
||||
<div class="bg-background-secondary rounded-lg p-6 px-6 py-8">
|
||||
<!-- Server Header -->
|
||||
<div class="flex items-start justify-between ">
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 rounded-full {{ $server->status === 'online' ? 'bg-green-500' : 'bg-red-500' }} mr-3 {{ $server->status === 'online' ? 'status-online' : 'status-offline' }}"></div>
|
||||
<div>
|
||||
<h3 class=" font-semibold text-sm">{{ $server->name }}</h3>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<span class="px-3 py-1 rounded-full text-xs font-medium {{ $server->status === 'online' ? 'bg-green-600 text-white' : 'bg-red-600 text-white' }}">
|
||||
{{ ucfirst($server->status) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Server Metrics -->
|
||||
|
||||
|
||||
<!-- Last Status Updates -->
|
||||
<div class="space-y-2" style="margin-top: .5rem;">
|
||||
<div class="flex items-center text-sm" style="align-items: center; ">
|
||||
<style>
|
||||
.svgclock {
|
||||
height: 4vh;
|
||||
width: auto;
|
||||
animation: upDown 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.loader-circle,
|
||||
.loader-pointer,
|
||||
.loader-line {
|
||||
fill: none;
|
||||
stroke-width: 5px;
|
||||
stroke: #4d6565;
|
||||
}
|
||||
|
||||
.loader-center {
|
||||
fill: #4d6565;
|
||||
}
|
||||
|
||||
.loader-pointer {
|
||||
transform-origin: bottom center;
|
||||
animation: spin 4s linear infinite;
|
||||
}
|
||||
|
||||
.loader-line {
|
||||
transform-origin: bottom center;
|
||||
animation: spin 60s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); transform-origin: 50% 50%; }
|
||||
to { transform: rotate(360deg); transform-origin: 50% 50%; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<svg class="svgclock" viewBox="0 0 240 240">
|
||||
<line class="loader-pointer" x1="120" y1="120" x2="120" y2="97"/>
|
||||
<line class="loader-line" x1="120" y1="120" x2="135" y2="120" />
|
||||
<circle class="loader-circle" cx="120" cy="120" r="30" />
|
||||
<circle class="loader-center" cx="120" cy="120" r="5" />
|
||||
</svg>
|
||||
|
||||
<span>Updated:</span>
|
||||
<span class="ml-2">
|
||||
{{ \Carbon\Carbon::parse($server->last_check)->format('m/d/y H:i') }} -0 UTC (MM/DD/YY, HH:MM)
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<div class="col-span-full text-center py-12">
|
||||
<div class="mb-4">
|
||||
<svg class="w-16 h-16 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-medium mb-2">No servers configured</h3>
|
||||
<p class="">Contact your administrator to add servers for monitoring.</p>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
<!-- Auto-refresh indicator -->
|
||||
<div class="mt-3 text-center text-gray-500 text-sm">
|
||||
<p>Status updates automatically every 30 seconds</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Auto-refresh every 30 seconds
|
||||
setInterval(function() {
|
||||
@this.refreshStatus();
|
||||
}, 30000);
|
||||
</script>
|
||||
8
extensions/Others/UptimeLab/routes/web.php
Normal file
8
extensions/Others/UptimeLab/routes/web.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Paymenter\Extensions\Others\UptimeLab\Livewire\Uptime\Index;
|
||||
|
||||
Route::group(['middleware' => ['web', 'auth']], function () {
|
||||
Route::get('/uptime', Index::class)->name('uptime.index');
|
||||
});
|
||||
Reference in New Issue
Block a user