Initial commit

This commit is contained in:
root
2026-05-09 17:28:23 +02:00
commit 9d73f82529
5575 changed files with 281989 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
<?php
namespace App\Livewire;
use Illuminate\Support\Facades\Process;
use Livewire\Attributes\On;
use Livewire\Component;
class EmulatorLogViewer extends Component
{
public string $logPath = '';
public string $selectedFile = '';
public array $logFiles = [];
public string $logContent = '';
public int $lines = 100;
public bool $autoRefresh = true;
public int $refreshInterval = 5;
public function mount(): void
{
// Get log path from settings (default to logging subdirectory)
$emulatorPath = setting('emulator_jar_path', '/var/www/Emulator');
$this->logPath = $emulatorPath . '/logging';
$this->loadLogFiles();
if ($this->logFiles !== []) {
$this->selectedFile = $this->logFiles[0];
$this->loadLogContent();
}
}
#[On('refresh')]
public function refresh(): void
{
$this->loadLogContent();
}
public function loadLogFiles(): void
{
// Find log files (txt, log, and gz files)
$result = Process::timeout(5)->run("find {$this->logPath} -name '*.txt' -o -name '*.log' -o -name '*.log.*' 2>/dev/null | sort -r | head -20");
if ($result->successful()) {
$files = explode("\n", trim($result->output()));
$this->logFiles = array_filter($files, fn ($f) => ! empty($f) && ! str_contains((string) $f, '.gz'));
}
}
public function loadLogContent(): void
{
if ($this->selectedFile === '' || $this->selectedFile === '0') {
$this->logContent = 'Geen log bestand geselecteerd';
return;
}
$result = Process::timeout(10)->run("tail -n {$this->lines} {$this->selectedFile} 2>/dev/null");
if ($result->successful()) {
$this->logContent = $result->output() ?: 'Log bestand is leeg';
} else {
$this->logContent = 'Fout bij lezen van log bestand';
}
}
public function selectFile(string $file): void
{
$this->selectedFile = $file;
$this->loadLogContent();
}
public function clearLog(): void
{
if ($this->selectedFile !== '' && $this->selectedFile !== '0') {
Process::timeout(5)->run("sudo truncate -s 0 {$this->selectedFile} 2>/dev/null");
$this->loadLogContent();
}
}
public function downloadLog()
{
if ($this->selectedFile !== '' && $this->selectedFile !== '0') {
return response()->download($this->selectedFile);
}
}
public function render()
{
return view('livewire.emulator-log-viewer');
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace App\Livewire;
use App\Models\Miscellaneous\WebsiteMaintenanceTask;
use Filament\Actions\Action;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Livewire\Component;
class MaintenanceTaskStatus extends Component implements HasActions, HasForms
{
use InteractsWithActions;
use InteractsWithForms;
public int $taskId;
public bool $completed;
public function mount(int $taskId, bool $completed): void
{
$this->taskId = $taskId;
$this->completed = $completed;
}
public function render()
{
return view('livewire.maintenance-task-status');
}
public function toggleStatusAction(): Action
{
return Action::make('toggleStatus')
->label($this->completed ? __('Mark as In Progress') : __('Mark as Completed'))
->icon($this->completed ? 'heroicon-o-clock' : 'heroicon-o-check-circle')
->color($this->completed ? 'warning' : 'success')
->action(function () {
$task = WebsiteMaintenanceTask::findOrFail($this->taskId);
$task->update(['completed' => ! $this->completed]);
$this->completed = ! $this->completed;
});
}
}
+149
View File
@@ -0,0 +1,149 @@
<?php
namespace App\Livewire;
use App\Models\Miscellaneous\WebsiteSetting;
use Carbon\Carbon;
use Filament\Actions\Action;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Livewire\Component;
class MaintenanceToggle extends Component implements HasActions, HasForms
{
use InteractsWithActions;
use InteractsWithForms;
public function render()
{
return view('livewire.maintenance-toggle');
}
public function toggleMaintenanceAction(): Action
{
$isEnabled = (bool) setting('maintenance_enabled');
return Action::make('toggleMaintenance')
->label($isEnabled ? __('Disable Maintenance') : __('Enable Maintenance'))
->color($isEnabled ? 'danger' : 'success')
->icon($isEnabled ? 'heroicon-o-lock-open' : 'heroicon-o-lock-closed')
->requiresConfirmation()
->modalHeading($isEnabled ? __('Disable Maintenance Mode?') : __('Enable Maintenance Mode?'))
->modalDescription($isEnabled
? __('Are you sure you want to disable maintenance mode? Users will be able to access the site.')
: __('Are you sure you want to enable maintenance mode? Users will not be able to access the site.'))
->action(function () use ($isEnabled) {
$newState = ! $isEnabled;
WebsiteSetting::updateOrCreate(
['key' => 'maintenance_enabled'],
['value' => $newState ? '1' : '0'],
);
Notification::make()
->title($newState ? __('Maintenance mode enabled') : __('Maintenance mode disabled'))
->success()
->send();
$this->redirect(request()->header('Referer') ?? route('filament.housekeeping.pages.dashboard'));
});
}
public function previewMaintenanceAction(): Action
{
return Action::make('previewMaintenance')
->label(__('Preview Page'))
->icon('heroicon-o-eye')
->color('info')
->url(route('maintenance.show', ['preview' => '1']), true);
}
public function editMaintenanceMessageAction(): Action
{
return Action::make('editMaintenanceMessage')
->label(__('Edit Message'))
->icon('heroicon-o-pencil')
->color('warning')
->form([
Textarea::make('message')
->label(__('Maintenance Message'))
->default(fn () => setting('maintenance_message'))
->rows(5)
->required(),
])
->action(function (array $data) {
WebsiteSetting::updateOrCreate(
['key' => 'maintenance_message'],
['value' => $data['message']],
);
Notification::make()
->title(__('Maintenance message updated'))
->success()
->send();
});
}
public function scheduleMaintenanceAction(): Action
{
$scheduledAt = setting('maintenance_scheduled_at');
$isScheduled = $scheduledAt && strtotime((string) $scheduledAt) > time();
return Action::make('scheduleMaintenance')
->label($isScheduled ? __('Cancel Schedule') : __('Schedule'))
->icon($isScheduled ? 'heroicon-o-x-circle' : 'heroicon-o-clock')
->color($isScheduled ? 'danger' : 'info')
->form($isScheduled ? [] : [
DateTimePicker::make('scheduled_at')
->label(__('Start Time'))
->required()
->minDate(now())
->helperText(__('When should maintenance mode start?')),
TextInput::make('duration')
->label(__('Duration (minutes)'))
->numeric()
->default(30)
->minValue(1)
->helperText(__('How long should maintenance last?')),
])
->modalHeading($isScheduled ? __('Cancel Scheduled Maintenance?') : __('Schedule Maintenance'))
->modalDescription($isScheduled
? __('Are you sure you want to cancel the scheduled maintenance?')
: __('Schedule when maintenance mode should automatically start.'))
->action(function (array $data) use ($isScheduled) {
if ($isScheduled) {
WebsiteSetting::where('key', 'maintenance_scheduled_at')->delete();
WebsiteSetting::where('key', 'maintenance_duration_minutes')->delete();
Notification::make()
->title(__('Scheduled maintenance cancelled'))
->success()
->send();
} else {
WebsiteSetting::updateOrCreate(
['key' => 'maintenance_scheduled_at'],
['value' => $data['scheduled_at']],
);
WebsiteSetting::updateOrCreate(
['key' => 'maintenance_duration_minutes'],
['value' => $data['duration']],
);
$startTime = Carbon::parse($data['scheduled_at'])->format('M d, Y H:i');
Notification::make()
->title(__('Maintenance scheduled'))
->body(__('Maintenance will start at :time for :duration minutes', ['time' => $startTime, 'duration' => $data['duration']]))
->success()
->send();
}
});
}
}