diff --git a/app/Filament/Server/Pages/Console.php b/app/Filament/Server/Pages/Console.php
index 3ef8511bf..ef63364ab 100644
--- a/app/Filament/Server/Pages/Console.php
+++ b/app/Filament/Server/Pages/Console.php
@@ -191,7 +191,6 @@ class Console extends Page
->label(trans('server/console.power_actions.kill'))
->color('danger')
->tooltip(trans('server/console.power_actions.kill_tooltip'))
- ->size(ActionSize::ExtraLarge)
->requiresConfirmation()
->size(Size::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'kill', uuid: $server->uuid))
diff --git a/app/Filament/Server/Pages/Settings.php b/app/Filament/Server/Pages/Settings.php
index e57fcd5b4..2e88ead2b 100644
--- a/app/Filament/Server/Pages/Settings.php
+++ b/app/Filament/Server/Pages/Settings.php
@@ -188,7 +188,7 @@ class Settings extends ServerFormPage
TextEntry::make('password')
->label(trans('server/setting.node_info.sftp.password'))
->columnSpan(1)
- ->content(trans('server/setting.node_info.sftp.password_body')),
+ ->label(trans('server/setting.node_info.sftp.password_body')),
]),
]),
Section::make(trans('server/setting.reinstall.title'))
diff --git a/app/Filament/Server/Pages/Startup.php b/app/Filament/Server/Pages/Startup.php
index 2252a583a..4e277f73b 100644
--- a/app/Filament/Server/Pages/Startup.php
+++ b/app/Filament/Server/Pages/Startup.php
@@ -249,7 +249,7 @@ class Startup extends ServerFormPage
return null;
}
- public function getTitle(): string|Htmlable
+ public function getTitle(): string
{
return trans('server/startup.title');
}
diff --git a/app/Filament/Server/Resources/BackupResource/Pages/ListBackups.php b/app/Filament/Server/Resources/BackupResource/Pages/ListBackups.php
index 0dc94b2d9..3ab6aac8b 100644
--- a/app/Filament/Server/Resources/BackupResource/Pages/ListBackups.php
+++ b/app/Filament/Server/Resources/BackupResource/Pages/ListBackups.php
@@ -2,12 +2,21 @@
namespace App\Filament\Server\Resources\BackupResource\Pages;
+use App\Facades\Activity;
use App\Filament\Server\Resources\BackupResource;
+use App\Models\Permission;
+use App\Models\Server;
+use App\Services\Backups\InitiateBackupService;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
+use Filament\Actions\CreateAction;
+use Filament\Facades\Filament;
+use Filament\Notifications\Notification;
use Filament\Resources\Pages\ListRecords;
+use Filament\Support\Enums\IconSize;
+use Symfony\Component\HttpKernel\Exception\HttpException;
class ListBackups extends ListRecords
{
diff --git a/app/Filament/Server/Resources/DatabaseResource.php b/app/Filament/Server/Resources/DatabaseResource.php
index 6ed7f3bd5..661e7a590 100644
--- a/app/Filament/Server/Resources/DatabaseResource.php
+++ b/app/Filament/Server/Resources/DatabaseResource.php
@@ -2,6 +2,7 @@
namespace App\Filament\Server\Resources;
+use App\Filament\Components\Actions\CopyAction;
use App\Filament\Components\Actions\RotateDatabasePasswordAction;
use App\Filament\Server\Resources\DatabaseResource\Pages\ListDatabases;
use App\Filament\Components\Tables\Columns\DateTimeColumn;
diff --git a/app/Filament/Server/Resources/FileResource/Pages/ListFiles.php b/app/Filament/Server/Resources/FileResource/Pages/ListFiles.php
index 40fe3f717..37423b48c 100644
--- a/app/Filament/Server/Resources/FileResource/Pages/ListFiles.php
+++ b/app/Filament/Server/Resources/FileResource/Pages/ListFiles.php
@@ -2,7 +2,6 @@
namespace App\Filament\Server\Resources\FileResource\Pages;
-use App\Exceptions\Repository\FileExistsException;
use Exception;
use App\Facades\Activity;
use App\Filament\Server\Resources\FileResource;
@@ -12,7 +11,6 @@ use App\Models\Server;
use App\Repositories\Daemon\DaemonFileRepository;
use App\Filament\Components\Tables\Columns\BytesColumn;
use App\Filament\Components\Tables\Columns\DateTimeColumn;
-use App\Livewire\AlertBanner;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use Filament\Actions\Action;
@@ -24,22 +22,17 @@ use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Facades\Filament;
use Filament\Forms\Components\CheckboxList;
-use Filament\Forms\Components\CodeEditor;
-use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Notifications\Notification;
use Filament\Panel;
use Filament\Resources\Pages\ListRecords;
use Filament\Resources\Pages\PageRegistration;
-use Filament\Schemas\Components\Tabs;
-use Filament\Schemas\Components\Tabs\Tab;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Support\Enums\IconSize;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Collection;
-use Illuminate\Http\UploadedFile;
use Illuminate\Routing\Route;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Route as RouteFacade;
@@ -350,10 +343,10 @@ class ListFiles extends ListRecords
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
->schema([
TextInput::make('location')
- ->label(trans('server/file.actions.move.directory'))
- ->hint(trans('server/file.actions.move.directory_hint'))
- ->required()
- ->live(),
+ ->label(trans('server/file.actions.move.directory'))
+ ->hint(trans('server/file.actions.move.directory_hint'))
+ ->required()
+ ->live(),
TextEntry::make('new_location')
->state(fn (Get $get) => resolve_path('./' . join_paths($this->path, $get('location') ?? ''))),
])
@@ -368,21 +361,21 @@ class ListFiles extends ListRecords
->property('files', $files)
->log();
- Notification::make()
- ->title(trans('server/file.actions.move.bulk_notification', ['count' => count($files), 'directory' => resolve_path(join_paths($this->path, $location))]))
- ->success()
- ->send();
- }),
- BulkAction::make('archive')
- ->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_ARCHIVE, $server))
- ->form([
- TextInput::make('name')
- ->label(trans('server/file.actions.archive.archive_name'))
- ->placeholder(fn () => 'archive-' . str(Carbon::now()->toRfc3339String())->replace(':', '')->before('+0000') . 'Z')
- ->suffix('.tar.gz'),
- ])
- ->action(function ($data, Collection $files) {
- $files = $files->map(fn ($file) => $file['name'])->toArray();
+ Notification::make()
+ ->title(trans('server/file.actions.move.bulk_notification', ['count' => count($files), 'directory' => resolve_path(join_paths($this->path, $location))]))
+ ->success()
+ ->send();
+ }),
+ BulkAction::make('archive')
+ ->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_ARCHIVE, $server))
+ ->schema([
+ TextInput::make('name')
+ ->label(trans('server/file.actions.archive.archive_name'))
+ ->placeholder(fn () => 'archive-' . str(Carbon::now()->toRfc3339String())->replace(':', '')->before('+0000') . 'Z')
+ ->suffix('.tar.gz'),
+ ])
+ ->action(function ($data, Collection $files) {
+ $files = $files->map(fn ($file) => $file['name'])->toArray();
$archive = $this->getDaemonFileRepository()->compressFiles($this->path, $files, $data['name']);
@@ -392,11 +385,11 @@ class ListFiles extends ListRecords
->property('files', $files)
->log();
- Notification::make()
- ->title(trans('server/file.actions.archive.notification'))
- ->body($archive['name'])
- ->success()
- ->send();
+ Notification::make()
+ ->title(trans('server/file.actions.archive.notification'))
+ ->body($archive['name'])
+ ->success()
+ ->send();
return redirect(ListFiles::getUrl(['path' => $this->path]));
}),
@@ -411,207 +404,15 @@ class ListFiles extends ListRecords
->property('files', $files)
->log();
- Notification::make()
- ->title(trans('server/file.actions.delete.bulk_notification', ['count' => count($files)]))
- ->success()
- ->send();
- }),
- ]);
- }
-
- Activity::event('server:file.write')
- ->property('file', join_paths($path, $data['name']))
- ->log();
- } catch (FileExistsException) {
- AlertBanner::make()
- ->title('' . $path . '
already exists!')
- ->danger()
- ->closable()
+ Notification::make()
+ ->title(trans('server/file.actions.delete.bulk_notification', ['count' => count($files)]))
+ ->success()
->send();
-
- return [
- HeaderAction::make('new_file')
- ->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
- ->tooltip(trans('server/file.actions.new_file.title'))
- ->hiddenLabel()->icon('tabler-file-plus')->iconButton()->iconSize(IconSize::Large)
- ->color('primary')
- ->modalSubmitActionLabel(trans('server/file.actions.new_file.create'))
- ->action(function ($data) {
- $path = join_paths($this->path, $data['name']);
- try {
- $this->getDaemonFileRepository()->putContent($path, $data['editor'] ?? '');
-
- Activity::event('server:file.write')
- ->property('file', join_paths($path, $data['name']))
- ->log();
- } catch (FileExistsException) {
- AlertBanner::make('file_already_exists')
- ->title('' . $path . '
already exists!')
- ->danger()
- ->closable()
- ->send();
-
- $this->redirect(self::getUrl(['path' => dirname($path)]));
- }
- })
- ->form([
- TextInput::make('name')
- ->label(trans('server/file.actions.new_file.file_name'))
- ->required(),
- Select::make('lang')
- ->label(trans('server/file.actions.new_file.syntax'))
- ->searchable()
- ->native(false)
- ->live()
- ->options(EditorLanguages::class)
- ->selectablePlaceholder(false)
- ->afterStateUpdated(fn ($state) => $this->dispatch('setLanguage', lang: $state))
- ->default(EditorLanguages::plaintext->value),
- MonacoEditor::make('editor')
- ->label('')
- ->view('filament.plugins.monaco-editor')
- ->language(fn (Get $get) => $get('lang') ?? 'plaintext'),
+ }),
]),
- HeaderAction::make('new_folder')
- ->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
- ->hiddenLabel()->icon('tabler-folder-plus')->iconButton()->iconSize(IconSize::Large)
- ->tooltip(trans('server/file.actions.new_folder.title'))
- ->color('primary')
- ->action(function ($data) {
- try {
- $this->getDaemonFileRepository()->createDirectory($data['name'], $this->path);
-
- Activity::event('server:file.create-directory')
- ->property(['directory' => $this->path, 'name' => $data['name']])
- ->log();
- } catch (FileExistsException) {
- $path = join_paths($this->path, $data['name']);
- AlertBanner::make('folder_already_exists')
- ->title('' . $path . '
already exists!')
- ->danger()
- ->closable()
- ->send();
-
- $this->redirect(self::getUrl(['path' => dirname($path)]));
- }
- })
- ->form([
- TextInput::make('name')
- ->label(trans('server/file.actions.new_folder.folder_name'))
- ->required(),
- ]),
- HeaderAction::make('upload')
- ->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
- ->hiddenLabel()->icon('tabler-upload')->iconButton()->iconSize(IconSize::Large)
- ->tooltip(trans('server/file.actions.upload.title'))
- ->color('success')
- ->action(function ($data) {
- if (count($data['files']) > 0 && !isset($data['url'])) {
- /** @var UploadedFile $file */
- foreach ($data['files'] as $file) {
- $this->getDaemonFileRepository()->putContent(join_paths($this->path, $file->getClientOriginalName()), $file->getContent());
-
- Activity::event('server:file.uploaded')
- ->property('directory', $this->path)
- ->log();
- }
-
- return redirect(ListFiles::getUrl(['path' => $this->path]));
- })
- ->schema([
- Tabs::make()
- ->contained(false)
- ->schema([
- Tab::make('Upload Files')
- ->live()
- ->schema([
- FileUpload::make('files')
- ->storeFiles(false)
- ->previewable(false)
- ->preserveFilenames()
- ->maxSize((int) round($server->node->upload_size * (config('panel.use_binary_prefix') ? 1.048576 * 1024 : 1000)))
- ->multiple(),
- ]),
- Tab::make('Upload From URL')
- ->live()
- ->disabled(fn (Get $get) => count($get('files')) > 0)
- ->schema([
- TextInput::make('url')
- ->label('URL')
- ->url(),
- ]),
- ]),
- ]),
- Action::make('search')
- ->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_READ, $server))
- ->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge)
- ->tooltip('Global Search')
- ->color('primary')
- ->icon('tabler-world-search')
- ->modalSubmitActionLabel('Search')
- ->schema([
- TextInput::make('searchTerm')
- ->placeholder('Enter a search term, e.g. *.txt')
- ->required()
- ->regex('/^[^*]*\*?[^*]*$/')
- ->minValue(3),
- ])
- ->action(fn ($data) => redirect(SearchFiles::getUrl([
- 'searchTerm' => $data['searchTerm'],
- 'path' => $this->path,
- ]))),
]);
}
- return redirect(ListFiles::getUrl(['path' => $this->path]));
- })
- ->form([
- Tabs::make()
- ->contained(false)
- ->schema([
- Tab::make(trans('server/file.actions.upload.from_files'))
- ->live()
- ->schema([
- FileUpload::make('files')
- ->storeFiles(false)
- ->previewable(false)
- ->preserveFilenames()
- ->maxSize((int) round($server->node->upload_size * (config('panel.use_binary_prefix') ? 1.048576 * 1024 : 1000)))
- ->multiple(),
- ]),
- Tab::make(trans('server/file.actions.upload.url'))
- ->live()
- ->disabled(fn (Get $get) => count($get('files')) > 0)
- ->schema([
- TextInput::make('url')
- ->label(trans('server/file.actions.upload.url'))
- ->url(),
- ]),
- ]),
- ]),
- HeaderAction::make('search')
- ->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_READ, $server))
- ->hiddenLabel()->iconButton()->iconSize(IconSize::Large)
- ->tooltip(trans('server/file.actions.global_search.title'))
- ->color('primary')
- ->icon('tabler-world-search')
- ->modalHeading(trans('server/file.actions.global_search.title'))
- ->modalSubmitActionLabel(trans('server/file.actions.global_search.search'))
- ->form([
- TextInput::make('searchTerm')
- ->label(trans('server/file.actions.global_search.search_term'))
- ->placeholder(trans('server/file.actions.global_search.search_term_placeholder'))
- ->required()
- ->regex('/^[^*]*\*?[^*]*$/')
- ->minValue(3),
- ])
- ->action(fn ($data) => redirect(SearchFiles::getUrl([
- 'searchTerm' => $data['searchTerm'],
- 'path' => $this->path,
- ]))),
- ];
- }
-
/**
* @return string[]
*/
diff --git a/app/Filament/Server/Resources/ScheduleResource/Pages/ListSchedules.php b/app/Filament/Server/Resources/ScheduleResource/Pages/ListSchedules.php
index 68f5763d6..62adebe39 100644
--- a/app/Filament/Server/Resources/ScheduleResource/Pages/ListSchedules.php
+++ b/app/Filament/Server/Resources/ScheduleResource/Pages/ListSchedules.php
@@ -2,12 +2,15 @@
namespace App\Filament\Server\Resources\ScheduleResource\Pages;
+use App\Filament\Components\Actions\ImportScheduleAction;
use App\Filament\Server\Resources\ScheduleResource;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
+use Filament\Actions\CreateAction;
use Filament\Resources\Pages\ListRecords;
+use Filament\Support\Enums\IconSize;
class ListSchedules extends ListRecords
{
diff --git a/app/Filament/Server/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Server/Resources/UserResource/Pages/ListUsers.php
index ad623f97f..5816a85a5 100644
--- a/app/Filament/Server/Resources/UserResource/Pages/ListUsers.php
+++ b/app/Filament/Server/Resources/UserResource/Pages/ListUsers.php
@@ -2,12 +2,28 @@
namespace App\Filament\Server\Resources\UserResource\Pages;
+use App\Facades\Activity;
use App\Filament\Server\Resources\UserResource;
+use App\Models\Permission;
+use App\Models\Server;
+use App\Services\Subusers\SubuserCreationService;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
+use Exception;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
+use Filament\Actions\CreateAction;
+use Filament\Facades\Filament;
+use Filament\Forms\Components\CheckboxList;
+use Filament\Forms\Components\TextInput;
+use Filament\Notifications\Notification;
use Filament\Resources\Pages\ListRecords;
+use Filament\Schemas\Components\Grid;
+use Filament\Schemas\Components\Section;
+use Filament\Schemas\Components\Tabs;
+use Filament\Schemas\Components\Tabs\Tab;
+use Filament\Schemas\Components\Utilities\Get;
+use Filament\Schemas\Components\Utilities\Set;
use Filament\Support\Enums\IconSize;
use Illuminate\Contracts\Support\Htmlable;
@@ -18,7 +34,9 @@ class ListUsers extends ListRecords
protected static string $resource = UserResource::class;
- /** @return array */
+ /** @return array
+ * @throws Exception
+ */
protected function getDefaultHeaderActions(): array
{
/** @var Server $server */
@@ -54,13 +72,13 @@ class ListUsers extends ListRecords
}
return [
- Actions\CreateAction::make('invite')
+ CreateAction::make('invite')
->hiddenLabel()->iconButton()->iconSize(IconSize::Large)
->icon('tabler-user-plus')
->tooltip(trans('server/user.invite_user'))
->createAnother(false)
->authorize(fn () => auth()->user()->can(Permission::ACTION_USER_CREATE, $server))
- ->form([
+ ->schema([
Grid::make()
->columnSpanFull()
->columns([
@@ -81,23 +99,15 @@ class ListUsers extends ListRecords
'lg' => 5,
])
->required(),
- assignAll::make([
- Action::make('assignAll')
- ->label(trans('server/user.assign_all'))
- ->action(function (Set $set, Get $get) use ($permissionsArray) {
- $permissions = $permissionsArray;
- foreach ($permissions as $key => $value) {
- $allValues = array_unique($value);
- $set($key, $allValues);
- }
- }),
- ])
- ->columnSpan([
- 'default' => 1,
- 'sm' => 1,
- 'md' => 1,
- 'lg' => 1,
- ]),
+ Action::make('assignAll')
+ ->label(trans('server/user.assign_all'))
+ ->action(function (Set $set, Get $get) use ($permissionsArray) {
+ $permissions = $permissionsArray;
+ foreach ($permissions as $key => $value) {
+ $allValues = array_unique($value);
+ $set($key, $allValues);
+ }
+ }),
Tabs::make()
->columnSpanFull()
->schema($tabs),