mirror of
https://github.com/pelican-dev/panel.git
synced 2025-05-19 22:14:45 +02:00
Mobile + Layout Changes (#836)
* Update Server Listing * Update Edit/Create Server Pages Re-arrange limits, CPU->Memory->Disk * Remove auto focus its cancer on mobile... * Hide Title, Quick yaml fix * Hide columns on mobile * Hide backup locked on mobile * Fix schedules for mobile * Hide Notes on mobile * Consolidate and clean these up * Simplify * Remove unused imports * Replace tabler icon package * Update app/Filament/Server/Resources/FileResource/Pages/EditFiles.php Co-authored-by: Lance Pioch <git@lance.sh> * Allow the unit to be changed * Use existing method * Update composer and pint * Update resources/views/tables/columns/server-entry-column.blade.php Co-authored-by: Boy132 <Boy132@users.noreply.github.com> * Simplify html and add small margin * Unused * Add enum --------- Co-authored-by: Lance Pioch <git@lance.sh> Co-authored-by: Boy132 <Boy132@users.noreply.github.com>
This commit is contained in:
parent
66a17879a0
commit
a8680c7aed
@ -53,6 +53,16 @@ enum ContainerStatus: string
|
||||
};
|
||||
}
|
||||
|
||||
public function colorHex(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::Created, self::Restarting => '#2563EB',
|
||||
self::Starting, self::Paused, self::Removing, self::Stopping => '#D97706',
|
||||
self::Running => '#22C55E',
|
||||
self::Exited, self::Missing, self::Dead, self::Offline => '#EF4444',
|
||||
};
|
||||
}
|
||||
|
||||
public function isStartingOrStopping(): bool
|
||||
{
|
||||
return in_array($this, [ContainerStatus::Starting, ContainerStatus::Stopping, ContainerStatus::Restarting]);
|
||||
|
10
app/Enums/ServerResourceType.php
Normal file
10
app/Enums/ServerResourceType.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum ServerResourceType
|
||||
{
|
||||
case Unit;
|
||||
case Percentage;
|
||||
case Time;
|
||||
}
|
@ -534,6 +534,37 @@ class CreateServer extends CreateRecord
|
||||
'lg' => 3,
|
||||
])
|
||||
->schema([
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
ToggleButtons::make('unlimited_cpu')
|
||||
->label('CPU')->inlineLabel()->inline()
|
||||
->default(true)
|
||||
->afterStateUpdated(fn (Set $set) => $set('cpu', 0))
|
||||
->live()
|
||||
->options([
|
||||
true => 'Unlimited',
|
||||
false => 'Limited',
|
||||
])
|
||||
->colors([
|
||||
true => 'primary',
|
||||
false => 'warning',
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('cpu')
|
||||
->dehydratedWhenHidden()
|
||||
->hidden(fn (Get $get) => $get('unlimited_cpu'))
|
||||
->label('CPU Limit')->inlineLabel()
|
||||
->suffix('%')
|
||||
->default(0)
|
||||
->required()
|
||||
->columnSpan(2)
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->helperText('100% equals one CPU core.'),
|
||||
]),
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
@ -564,7 +595,6 @@ class CreateServer extends CreateRecord
|
||||
->numeric()
|
||||
->minValue(0),
|
||||
]),
|
||||
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
@ -596,37 +626,6 @@ class CreateServer extends CreateRecord
|
||||
->minValue(0),
|
||||
]),
|
||||
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
ToggleButtons::make('unlimited_cpu')
|
||||
->label('CPU')->inlineLabel()->inline()
|
||||
->default(true)
|
||||
->afterStateUpdated(fn (Set $set) => $set('cpu', 0))
|
||||
->live()
|
||||
->options([
|
||||
true => 'Unlimited',
|
||||
false => 'Limited',
|
||||
])
|
||||
->colors([
|
||||
true => 'primary',
|
||||
false => 'warning',
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('cpu')
|
||||
->dehydratedWhenHidden()
|
||||
->hidden(fn (Get $get) => $get('unlimited_cpu'))
|
||||
->label('CPU Limit')->inlineLabel()
|
||||
->suffix('%')
|
||||
->default(0)
|
||||
->required()
|
||||
->columnSpan(2)
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->helperText('100% equals one CPU core.'),
|
||||
]),
|
||||
]),
|
||||
|
||||
Fieldset::make('Advanced Limits')
|
||||
@ -638,6 +637,40 @@ class CreateServer extends CreateRecord
|
||||
'lg' => 3,
|
||||
])
|
||||
->schema([
|
||||
Hidden::make('io')
|
||||
->helperText('The IO performance relative to other running containers')
|
||||
->label('Block IO Proportion')
|
||||
->default(500),
|
||||
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
ToggleButtons::make('cpu_pinning')
|
||||
->label('CPU Pinning')->inlineLabel()->inline()
|
||||
->default(false)
|
||||
->afterStateUpdated(fn (Set $set) => $set('threads', []))
|
||||
->live()
|
||||
->options([
|
||||
false => 'Disabled',
|
||||
true => 'Enabled',
|
||||
])
|
||||
->colors([
|
||||
false => 'success',
|
||||
true => 'warning',
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TagsInput::make('threads')
|
||||
->dehydratedWhenHidden()
|
||||
->hidden(fn (Get $get) => !$get('cpu_pinning'))
|
||||
->label('Pinned Threads')->inlineLabel()
|
||||
->required(fn (Get $get) => $get('cpu_pinning'))
|
||||
->columnSpan(2)
|
||||
->separator()
|
||||
->splitKeys([','])
|
||||
->placeholder('Add pinned thread, e.g. 0 or 2-4'),
|
||||
]),
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
@ -686,41 +719,6 @@ class CreateServer extends CreateRecord
|
||||
->integer(),
|
||||
]),
|
||||
|
||||
Hidden::make('io')
|
||||
->helperText('The IO performance relative to other running containers')
|
||||
->label('Block IO Proportion')
|
||||
->default(500),
|
||||
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
ToggleButtons::make('cpu_pinning')
|
||||
->label('CPU Pinning')->inlineLabel()->inline()
|
||||
->default(false)
|
||||
->afterStateUpdated(fn (Set $set) => $set('threads', []))
|
||||
->live()
|
||||
->options([
|
||||
false => 'Disabled',
|
||||
true => 'Enabled',
|
||||
])
|
||||
->colors([
|
||||
false => 'success',
|
||||
true => 'warning',
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TagsInput::make('threads')
|
||||
->dehydratedWhenHidden()
|
||||
->hidden(fn (Get $get) => !$get('cpu_pinning'))
|
||||
->label('Pinned Threads')->inlineLabel()
|
||||
->required(fn (Get $get) => $get('cpu_pinning'))
|
||||
->columnSpan(2)
|
||||
->separator()
|
||||
->splitKeys([','])
|
||||
->placeholder('Add pinned thread, e.g. 0 or 2-4'),
|
||||
]),
|
||||
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
|
@ -184,6 +184,35 @@ class EditServer extends EditRecord
|
||||
'lg' => 3,
|
||||
])
|
||||
->schema([
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
ToggleButtons::make('unlimited_cpu')
|
||||
->label('CPU')->inlineLabel()->inline()
|
||||
->afterStateUpdated(fn (Set $set) => $set('cpu', 0))
|
||||
->formatStateUsing(fn (Get $get) => $get('cpu') == 0)
|
||||
->live()
|
||||
->options([
|
||||
true => 'Unlimited',
|
||||
false => 'Limited',
|
||||
])
|
||||
->colors([
|
||||
true => 'primary',
|
||||
false => 'warning',
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('cpu')
|
||||
->dehydratedWhenHidden()
|
||||
->hidden(fn (Get $get) => $get('unlimited_cpu'))
|
||||
->label('CPU Limit')->inlineLabel()
|
||||
->suffix('%')
|
||||
->required()
|
||||
->columnSpan(2)
|
||||
->numeric()
|
||||
->minValue(0),
|
||||
]),
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
@ -243,36 +272,6 @@ class EditServer extends EditRecord
|
||||
->numeric()
|
||||
->minValue(0),
|
||||
]),
|
||||
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
ToggleButtons::make('unlimited_cpu')
|
||||
->label('CPU')->inlineLabel()->inline()
|
||||
->afterStateUpdated(fn (Set $set) => $set('cpu', 0))
|
||||
->formatStateUsing(fn (Get $get) => $get('cpu') == 0)
|
||||
->live()
|
||||
->options([
|
||||
true => 'Unlimited',
|
||||
false => 'Limited',
|
||||
])
|
||||
->colors([
|
||||
true => 'primary',
|
||||
false => 'warning',
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('cpu')
|
||||
->dehydratedWhenHidden()
|
||||
->hidden(fn (Get $get) => $get('unlimited_cpu'))
|
||||
->label('CPU Limit')->inlineLabel()
|
||||
->suffix('%')
|
||||
->required()
|
||||
->columnSpan(2)
|
||||
->numeric()
|
||||
->minValue(0),
|
||||
]),
|
||||
]),
|
||||
|
||||
Fieldset::make('Advanced Limits')
|
||||
@ -287,6 +286,36 @@ class EditServer extends EditRecord
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
ToggleButtons::make('cpu_pinning')
|
||||
->label('CPU Pinning')->inlineLabel()->inline()
|
||||
->default(false)
|
||||
->afterStateUpdated(fn (Set $set) => $set('threads', []))
|
||||
->formatStateUsing(fn (Get $get) => !empty($get('threads')))
|
||||
->live()
|
||||
->options([
|
||||
false => 'Disabled',
|
||||
true => 'Enabled',
|
||||
])
|
||||
->colors([
|
||||
false => 'success',
|
||||
true => 'warning',
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TagsInput::make('threads')
|
||||
->dehydratedWhenHidden()
|
||||
->hidden(fn (Get $get) => !$get('cpu_pinning'))
|
||||
->label('Pinned Threads')->inlineLabel()
|
||||
->required(fn (Get $get) => $get('cpu_pinning'))
|
||||
->columnSpan(2)
|
||||
->separator()
|
||||
->splitKeys([','])
|
||||
->placeholder('Add pinned thread, e.g. 0 or 2-4'),
|
||||
]),
|
||||
ToggleButtons::make('swap_support')
|
||||
->live()
|
||||
->label('Swap Memory')->inlineLabel()->inline()
|
||||
@ -338,37 +367,6 @@ class EditServer extends EditRecord
|
||||
->helperText('The IO performance relative to other running containers')
|
||||
->label('Block IO Proportion'),
|
||||
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
->schema([
|
||||
ToggleButtons::make('cpu_pinning')
|
||||
->label('CPU Pinning')->inlineLabel()->inline()
|
||||
->default(false)
|
||||
->afterStateUpdated(fn (Set $set) => $set('threads', []))
|
||||
->formatStateUsing(fn (Get $get) => !empty($get('threads')))
|
||||
->live()
|
||||
->options([
|
||||
false => 'Disabled',
|
||||
true => 'Enabled',
|
||||
])
|
||||
->colors([
|
||||
false => 'success',
|
||||
true => 'warning',
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TagsInput::make('threads')
|
||||
->dehydratedWhenHidden()
|
||||
->hidden(fn (Get $get) => !$get('cpu_pinning'))
|
||||
->label('Pinned Threads')->inlineLabel()
|
||||
->required(fn (Get $get) => $get('cpu_pinning'))
|
||||
->columnSpan(2)
|
||||
->separator()
|
||||
->splitKeys([','])
|
||||
->placeholder('Add pinned thread, e.g. 0 or 2-4'),
|
||||
]),
|
||||
|
||||
Grid::make()
|
||||
->columns(4)
|
||||
->columnSpanFull()
|
||||
@ -400,16 +398,19 @@ class EditServer extends EditRecord
|
||||
])
|
||||
->schema([
|
||||
TextInput::make('allocation_limit')
|
||||
->label('Allocations')
|
||||
->suffixIcon('tabler-network')
|
||||
->required()
|
||||
->minValue(0)
|
||||
->numeric(),
|
||||
TextInput::make('database_limit')
|
||||
->label('Databases')
|
||||
->suffixIcon('tabler-database')
|
||||
->required()
|
||||
->minValue(0)
|
||||
->numeric(),
|
||||
TextInput::make('backup_limit')
|
||||
->label('Backups')
|
||||
->suffixIcon('tabler-copy-check')
|
||||
->required()
|
||||
->minValue(0)
|
||||
@ -420,7 +421,7 @@ class EditServer extends EditRecord
|
||||
'default' => 1,
|
||||
'sm' => 2,
|
||||
'md' => 3,
|
||||
'lg' => 3,
|
||||
'lg' => 4,
|
||||
])
|
||||
->schema([
|
||||
Select::make('select_image')
|
||||
@ -441,7 +442,12 @@ class EditServer extends EditRecord
|
||||
return array_flip($images) + ['ghcr.io/custom-image' => 'Custom Image'];
|
||||
})
|
||||
->selectablePlaceholder(false)
|
||||
->columnSpan(1),
|
||||
->columnSpan([
|
||||
'default' => 1,
|
||||
'sm' => 2,
|
||||
'md' => 3,
|
||||
'lg' => 2,
|
||||
]),
|
||||
|
||||
TextInput::make('image')
|
||||
->label('Image')
|
||||
@ -457,7 +463,12 @@ class EditServer extends EditRecord
|
||||
}
|
||||
})
|
||||
->placeholder('Enter a custom Image')
|
||||
->columnSpan(2),
|
||||
->columnSpan([
|
||||
'default' => 1,
|
||||
'sm' => 2,
|
||||
'md' => 3,
|
||||
'lg' => 2,
|
||||
]),
|
||||
|
||||
KeyValue::make('docker_labels')
|
||||
->label('Container Labels')
|
||||
|
@ -6,15 +6,12 @@ use App\Filament\App\Resources\ServerResource;
|
||||
use App\Filament\Components\Tables\Columns\ServerEntryColumn;
|
||||
use App\Filament\Server\Pages\Console;
|
||||
use App\Models\Server;
|
||||
use Carbon\CarbonInterface;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
use Filament\Tables\Columns\Layout\Stack;
|
||||
use Filament\Tables\Filters\SelectFilter;
|
||||
use Filament\Tables\Filters\TernaryFilter;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Number;
|
||||
|
||||
class ListServers extends ListRecords
|
||||
{
|
||||
@ -36,7 +33,7 @@ class ListServers extends ListRecords
|
||||
])
|
||||
->contentGrid([
|
||||
'default' => 1,
|
||||
'xl' => 2,
|
||||
'md' => 2,
|
||||
])
|
||||
->recordUrl(fn (Server $server) => Console::getUrl(panel: 'server', tenant: $server))
|
||||
->emptyStateIcon('tabler-brand-docker')
|
||||
@ -61,64 +58,4 @@ class ListServers extends ListRecords
|
||||
->preload(),
|
||||
]);
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
private function uptime(Server $server): string
|
||||
{
|
||||
$uptime = Arr::get($server->resources(), 'uptime', 0);
|
||||
|
||||
if ($uptime === 0) {
|
||||
return 'Offline';
|
||||
}
|
||||
|
||||
return now()->subMillis($uptime)->diffForHumans(syntax: CarbonInterface::DIFF_ABSOLUTE, short: true, parts: 2);
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
private function cpu(Server $server): string
|
||||
{
|
||||
$cpu = Number::format(Arr::get($server->resources(), 'cpu_absolute', 0), maxPrecision: 2, locale: auth()->user()->language) . '%';
|
||||
$max = Number::format($server->cpu, locale: auth()->user()->language) . '%';
|
||||
|
||||
return $cpu . ($server->cpu > 0 ? ' Of ' . $max : '');
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
private function memory(Server $server): string
|
||||
{
|
||||
$latestMemoryUsed = Arr::get($server->resources(), 'memory_bytes', 0);
|
||||
$totalMemory = Arr::get($server->resources(), 'memory_limit_bytes', 0);
|
||||
|
||||
$used = config('panel.use_binary_prefix')
|
||||
? Number::format($latestMemoryUsed / 1024 / 1024 / 1024, maxPrecision: 2, locale: auth()->user()->language) .' GiB'
|
||||
: Number::format($latestMemoryUsed / 1000 / 1000 / 1000, maxPrecision: 2, locale: auth()->user()->language) . ' GB';
|
||||
|
||||
if ($totalMemory === 0) {
|
||||
$total = config('panel.use_binary_prefix')
|
||||
? Number::format($server->memory / 1024, maxPrecision: 2, locale: auth()->user()->language) .' GiB'
|
||||
: Number::format($server->memory / 1000, maxPrecision: 2, locale: auth()->user()->language) . ' GB';
|
||||
} else {
|
||||
$total = config('panel.use_binary_prefix')
|
||||
? Number::format($totalMemory / 1024 / 1024 / 1024, maxPrecision: 2, locale: auth()->user()->language) .' GiB'
|
||||
: Number::format($totalMemory / 1000 / 1000 / 1000, maxPrecision: 2, locale: auth()->user()->language) . ' GB';
|
||||
}
|
||||
|
||||
return $used . ($server->memory > 0 ? ' Of ' . $total : '');
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
private function disk(Server $server): string
|
||||
{
|
||||
$usedDisk = Arr::get($server->resources(), 'disk_bytes', 0);
|
||||
|
||||
$used = config('panel.use_binary_prefix')
|
||||
? Number::format($usedDisk / 1024 / 1024 / 1024, maxPrecision: 2, locale: auth()->user()->language) .' GiB'
|
||||
: Number::format($usedDisk / 1000 / 1000 / 1000, maxPrecision: 2, locale: auth()->user()->language) . ' GB';
|
||||
|
||||
$total = config('panel.use_binary_prefix')
|
||||
? Number::format($server->disk / 1024, maxPrecision: 2, locale: auth()->user()->language) .' GiB'
|
||||
: Number::format($server->disk / 1000, maxPrecision: 2, locale: auth()->user()->language) . ' GB';
|
||||
|
||||
return $used . ($server->disk > 0 ? ' Of ' . $total : '');
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class ListAllocations extends ListRecords
|
||||
->hidden(),
|
||||
TextColumn::make('port'),
|
||||
TextInputColumn::make('notes')
|
||||
->visibleFrom('sm')
|
||||
->disabled(fn () => !auth()->user()->can(Permission::ACTION_ALLOCATION_UPDATE, $server))
|
||||
->label('Notes')
|
||||
->placeholder('No Notes'),
|
||||
|
@ -74,6 +74,7 @@ class ListBackups extends ListRecords
|
||||
->label('Successful')
|
||||
->boolean(),
|
||||
IconColumn::make('is_locked')
|
||||
->visibleFrom('md')
|
||||
->label('Lock Status')
|
||||
->icon(fn (Backup $backup) => !$backup->is_locked ? 'tabler-lock-open' : 'tabler-lock'),
|
||||
])
|
||||
|
@ -42,6 +42,8 @@ class EditFiles extends Page
|
||||
|
||||
protected static string $view = 'filament.server.pages.edit-file';
|
||||
|
||||
protected static ?string $title = '';
|
||||
|
||||
#[Locked]
|
||||
public string $path;
|
||||
|
||||
@ -63,9 +65,13 @@ class EditFiles extends Page
|
||||
->options(EditorLanguages::class)
|
||||
->hidden() //TODO Fix Dis
|
||||
->default(function () {
|
||||
$split = explode('.', $this->path);
|
||||
$ext = pathinfo($this->path, PATHINFO_EXTENSION);
|
||||
|
||||
return end($split);
|
||||
if ($ext === 'yml') {
|
||||
return 'yaml';
|
||||
}
|
||||
|
||||
return $ext;
|
||||
}),
|
||||
Section::make('Editing: ' . $this->path)
|
||||
->footerActions([
|
||||
|
@ -88,8 +88,10 @@ class ListFiles extends ListRecords
|
||||
->sortable()
|
||||
->icon(fn (File $file) => $file->getIcon()),
|
||||
BytesColumn::make('size')
|
||||
->visibleFrom('md')
|
||||
->sortable(),
|
||||
DateTimeColumn::make('modified_at')
|
||||
->visibleFrom('md')
|
||||
->since()
|
||||
->sortable(),
|
||||
])
|
||||
|
@ -64,10 +64,17 @@ class ScheduleResource extends Resource
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->columns(10)
|
||||
->columns([
|
||||
'default' => 4,
|
||||
'lg' => 5,
|
||||
])
|
||||
->schema([
|
||||
TextInput::make('name')
|
||||
->columnSpan(fn ($operation) => $operation !== 'view' ? 10 : 5)
|
||||
->columnSpan([
|
||||
'default' => 4,
|
||||
'md' => 3,
|
||||
'lg' => 4,
|
||||
])
|
||||
->label('Schedule Name')
|
||||
->placeholder('A human readable identifier for this schedule.')
|
||||
->autocomplete(false)
|
||||
@ -81,13 +88,20 @@ class ScheduleResource extends Resource
|
||||
'active' => 'success',
|
||||
])
|
||||
->visibleOn('view')
|
||||
->columnSpan(5),
|
||||
->columnSpan([
|
||||
'default' => 4,
|
||||
'md' => 1,
|
||||
'lg' => 1,
|
||||
]),
|
||||
Toggle::make('only_when_online')
|
||||
->label('Only when Server is Online?')
|
||||
->hintIconTooltip('Only execute this schedule when the server is in a running state.')
|
||||
->hintIcon('tabler-question-mark')
|
||||
->inline(false)
|
||||
->columnSpan(5)
|
||||
->columnSpan([
|
||||
'default' => 2,
|
||||
'lg' => 3,
|
||||
])
|
||||
->required()
|
||||
->default(1),
|
||||
Toggle::make('is_active')
|
||||
@ -95,36 +109,55 @@ class ScheduleResource extends Resource
|
||||
->hintIconTooltip('This schedule will be executed automatically if enabled.')
|
||||
->hintIcon('tabler-question-mark')
|
||||
->inline(false)
|
||||
->columnSpan(5)
|
||||
->columnSpan([
|
||||
'default' => 2,
|
||||
'lg' => 2,
|
||||
])
|
||||
->required()
|
||||
->default(1),
|
||||
TextInput::make('cron_minute')
|
||||
->columnSpan(2)
|
||||
->columnSpan([
|
||||
'default' => 2,
|
||||
'lg' => 1,
|
||||
])
|
||||
->label('Minute')
|
||||
->default('*/5')
|
||||
->required(),
|
||||
TextInput::make('cron_hour')
|
||||
->columnSpan(2)
|
||||
->columnSpan([
|
||||
'default' => 2,
|
||||
'lg' => 1,
|
||||
])
|
||||
->label('Hour')
|
||||
->default('*')
|
||||
->required(),
|
||||
TextInput::make('cron_day_of_month')
|
||||
->columnSpan(2)
|
||||
->columnSpan([
|
||||
'default' => 2,
|
||||
'lg' => 1,
|
||||
])
|
||||
->label('Day of Month')
|
||||
->default('*')
|
||||
->required(),
|
||||
TextInput::make('cron_month')
|
||||
->columnSpan(2)
|
||||
->columnSpan([
|
||||
'default' => 2,
|
||||
'lg' => 1,
|
||||
])
|
||||
->label('Month')
|
||||
->default('*')
|
||||
->required(),
|
||||
TextInput::make('cron_day_of_week')
|
||||
->columnSpan(2)
|
||||
->columnSpan([
|
||||
'default' => 2,
|
||||
'lg' => 1,
|
||||
])
|
||||
->label('Day of Week')
|
||||
->default('*')
|
||||
->required(),
|
||||
Section::make('Presets')
|
||||
->hiddenOn('view')
|
||||
->columns(1)
|
||||
->schema([
|
||||
Actions::make([
|
||||
Action::make('hourly')
|
||||
|
@ -3,9 +3,11 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\ContainerStatus;
|
||||
use App\Enums\ServerResourceType;
|
||||
use App\Enums\ServerState;
|
||||
use App\Exceptions\Http\Connection\DaemonConnectionException;
|
||||
use App\Repositories\Daemon\DaemonServerRepository;
|
||||
use Carbon\CarbonInterface;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@ -13,6 +15,7 @@ use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Number;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
@ -453,6 +456,32 @@ class Server extends Model
|
||||
});
|
||||
}
|
||||
|
||||
public function formatResource(string $resourceKey, bool $limit = false, ServerResourceType $type = ServerResourceType::Unit, int $precision = 2): string
|
||||
{
|
||||
$resourceAmount = $this->{$resourceKey} ?? 0;
|
||||
if (!$limit) {
|
||||
$resourceAmount = $this->resources()[$resourceKey] ?? 0;
|
||||
}
|
||||
|
||||
if ($type === ServerResourceType::Time) {
|
||||
if ($resourceAmount === 0) {
|
||||
return 'Offline';
|
||||
}
|
||||
|
||||
return now()->subMillis($resourceAmount)->diffForHumans(syntax: CarbonInterface::DIFF_ABSOLUTE, short: true, parts: 4);
|
||||
}
|
||||
|
||||
if ($resourceAmount === 0 & $limit) {
|
||||
return 'Unlimited';
|
||||
}
|
||||
|
||||
if ($type === ServerResourceType::Percentage) {
|
||||
return Number::format($resourceAmount, precision: $precision, locale: auth()->user()->language ?? 'en') . '%';
|
||||
}
|
||||
|
||||
return convert_bytes_to_readable($resourceAmount, decimals: $precision, base: 3);
|
||||
}
|
||||
|
||||
public function condition(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
@ -481,4 +510,9 @@ class Server extends Model
|
||||
|
||||
return $this->status->color();
|
||||
}
|
||||
|
||||
public function conditionColorHex(): string
|
||||
{
|
||||
return ContainerStatus::from($this->retrieveStatus())->colorHex();
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ if (!function_exists('is_ip')) {
|
||||
}
|
||||
|
||||
if (!function_exists('convert_bytes_to_readable')) {
|
||||
function convert_bytes_to_readable(int $bytes, int $decimals = 2): string
|
||||
function convert_bytes_to_readable(int $bytes, int $decimals = 2, ?int $base = null): string
|
||||
{
|
||||
$conversionUnit = config('panel.use_binary_prefix') ? 1024 : 1000;
|
||||
$suffix = config('panel.use_binary_prefix') ? ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB'] : ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
@ -28,10 +28,10 @@ if (!function_exists('convert_bytes_to_readable')) {
|
||||
return '0 ' . $suffix[0];
|
||||
}
|
||||
|
||||
$base = log($bytes) / log($conversionUnit);
|
||||
$f_base = floor($base);
|
||||
$fromBase = log($bytes) / log($conversionUnit);
|
||||
$base ??= floor($fromBase);
|
||||
|
||||
return round(pow($conversionUnit, $base - $f_base), $decimals) . ' ' . $suffix[$f_base];
|
||||
return round(pow($conversionUnit, $fromBase - $base), $decimals) . ' ' . $suffix[$base];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,8 @@
|
||||
"phpseclib/phpseclib": "~3.0.18",
|
||||
"pragmarx/google2fa": "~8.0.0",
|
||||
"predis/predis": "~2.1.1",
|
||||
"ryangjchandler/blade-tabler-icons": "^2.3",
|
||||
"s1lentium/iptools": "~1.2.0",
|
||||
"secondnetwork/blade-tabler-icons": "^3.26",
|
||||
"socialiteproviders/authentik": "^5.2",
|
||||
"socialiteproviders/discord": "^4.2",
|
||||
"socialiteproviders/steam": "^4.2",
|
||||
@ -93,4 +93,4 @@
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true
|
||||
}
|
||||
}
|
||||
|
122
composer.lock
generated
122
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2fddfe7f5db269cdf9e906b83c815756",
|
||||
"content-hash": "4c83ce23eb3e0fab5738cdd7212e4fe3",
|
||||
"packages": [
|
||||
{
|
||||
"name": "abdelhamiderrahmouni/filament-monaco-editor",
|
||||
@ -6762,68 +6762,6 @@
|
||||
],
|
||||
"time": "2024-02-26T18:08:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ryangjchandler/blade-tabler-icons",
|
||||
"version": "v2.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ryangjchandler/blade-tabler-icons.git",
|
||||
"reference": "cd359f5d3b406a982dae1aaaf121d84067576a2e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ryangjchandler/blade-tabler-icons/zipball/cd359f5d3b406a982dae1aaaf121d84067576a2e",
|
||||
"reference": "cd359f5d3b406a982dae1aaaf121d84067576a2e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"blade-ui-kit/blade-icons": "^1.5",
|
||||
"illuminate/support": "^10.0 || ^11.0",
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.14",
|
||||
"orchestra/testbench": "^8.0 || ^9.0",
|
||||
"phpunit/phpunit": "^9.5.10 || ^10.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"RyanChandler\\TablerIcons\\BladeTablerIconsServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"RyanChandler\\TablerIcons\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ryan Chandler",
|
||||
"email": "support@ryangjchandler.co.uk",
|
||||
"homepage": "https://ryangjchandler.co.uk",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A package to easily make use of Tabler icons in your Laravel Blade views.",
|
||||
"homepage": "https://github.com/ryangjchandler/blade-tabler-icons",
|
||||
"keywords": [
|
||||
"blade",
|
||||
"laravel",
|
||||
"tabler"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ryangjchandler/blade-tabler-icons/issues",
|
||||
"source": "https://github.com/ryangjchandler/blade-tabler-icons/tree/v2.3.0"
|
||||
},
|
||||
"time": "2024-03-12T23:54:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "s1lentium/iptools",
|
||||
"version": "v1.2.0",
|
||||
@ -6879,6 +6817,64 @@
|
||||
},
|
||||
"time": "2022-08-17T14:28:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "secondnetwork/blade-tabler-icons",
|
||||
"version": "v3.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/secondnetwork/blade-tabler-icons.git",
|
||||
"reference": "d25677773f7b3a534faedcbba089bff7a25568e8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/secondnetwork/blade-tabler-icons/zipball/d25677773f7b3a534faedcbba089bff7a25568e8",
|
||||
"reference": "d25677773f7b3a534faedcbba089bff7a25568e8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"blade-ui-kit/blade-icons": "^1.1|^1.5|^1.6",
|
||||
"illuminate/support": "^8.0|^9.0|^10.0|^11.0",
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^6.0|^7.0|^9.0",
|
||||
"phpunit/phpunit": "^9.0|^10.0|^11.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"secondnetwork\\TablerIcons\\BladeTablerIconsServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"secondnetwork\\TablerIcons\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andreas Farah"
|
||||
}
|
||||
],
|
||||
"description": "A package to easily make use of tabler-icons in your Laravel Blade views.",
|
||||
"homepage": "https://github.com/secondnetwork/blade-tabler-icons",
|
||||
"keywords": [
|
||||
"blade",
|
||||
"laravel",
|
||||
"tabler-icons"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/secondnetwork/blade-tabler-icons/issues",
|
||||
"source": "https://github.com/secondnetwork/blade-tabler-icons/tree/v3.26.0"
|
||||
},
|
||||
"time": "2024-12-21T15:50:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/authentik",
|
||||
"version": "5.2.0",
|
||||
|
@ -20,7 +20,6 @@
|
||||
class="w-full focus:outline-none focus:ring-0 border-none"
|
||||
style="background-color: #202A32;"
|
||||
type="text"
|
||||
autofocus
|
||||
:readonly="{{ $this->canSendCommand() ? 'false' : 'true' }}"
|
||||
title="{{ $this->canSendCommand() ? '' : 'Can\'t send command when the server is Offline' }}"
|
||||
placeholder="{{ $this->canSendCommand() ? 'Type a command...' : 'Server Offline...' }}"
|
||||
@ -126,7 +125,7 @@
|
||||
case 'status':
|
||||
handlePowerChangeEvent(args[0]);
|
||||
|
||||
$wire.dispatch('console-status', {state: args[0]})
|
||||
$wire.dispatch('console-status', { state: args[0] });
|
||||
break;
|
||||
case 'transfer status':
|
||||
handleTransferStatus(args[0]);
|
||||
|
@ -1,65 +1,67 @@
|
||||
@php
|
||||
use App\Enums\ServerResourceType;
|
||||
|
||||
/** @var \App\Models\Server $server */
|
||||
$server = $getRecord();
|
||||
@endphp
|
||||
|
||||
<head>
|
||||
<style>
|
||||
.inline-flex {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
hr {
|
||||
border-color: #9ca3af;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<div class="w-full grid gap-y-2 overflow-x-auto">
|
||||
<div class="flex items-center gap-x-1">
|
||||
<x-filament::icon-button
|
||||
:icon="$getRecord()->conditionIcon()"
|
||||
:color="$getRecord()->conditionColor()"
|
||||
:tooltip="\Illuminate\Support\Str::title($getRecord()->condition)" size="xl"
|
||||
/>
|
||||
<div class="w-full">
|
||||
<!-- Wrapper for Positioning -->
|
||||
<div class="relative flex">
|
||||
<!-- Status Strip Outside the Box -->
|
||||
<div
|
||||
class="absolute left-0 top-1 bottom-0 w-1 rounded-lg"
|
||||
style="background-color: {{ $server->conditionColorHex() }};">
|
||||
</div>
|
||||
|
||||
<span class="text-2xl font-semibold text-gray-500 dark:text-gray-400">
|
||||
{{ $getRecord()->name }} ({{ $this->uptime($getRecord()) }})
|
||||
</span>
|
||||
</div>
|
||||
<!-- Card Component -->
|
||||
<div class="flex-1 bg-gray-800 text-white rounded-lg overflow-hidden p-3">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center mb-5 gap-2">
|
||||
<x-filament::icon-button
|
||||
:icon="$server->conditionIcon()"
|
||||
:color="$server->conditionColor()"
|
||||
:tooltip="\Illuminate\Support\Str::title($server->condition)"
|
||||
size="xl"
|
||||
/>
|
||||
<h2 class="text-xl font-bold">
|
||||
{{ $server->name }}
|
||||
<span class="text-gray-400">({{ $server->formatResource('uptime', type: ServerResourceType::Time) }})</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<div class="flex-1 text-md font-medium text-gray-850 dark:text-white inline-flex" title="Egg Name">
|
||||
<x-filament::icon
|
||||
icon="tabler-egg"
|
||||
/>
|
||||
{{ $getRecord()->egg->name }}
|
||||
</div>
|
||||
<div class="flex-1 text-md font-medium text-gray-850 dark:text-white inline-flex" title="Owner">
|
||||
<x-filament::icon
|
||||
icon="tabler-user"
|
||||
/>
|
||||
{{ $getRecord()->user->username }}
|
||||
</div>
|
||||
<div class="flex-1 text-md font-medium text-gray-850 dark:text-white inline-flex" title="Primary Allocation">
|
||||
<x-filament::icon
|
||||
icon="tabler-network"
|
||||
/>
|
||||
{{ $getRecord()->allocation->address }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="flex">
|
||||
<div class="flex-1 text-md font-medium text-gray-850 dark:text-white inline-flex" title="CPU Usage">
|
||||
<x-filament::icon
|
||||
icon="tabler-cpu"
|
||||
/>
|
||||
{{ $this->cpu($getRecord()) }}
|
||||
</div>
|
||||
<div class="flex-1 text-md font-medium text-gray-850 dark:text-white inline-flex" title="Memory Usage">
|
||||
<x-filament::icon
|
||||
icon="tabler-device-desktop-analytics"
|
||||
/>
|
||||
{{ $this->memory($getRecord()) }}
|
||||
</div>
|
||||
<div class="flex-1 text-md font-medium text-gray-850 dark:text-white inline-flex" title="Disk Usage">
|
||||
<x-filament::icon
|
||||
icon="tabler-packages"
|
||||
/>
|
||||
{{ $this->disk($getRecord()) }}
|
||||
<!-- Resource Usage -->
|
||||
<div class="flex justify-between text-center">
|
||||
<div>
|
||||
<p class="text-sm text-gray-400">CPU</p>
|
||||
<p class="text-md font-semibold">{{ $server->formatResource('cpu_absolute', type: ServerResourceType::Percentage) }}</p>
|
||||
<hr class="p-0.5">
|
||||
<p class="text-xs text-gray-400">{{ $server->formatResource('cpu', type: ServerResourceType::Percentage, limit: true) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm text-gray-400">Memory</p>
|
||||
<p class="text-md font-semibold">{{ $server->formatResource('memory_bytes') }}</p>
|
||||
<hr class="p-0.5">
|
||||
<p class="text-xs text-gray-400">{{ $server->formatResource('memory', limit: true) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm text-gray-400">Disk</p>
|
||||
<p class="text-md font-semibold">{{ $server->formatResource('disk_bytes') }}</p>
|
||||
<hr class="p-0.5">
|
||||
<p class="text-xs text-gray-400">{{ $server->formatResource('disk', limit: true) }}</p>
|
||||
</div>
|
||||
<div class="hidden sm:block">
|
||||
<p class="text-sm text-gray-400">Network</p>
|
||||
<p class="text-md font-semibold">{{ $server->allocation->address }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user