mirror of
https://github.com/pelican-dev/panel.git
synced 2025-09-10 02:18:36 +02:00
Relocate some actions to toolbarActions
This commit is contained in:
parent
91fcaf4b45
commit
b5f6cc345b
@ -15,6 +15,7 @@ use App\Services\Backups\DownloadLinkService;
|
|||||||
use App\Filament\Components\Tables\Columns\BytesColumn;
|
use App\Filament\Components\Tables\Columns\BytesColumn;
|
||||||
use App\Filament\Components\Tables\Columns\DateTimeColumn;
|
use App\Filament\Components\Tables\Columns\DateTimeColumn;
|
||||||
use App\Services\Backups\DeleteBackupService;
|
use App\Services\Backups\DeleteBackupService;
|
||||||
|
use App\Services\Backups\InitiateBackupService;
|
||||||
use App\Traits\Filament\BlockAccessInConflict;
|
use App\Traits\Filament\BlockAccessInConflict;
|
||||||
use App\Traits\Filament\CanCustomizePages;
|
use App\Traits\Filament\CanCustomizePages;
|
||||||
use App\Traits\Filament\CanCustomizeRelations;
|
use App\Traits\Filament\CanCustomizeRelations;
|
||||||
@ -23,6 +24,7 @@ use App\Traits\Filament\CanModifyTable;
|
|||||||
use App\Traits\Filament\HasLimitBadge;
|
use App\Traits\Filament\HasLimitBadge;
|
||||||
use Filament\Actions\Action;
|
use Filament\Actions\Action;
|
||||||
use Filament\Actions\ActionGroup;
|
use Filament\Actions\ActionGroup;
|
||||||
|
use Filament\Actions\CreateAction;
|
||||||
use Filament\Actions\DeleteAction;
|
use Filament\Actions\DeleteAction;
|
||||||
use Filament\Facades\Filament;
|
use Filament\Facades\Filament;
|
||||||
use Filament\Forms\Components\Checkbox;
|
use Filament\Forms\Components\Checkbox;
|
||||||
@ -34,12 +36,14 @@ use Filament\Notifications\Notification;
|
|||||||
use Filament\Resources\Pages\PageRegistration;
|
use Filament\Resources\Pages\PageRegistration;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
use Filament\Schemas\Schema;
|
use Filament\Schemas\Schema;
|
||||||
|
use Filament\Support\Enums\IconSize;
|
||||||
use Filament\Tables\Columns\IconColumn;
|
use Filament\Tables\Columns\IconColumn;
|
||||||
use Filament\Tables\Columns\TextColumn;
|
use Filament\Tables\Columns\TextColumn;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Http\Client\ConnectionException;
|
use Illuminate\Http\Client\ConnectionException;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class BackupResource extends Resource
|
class BackupResource extends Resource
|
||||||
@ -122,18 +126,21 @@ class BackupResource extends Resource
|
|||||||
->recordActions([
|
->recordActions([
|
||||||
ActionGroup::make([
|
ActionGroup::make([
|
||||||
Action::make('lock')
|
Action::make('lock')
|
||||||
|
->iconSize(IconSize::Large)
|
||||||
->icon(fn (Backup $backup) => !$backup->is_locked ? 'tabler-lock' : 'tabler-lock-open')
|
->icon(fn (Backup $backup) => !$backup->is_locked ? 'tabler-lock' : 'tabler-lock-open')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_DELETE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_DELETE, $server))
|
||||||
->label(fn (Backup $backup) => !$backup->is_locked ? 'Lock' : 'Unlock')
|
->label(fn (Backup $backup) => !$backup->is_locked ? 'Lock' : 'Unlock')
|
||||||
->action(fn (BackupController $backupController, Backup $backup, Request $request) => $backupController->toggleLock($request, $server, $backup))
|
->action(fn (BackupController $backupController, Backup $backup, Request $request) => $backupController->toggleLock($request, $server, $backup))
|
||||||
->visible(fn (Backup $backup) => $backup->status === BackupStatus::Successful),
|
->visible(fn (Backup $backup) => $backup->status === BackupStatus::Successful),
|
||||||
Action::make('download')
|
Action::make('download')
|
||||||
|
->iconSize(IconSize::Large)
|
||||||
->color('primary')
|
->color('primary')
|
||||||
->icon('tabler-download')
|
->icon('tabler-download')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_DOWNLOAD, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_DOWNLOAD, $server))
|
||||||
->url(fn (DownloadLinkService $downloadLinkService, Backup $backup, Request $request) => $downloadLinkService->handle($backup, $request->user()), true)
|
->url(fn (DownloadLinkService $downloadLinkService, Backup $backup, Request $request) => $downloadLinkService->handle($backup, $request->user()), true)
|
||||||
->visible(fn (Backup $backup) => $backup->status === BackupStatus::Successful),
|
->visible(fn (Backup $backup) => $backup->status === BackupStatus::Successful),
|
||||||
Action::make('restore')
|
Action::make('restore')
|
||||||
|
->iconSize(IconSize::Large)
|
||||||
->color('success')
|
->color('success')
|
||||||
->icon('tabler-folder-up')
|
->icon('tabler-folder-up')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_RESTORE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_RESTORE, $server))
|
||||||
@ -185,6 +192,7 @@ class BackupResource extends Resource
|
|||||||
})
|
})
|
||||||
->visible(fn (Backup $backup) => $backup->status === BackupStatus::Successful),
|
->visible(fn (Backup $backup) => $backup->status === BackupStatus::Successful),
|
||||||
DeleteAction::make('delete')
|
DeleteAction::make('delete')
|
||||||
|
->iconSize(IconSize::Large)
|
||||||
->disabled(fn (Backup $backup) => $backup->is_locked)
|
->disabled(fn (Backup $backup) => $backup->is_locked)
|
||||||
->modalDescription(fn (Backup $backup) => 'Do you wish to delete ' . $backup->name . '?')
|
->modalDescription(fn (Backup $backup) => 'Do you wish to delete ' . $backup->name . '?')
|
||||||
->modalSubmitActionLabel('Delete Backup')
|
->modalSubmitActionLabel('Delete Backup')
|
||||||
@ -207,7 +215,45 @@ class BackupResource extends Resource
|
|||||||
->log();
|
->log();
|
||||||
})
|
})
|
||||||
->visible(fn (Backup $backup) => $backup->status !== BackupStatus::InProgress),
|
->visible(fn (Backup $backup) => $backup->status !== BackupStatus::InProgress),
|
||||||
]),
|
])->iconSize(IconSize::ExtraLarge),
|
||||||
|
])
|
||||||
|
->toolbarActions([
|
||||||
|
CreateAction::make()
|
||||||
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_CREATE, $server))
|
||||||
|
->icon('tabler-file-zip')
|
||||||
|
->tooltip(fn () => $server->backups()->count() >= $server->backup_limit ? 'Backup Limit Reached' : 'Create Backup')
|
||||||
|
->disabled(fn () => $server->backups()->count() >= $server->backup_limit)
|
||||||
|
->color(fn () => $server->backups()->count() >= $server->backup_limit ? 'danger' : 'primary')
|
||||||
|
->createAnother(false)
|
||||||
|
->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge)
|
||||||
|
->action(function (InitiateBackupService $initiateBackupService, $data) use ($server) {
|
||||||
|
$action = $initiateBackupService->setIgnoredFiles(explode(PHP_EOL, $data['ignored'] ?? ''));
|
||||||
|
|
||||||
|
if (auth()->user()->can(Permission::ACTION_BACKUP_DELETE, $server)) {
|
||||||
|
$action->setIsLocked((bool) $data['is_locked']);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$backup = $action->handle($server, $data['name']);
|
||||||
|
|
||||||
|
Activity::event('server:backup.start')
|
||||||
|
->subject($backup)
|
||||||
|
->property(['name' => $backup->name, 'locked' => (bool) $data['is_locked']])
|
||||||
|
->log();
|
||||||
|
|
||||||
|
return Notification::make()
|
||||||
|
->title('Backup Created')
|
||||||
|
->body($backup->name . ' created.')
|
||||||
|
->success()
|
||||||
|
->send();
|
||||||
|
} catch (HttpException $e) {
|
||||||
|
return Notification::make()
|
||||||
|
->danger()
|
||||||
|
->title('Backup Failed')
|
||||||
|
->body($e->getMessage() . ' Try again' . ($e->getHeaders()['Retry-After'] ? ' in ' . $e->getHeaders()['Retry-After'] . ' seconds.' : ''))
|
||||||
|
->send();
|
||||||
|
}
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,20 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Filament\Server\Resources\BackupResource\Pages;
|
namespace App\Filament\Server\Resources\BackupResource\Pages;
|
||||||
|
|
||||||
use App\Facades\Activity;
|
|
||||||
use App\Filament\Server\Resources\BackupResource;
|
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\CanCustomizeHeaderActions;
|
||||||
use App\Traits\Filament\CanCustomizeHeaderWidgets;
|
use App\Traits\Filament\CanCustomizeHeaderWidgets;
|
||||||
use Filament\Actions\Action;
|
use Filament\Actions\Action;
|
||||||
use Filament\Actions\ActionGroup;
|
use Filament\Actions\ActionGroup;
|
||||||
use Filament\Actions\CreateAction;
|
|
||||||
use Filament\Facades\Filament;
|
|
||||||
use Filament\Notifications\Notification;
|
|
||||||
use Filament\Resources\Pages\ListRecords;
|
use Filament\Resources\Pages\ListRecords;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
|
||||||
|
|
||||||
class ListBackups extends ListRecords
|
class ListBackups extends ListRecords
|
||||||
{
|
{
|
||||||
@ -27,44 +19,7 @@ class ListBackups extends ListRecords
|
|||||||
/** @return array<Action|ActionGroup> */
|
/** @return array<Action|ActionGroup> */
|
||||||
protected function getDefaultHeaderActions(): array
|
protected function getDefaultHeaderActions(): array
|
||||||
{
|
{
|
||||||
/** @var Server $server */
|
|
||||||
$server = Filament::getTenant();
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
CreateAction::make()
|
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_CREATE, $server))
|
|
||||||
->label(fn () => $server->backups()->count() >= $server->backup_limit ? 'Backup limit reached' : 'Create Backup')
|
|
||||||
->disabled(fn () => $server->backups()->count() >= $server->backup_limit)
|
|
||||||
->color(fn () => $server->backups()->count() >= $server->backup_limit ? 'danger' : 'primary')
|
|
||||||
->createAnother(false)
|
|
||||||
->action(function (InitiateBackupService $initiateBackupService, $data) use ($server) {
|
|
||||||
$action = $initiateBackupService->setIgnoredFiles(explode(PHP_EOL, $data['ignored'] ?? ''));
|
|
||||||
|
|
||||||
if (auth()->user()->can(Permission::ACTION_BACKUP_DELETE, $server)) {
|
|
||||||
$action->setIsLocked((bool) $data['is_locked']);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$backup = $action->handle($server, $data['name']);
|
|
||||||
|
|
||||||
Activity::event('server:backup.start')
|
|
||||||
->subject($backup)
|
|
||||||
->property(['name' => $backup->name, 'locked' => (bool) $data['is_locked']])
|
|
||||||
->log();
|
|
||||||
|
|
||||||
return Notification::make()
|
|
||||||
->title('Backup Created')
|
|
||||||
->body($backup->name . ' created.')
|
|
||||||
->success()
|
|
||||||
->send();
|
|
||||||
} catch (HttpException $e) {
|
|
||||||
return Notification::make()
|
|
||||||
->danger()
|
|
||||||
->title('Backup Failed')
|
|
||||||
->body($e->getMessage() . ' Try again' . ($e->getHeaders()['Retry-After'] ? ' in ' . $e->getHeaders()['Retry-After'] . ' seconds.' : ''))
|
|
||||||
->send();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ use App\Traits\Filament\CanCustomizeHeaderWidgets;
|
|||||||
use Filament\Actions\Action;
|
use Filament\Actions\Action;
|
||||||
use Filament\Actions\ActionGroup;
|
use Filament\Actions\ActionGroup;
|
||||||
use Filament\Actions\BulkAction;
|
use Filament\Actions\BulkAction;
|
||||||
|
use Filament\Actions\BulkActionGroup;
|
||||||
use Filament\Actions\DeleteAction;
|
use Filament\Actions\DeleteAction;
|
||||||
use Filament\Actions\DeleteBulkAction;
|
use Filament\Actions\DeleteBulkAction;
|
||||||
use Filament\Actions\EditAction;
|
use Filament\Actions\EditAction;
|
||||||
@ -34,6 +35,7 @@ use Filament\Resources\Pages\PageRegistration;
|
|||||||
use Filament\Schemas\Components\Tabs;
|
use Filament\Schemas\Components\Tabs;
|
||||||
use Filament\Schemas\Components\Tabs\Tab;
|
use Filament\Schemas\Components\Tabs\Tab;
|
||||||
use Filament\Schemas\Components\Utilities\Get;
|
use Filament\Schemas\Components\Utilities\Get;
|
||||||
|
use Filament\Support\Enums\IconSize;
|
||||||
use Filament\Tables\Columns\TextColumn;
|
use Filament\Tables\Columns\TextColumn;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
@ -116,7 +118,7 @@ class ListFiles extends ListRecords
|
|||||||
Action::make('view')
|
Action::make('view')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_READ, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_READ, $server))
|
||||||
->label('Open')
|
->label('Open')
|
||||||
->icon('tabler-eye')
|
->icon('tabler-eye')->iconSize(IconSize::Large)
|
||||||
->visible(fn (File $file) => $file->is_directory)
|
->visible(fn (File $file) => $file->is_directory)
|
||||||
->url(fn (File $file) => self::getUrl(['path' => join_paths($this->path, $file->name)])),
|
->url(fn (File $file) => self::getUrl(['path' => join_paths($this->path, $file->name)])),
|
||||||
EditAction::make('edit')
|
EditAction::make('edit')
|
||||||
@ -128,7 +130,7 @@ class ListFiles extends ListRecords
|
|||||||
Action::make('rename')
|
Action::make('rename')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
|
||||||
->label('Rename')
|
->label('Rename')
|
||||||
->icon('tabler-forms')
|
->icon('tabler-forms')->iconSize(IconSize::Large)
|
||||||
->schema([
|
->schema([
|
||||||
TextInput::make('name')
|
TextInput::make('name')
|
||||||
->label('File name')
|
->label('File name')
|
||||||
@ -156,7 +158,7 @@ class ListFiles extends ListRecords
|
|||||||
Action::make('copy')
|
Action::make('copy')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
|
||||||
->label('Copy')
|
->label('Copy')
|
||||||
->icon('tabler-copy')
|
->icon('tabler-copy')->iconSize(IconSize::Large)
|
||||||
->visible(fn (File $file) => $file->is_file)
|
->visible(fn (File $file) => $file->is_file)
|
||||||
->action(function (File $file) {
|
->action(function (File $file) {
|
||||||
$this->getDaemonFileRepository()->copyFile(join_paths($this->path, $file->name));
|
$this->getDaemonFileRepository()->copyFile(join_paths($this->path, $file->name));
|
||||||
@ -175,13 +177,13 @@ class ListFiles extends ListRecords
|
|||||||
Action::make('download')
|
Action::make('download')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_READ_CONTENT, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_READ_CONTENT, $server))
|
||||||
->label('Download')
|
->label('Download')
|
||||||
->icon('tabler-download')
|
->icon('tabler-download')->iconSize(IconSize::Large)
|
||||||
->visible(fn (File $file) => $file->is_file)
|
->visible(fn (File $file) => $file->is_file)
|
||||||
->url(fn (File $file) => DownloadFiles::getUrl(['path' => join_paths($this->path, $file->name)]), true),
|
->url(fn (File $file) => DownloadFiles::getUrl(['path' => join_paths($this->path, $file->name)]), true),
|
||||||
Action::make('move')
|
Action::make('move')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
|
||||||
->label('Move')
|
->label('Move')
|
||||||
->icon('tabler-replace')
|
->icon('tabler-replace')->iconSize(IconSize::Large)
|
||||||
->schema([
|
->schema([
|
||||||
TextInput::make('location')
|
TextInput::make('location')
|
||||||
->label('New location')
|
->label('New location')
|
||||||
@ -216,7 +218,7 @@ class ListFiles extends ListRecords
|
|||||||
Action::make('permissions')
|
Action::make('permissions')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
|
||||||
->label('Permissions')
|
->label('Permissions')
|
||||||
->icon('tabler-license')
|
->icon('tabler-license')->iconSize(IconSize::Large)
|
||||||
->schema([
|
->schema([
|
||||||
CheckboxList::make('owner')
|
CheckboxList::make('owner')
|
||||||
->bulkToggleable()
|
->bulkToggleable()
|
||||||
@ -272,7 +274,7 @@ class ListFiles extends ListRecords
|
|||||||
Action::make('archive')
|
Action::make('archive')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_ARCHIVE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_ARCHIVE, $server))
|
||||||
->label('Archive')
|
->label('Archive')
|
||||||
->icon('tabler-archive')
|
->icon('tabler-archive')->iconSize(IconSize::Large)
|
||||||
->schema([
|
->schema([
|
||||||
TextInput::make('name')
|
TextInput::make('name')
|
||||||
->label('Archive name')
|
->label('Archive name')
|
||||||
@ -299,7 +301,7 @@ class ListFiles extends ListRecords
|
|||||||
Action::make('unarchive')
|
Action::make('unarchive')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_ARCHIVE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_ARCHIVE, $server))
|
||||||
->label('Unarchive')
|
->label('Unarchive')
|
||||||
->icon('tabler-archive')
|
->icon('tabler-archive')->iconSize(IconSize::Large)
|
||||||
->visible(fn (File $file) => $file->isArchive())
|
->visible(fn (File $file) => $file->isArchive())
|
||||||
->action(function (File $file) {
|
->action(function (File $file) {
|
||||||
$this->getDaemonFileRepository()->decompressFile($this->path, $file->name);
|
$this->getDaemonFileRepository()->decompressFile($this->path, $file->name);
|
||||||
@ -316,11 +318,11 @@ class ListFiles extends ListRecords
|
|||||||
|
|
||||||
return redirect(ListFiles::getUrl(['path' => $this->path]));
|
return redirect(ListFiles::getUrl(['path' => $this->path]));
|
||||||
}),
|
}),
|
||||||
]),
|
])->iconSize(IconSize::Large),
|
||||||
DeleteAction::make()
|
DeleteAction::make()
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_DELETE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_DELETE, $server))
|
||||||
->label('')
|
->label('')
|
||||||
->icon('tabler-trash')
|
->icon('tabler-trash')->iconSize(IconSize::Large)
|
||||||
->requiresConfirmation()
|
->requiresConfirmation()
|
||||||
->modalHeading(fn (File $file) => trans('filament-actions::delete.single.modal.heading', ['label' => $file->name . ' ' . ($file->is_directory ? 'folder' : 'file')]))
|
->modalHeading(fn (File $file) => trans('filament-actions::delete.single.modal.heading', ['label' => $file->name . ' ' . ($file->is_directory ? 'folder' : 'file')]))
|
||||||
->action(function (File $file) {
|
->action(function (File $file) {
|
||||||
@ -333,77 +335,208 @@ class ListFiles extends ListRecords
|
|||||||
->log();
|
->log();
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
->groupedBulkActions([
|
->toolbarActions([
|
||||||
BulkAction::make('move')
|
BulkActionGroup::make([
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
|
BulkAction::make('move')
|
||||||
->schema([
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
|
||||||
TextInput::make('location')
|
->schema([
|
||||||
->label('Directory')
|
TextInput::make('location')
|
||||||
->hint('Enter the new directory, relative to the current directory.')
|
->label('Directory')
|
||||||
->required()
|
->hint('Enter the new directory, relative to the current directory.')
|
||||||
->live(),
|
->required()
|
||||||
TextEntry::make('new_location')
|
->live(),
|
||||||
->state(fn (Get $get) => resolve_path('./' . join_paths($this->path, $get('location') ?? ''))),
|
TextEntry::make('new_location')
|
||||||
])
|
->state(fn (Get $get) => resolve_path('./' . join_paths($this->path, $get('location') ?? ''))),
|
||||||
->action(function (Collection $files, $data) {
|
])
|
||||||
$location = rtrim($data['location'], '/');
|
->action(function (Collection $files, $data) {
|
||||||
|
$location = rtrim($data['location'], '/');
|
||||||
|
|
||||||
$files = $files->map(fn ($file) => ['to' => join_paths($location, $file['name']), 'from' => $file['name']])->toArray();
|
$files = $files->map(fn ($file) => ['to' => join_paths($location, $file['name']), 'from' => $file['name']])->toArray();
|
||||||
$this->getDaemonFileRepository()->renameFiles($this->path, $files);
|
$this->getDaemonFileRepository()->renameFiles($this->path, $files);
|
||||||
|
|
||||||
Activity::event('server:file.rename')
|
Activity::event('server:file.rename')
|
||||||
->property('directory', $this->path)
|
->property('directory', $this->path)
|
||||||
->property('files', $files)
|
->property('files', $files)
|
||||||
->log();
|
->log();
|
||||||
|
|
||||||
Notification::make()
|
Notification::make()
|
||||||
->title(count($files) . ' Files were moved to ' . resolve_path(join_paths($this->path, $location)))
|
->title(count($files) . ' Files were moved to ' . resolve_path(join_paths($this->path, $location)))
|
||||||
->success()
|
->success()
|
||||||
->send();
|
->send();
|
||||||
}),
|
}),
|
||||||
BulkAction::make('archive')
|
BulkAction::make('archive')
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_ARCHIVE, $server))
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_ARCHIVE, $server))
|
||||||
|
->schema([
|
||||||
|
TextInput::make('name')
|
||||||
|
->label('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']);
|
||||||
|
|
||||||
|
Activity::event('server:file.compress')
|
||||||
|
->property('name', $archive['name'])
|
||||||
|
->property('directory', $this->path)
|
||||||
|
->property('files', $files)
|
||||||
|
->log();
|
||||||
|
|
||||||
|
Notification::make()
|
||||||
|
->title('Archive created')
|
||||||
|
->body($archive['name'])
|
||||||
|
->success()
|
||||||
|
->send();
|
||||||
|
|
||||||
|
return redirect(ListFiles::getUrl(['path' => $this->path]));
|
||||||
|
}),
|
||||||
|
DeleteBulkAction::make()
|
||||||
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_DELETE, $server))
|
||||||
|
->action(function (Collection $files) {
|
||||||
|
$files = $files->map(fn ($file) => $file['name'])->toArray();
|
||||||
|
$this->getDaemonFileRepository()->deleteFiles($this->path, $files);
|
||||||
|
|
||||||
|
Activity::event('server:file.delete')
|
||||||
|
->property('directory', $this->path)
|
||||||
|
->property('files', $files)
|
||||||
|
->log();
|
||||||
|
|
||||||
|
Notification::make()
|
||||||
|
->title(count($files) . ' Files deleted.')
|
||||||
|
->success()
|
||||||
|
->send();
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Action::make('new_file')
|
||||||
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
|
||||||
|
->tooltip('New File')
|
||||||
|
->hiddenLabel()->icon('tabler-file-plus')->iconButton()->iconSize(IconSize::ExtraLarge)
|
||||||
|
->color('primary')
|
||||||
|
->keyBindings('')
|
||||||
|
->modalSubmitActionLabel('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()
|
||||||
|
->title('<code>' . $path . '</code> already exists!')
|
||||||
|
->danger()
|
||||||
|
->closable()
|
||||||
|
->send();
|
||||||
|
|
||||||
|
$this->redirect(self::getUrl(['path' => dirname($path)]));
|
||||||
|
}
|
||||||
|
})
|
||||||
->schema([
|
->schema([
|
||||||
TextInput::make('name')
|
TextInput::make('name')
|
||||||
->label('Archive name')
|
->label('Name')
|
||||||
->placeholder(fn () => 'archive-' . str(Carbon::now()->toRfc3339String())->replace(':', '')->before('+0000') . 'Z')
|
->required(),
|
||||||
->suffix('.tar.gz'),
|
CodeEditor::make('editor')
|
||||||
])
|
->hiddenLabel(),
|
||||||
->action(function ($data, Collection $files) {
|
]),
|
||||||
$files = $files->map(fn ($file) => $file['name'])->toArray();
|
Action::make('new_folder')
|
||||||
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
|
||||||
|
->hiddenLabel()->icon('tabler-folder-plus')->iconButton()->iconSize(IconSize::ExtraLarge)
|
||||||
|
->tooltip('New Folder')
|
||||||
|
->color('primary')
|
||||||
|
->action(function ($data) {
|
||||||
|
try {
|
||||||
|
$this->getDaemonFileRepository()->createDirectory($data['name'], $this->path);
|
||||||
|
|
||||||
$archive = $this->getDaemonFileRepository()->compressFiles($this->path, $files, $data['name']);
|
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()
|
||||||
|
->title('<code>' . $path . '</code> already exists!')
|
||||||
|
->danger()
|
||||||
|
->closable()
|
||||||
|
->send();
|
||||||
|
|
||||||
Activity::event('server:file.compress')
|
$this->redirect(self::getUrl(['path' => dirname($path)]));
|
||||||
->property('name', $archive['name'])
|
}
|
||||||
->property('directory', $this->path)
|
})
|
||||||
->property('files', $files)
|
->schema([
|
||||||
->log();
|
TextInput::make('name')
|
||||||
|
->label('Folder Name')
|
||||||
|
->required(),
|
||||||
|
]),
|
||||||
|
Action::make('upload')
|
||||||
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
|
||||||
|
->hiddenLabel()->icon('tabler-upload')->iconButton()->iconSize(IconSize::ExtraLarge)
|
||||||
|
->tooltip('Upload')
|
||||||
|
->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());
|
||||||
|
|
||||||
Notification::make()
|
Activity::event('server:file.uploaded')
|
||||||
->title('Archive created')
|
->property('directory', $this->path)
|
||||||
->body($archive['name'])
|
->property('file', $file->getClientOriginalName())
|
||||||
->success()
|
->log();
|
||||||
->send();
|
}
|
||||||
|
} elseif ($data['url'] !== null) {
|
||||||
|
$this->getDaemonFileRepository()->pull($data['url'], $this->path);
|
||||||
|
|
||||||
|
Activity::event('server:file.pull')
|
||||||
|
->property('url', $data['url'])
|
||||||
|
->property('directory', $this->path)
|
||||||
|
->log();
|
||||||
|
}
|
||||||
|
|
||||||
return redirect(ListFiles::getUrl(['path' => $this->path]));
|
return redirect(ListFiles::getUrl(['path' => $this->path]));
|
||||||
}),
|
})
|
||||||
DeleteBulkAction::make()
|
->schema([
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_DELETE, $server))
|
Tabs::make()
|
||||||
->action(function (Collection $files) {
|
->contained(false)
|
||||||
$files = $files->map(fn ($file) => $file['name'])->toArray();
|
->schema([
|
||||||
$this->getDaemonFileRepository()->deleteFiles($this->path, $files);
|
Tab::make('Upload Files')
|
||||||
|
->live()
|
||||||
Activity::event('server:file.delete')
|
->schema([
|
||||||
->property('directory', $this->path)
|
FileUpload::make('files')
|
||||||
->property('files', $files)
|
->storeFiles(false)
|
||||||
->log();
|
->previewable(false)
|
||||||
|
->preserveFilenames()
|
||||||
Notification::make()
|
->maxSize((int) round($server->node->upload_size * (config('panel.use_binary_prefix') ? 1.048576 * 1024 : 1000)))
|
||||||
->title(count($files) . ' Files deleted.')
|
->multiple(),
|
||||||
->success()
|
]),
|
||||||
->send();
|
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,
|
||||||
|
]))),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,133 +545,7 @@ class ListFiles extends ListRecords
|
|||||||
*/
|
*/
|
||||||
protected function getDefaultHeaderActions(): array
|
protected function getDefaultHeaderActions(): array
|
||||||
{
|
{
|
||||||
/** @var Server $server */
|
return [];
|
||||||
$server = Filament::getTenant();
|
|
||||||
|
|
||||||
return [
|
|
||||||
Action::make('new_file')
|
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
|
|
||||||
->label('New File')
|
|
||||||
->color('gray')
|
|
||||||
->keyBindings('')
|
|
||||||
->modalSubmitActionLabel('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()
|
|
||||||
->title('<code>' . $path . '</code> already exists!')
|
|
||||||
->danger()
|
|
||||||
->closable()
|
|
||||||
->send();
|
|
||||||
|
|
||||||
$this->redirect(self::getUrl(['path' => dirname($path)]));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
->schema([
|
|
||||||
TextInput::make('name')
|
|
||||||
->label('Name')
|
|
||||||
->required(),
|
|
||||||
CodeEditor::make('editor')
|
|
||||||
->hiddenLabel(),
|
|
||||||
]),
|
|
||||||
Action::make('new_folder')
|
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
|
|
||||||
->label('New Folder')
|
|
||||||
->color('gray')
|
|
||||||
->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()
|
|
||||||
->title('<code>' . $path . '</code> already exists!')
|
|
||||||
->danger()
|
|
||||||
->closable()
|
|
||||||
->send();
|
|
||||||
|
|
||||||
$this->redirect(self::getUrl(['path' => dirname($path)]));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
->schema([
|
|
||||||
TextInput::make('name')
|
|
||||||
->label('Folder Name')
|
|
||||||
->required(),
|
|
||||||
]),
|
|
||||||
Action::make('upload')
|
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_CREATE, $server))
|
|
||||||
->label('Upload')
|
|
||||||
->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)
|
|
||||||
->property('file', $file->getClientOriginalName())
|
|
||||||
->log();
|
|
||||||
}
|
|
||||||
} elseif ($data['url'] !== null) {
|
|
||||||
$this->getDaemonFileRepository()->pull($data['url'], $this->path);
|
|
||||||
|
|
||||||
Activity::event('server:file.pull')
|
|
||||||
->property('url', $data['url'])
|
|
||||||
->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))
|
|
||||||
->label('Global 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,
|
|
||||||
]))),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Filament\Server\Resources;
|
namespace App\Filament\Server\Resources;
|
||||||
|
|
||||||
|
use App\Filament\Components\Actions\ImportScheduleAction;
|
||||||
use App\Filament\Server\Resources\ScheduleResource\Pages\ListSchedules;
|
use App\Filament\Server\Resources\ScheduleResource\Pages\ListSchedules;
|
||||||
use App\Filament\Server\Resources\ScheduleResource\Pages\CreateSchedule;
|
use App\Filament\Server\Resources\ScheduleResource\Pages\CreateSchedule;
|
||||||
use App\Filament\Server\Resources\ScheduleResource\Pages\ViewSchedule;
|
use App\Filament\Server\Resources\ScheduleResource\Pages\ViewSchedule;
|
||||||
@ -20,6 +21,7 @@ use App\Traits\Filament\CanModifyForm;
|
|||||||
use App\Traits\Filament\CanModifyTable;
|
use App\Traits\Filament\CanModifyTable;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Filament\Actions\CreateAction;
|
||||||
use Filament\Actions\DeleteAction;
|
use Filament\Actions\DeleteAction;
|
||||||
use Filament\Actions\EditAction;
|
use Filament\Actions\EditAction;
|
||||||
use Filament\Actions\ViewAction;
|
use Filament\Actions\ViewAction;
|
||||||
@ -38,6 +40,7 @@ use Filament\Resources\Pages\PageRegistration;
|
|||||||
use Filament\Resources\RelationManagers\RelationManager;
|
use Filament\Resources\RelationManagers\RelationManager;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
use Filament\Schemas\Schema;
|
use Filament\Schemas\Schema;
|
||||||
|
use Filament\Support\Enums\IconSize;
|
||||||
use Filament\Support\Exceptions\Halt;
|
use Filament\Support\Exceptions\Halt;
|
||||||
use Filament\Tables\Columns\IconColumn;
|
use Filament\Tables\Columns\IconColumn;
|
||||||
use Filament\Tables\Columns\TextColumn;
|
use Filament\Tables\Columns\TextColumn;
|
||||||
@ -334,6 +337,18 @@ class ScheduleResource extends Resource
|
|||||||
->property('name', $schedule->name)
|
->property('name', $schedule->name)
|
||||||
->log();
|
->log();
|
||||||
}),
|
}),
|
||||||
|
])
|
||||||
|
->toolbarActions([
|
||||||
|
CreateAction::make()
|
||||||
|
->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge)
|
||||||
|
->icon('tabler-calendar-plus')
|
||||||
|
->color('primary')
|
||||||
|
->tooltip('New Schedule'),
|
||||||
|
ImportScheduleAction::make()
|
||||||
|
->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge)
|
||||||
|
->icon('tabler-file-import')
|
||||||
|
->color('success')
|
||||||
|
->tooltip('Import Schedule'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Filament\Server\Resources\ScheduleResource\Pages;
|
namespace App\Filament\Server\Resources\ScheduleResource\Pages;
|
||||||
|
|
||||||
use App\Filament\Components\Actions\ImportScheduleAction;
|
|
||||||
use App\Filament\Server\Resources\ScheduleResource;
|
use App\Filament\Server\Resources\ScheduleResource;
|
||||||
use App\Traits\Filament\CanCustomizeHeaderActions;
|
use App\Traits\Filament\CanCustomizeHeaderActions;
|
||||||
use App\Traits\Filament\CanCustomizeHeaderWidgets;
|
use App\Traits\Filament\CanCustomizeHeaderWidgets;
|
||||||
use Filament\Actions\Action;
|
use Filament\Actions\Action;
|
||||||
use Filament\Actions\ActionGroup;
|
use Filament\Actions\ActionGroup;
|
||||||
use Filament\Actions\CreateAction;
|
|
||||||
use Filament\Resources\Pages\ListRecords;
|
use Filament\Resources\Pages\ListRecords;
|
||||||
|
|
||||||
class ListSchedules extends ListRecords
|
class ListSchedules extends ListRecords
|
||||||
@ -21,11 +19,7 @@ class ListSchedules extends ListRecords
|
|||||||
/** @return array<Action|ActionGroup> */
|
/** @return array<Action|ActionGroup> */
|
||||||
protected function getDefaultHeaderActions(): array
|
protected function getDefaultHeaderActions(): array
|
||||||
{
|
{
|
||||||
return [
|
return [];
|
||||||
CreateAction::make()
|
|
||||||
->label('New Schedule'),
|
|
||||||
ImportScheduleAction::make(),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBreadcrumbs(): array
|
public function getBreadcrumbs(): array
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Filament\Server\Resources;
|
namespace App\Filament\Server\Resources;
|
||||||
|
|
||||||
|
use App\Facades\Activity;
|
||||||
use App\Filament\Server\Resources\UserResource\Pages\ListUsers;
|
use App\Filament\Server\Resources\UserResource\Pages\ListUsers;
|
||||||
use App\Models\Permission;
|
use App\Models\Permission;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Services\Subusers\SubuserCreationService;
|
||||||
use App\Services\Subusers\SubuserDeletionService;
|
use App\Services\Subusers\SubuserDeletionService;
|
||||||
use App\Services\Subusers\SubuserUpdateService;
|
use App\Services\Subusers\SubuserUpdateService;
|
||||||
use App\Traits\Filament\BlockAccessInConflict;
|
use App\Traits\Filament\BlockAccessInConflict;
|
||||||
@ -13,6 +15,8 @@ use App\Traits\Filament\CanCustomizePages;
|
|||||||
use App\Traits\Filament\CanCustomizeRelations;
|
use App\Traits\Filament\CanCustomizeRelations;
|
||||||
use App\Traits\Filament\CanModifyTable;
|
use App\Traits\Filament\CanModifyTable;
|
||||||
use App\Traits\Filament\HasLimitBadge;
|
use App\Traits\Filament\HasLimitBadge;
|
||||||
|
use Exception;
|
||||||
|
use Filament\Actions\CreateAction;
|
||||||
use Filament\Facades\Filament;
|
use Filament\Facades\Filament;
|
||||||
use Filament\Actions\Action;
|
use Filament\Actions\Action;
|
||||||
use Filament\Forms\Components\CheckboxList;
|
use Filament\Forms\Components\CheckboxList;
|
||||||
@ -22,12 +26,14 @@ use Filament\Schemas\Components\Section;
|
|||||||
use Filament\Schemas\Components\Tabs;
|
use Filament\Schemas\Components\Tabs;
|
||||||
use Filament\Schemas\Components\Tabs\Tab;
|
use Filament\Schemas\Components\Tabs\Tab;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Schemas\Components\Utilities\Get;
|
||||||
use Filament\Schemas\Components\Utilities\Set;
|
use Filament\Schemas\Components\Utilities\Set;
|
||||||
use Filament\Notifications\Notification;
|
use Filament\Notifications\Notification;
|
||||||
use Filament\Actions\DeleteAction;
|
use Filament\Actions\DeleteAction;
|
||||||
use Filament\Resources\Pages\PageRegistration;
|
use Filament\Resources\Pages\PageRegistration;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
use Filament\Actions\EditAction;
|
use Filament\Actions\EditAction;
|
||||||
|
use Filament\Support\Enums\IconSize;
|
||||||
use Filament\Tables\Columns\ImageColumn;
|
use Filament\Tables\Columns\ImageColumn;
|
||||||
use Filament\Tables\Columns\TextColumn;
|
use Filament\Tables\Columns\TextColumn;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
@ -113,7 +119,7 @@ class UserResource extends Resource
|
|||||||
|
|
||||||
return $table
|
return $table
|
||||||
->paginated(false)
|
->paginated(false)
|
||||||
->searchable(false)
|
// ->searchable(false) TODO toolbarActions do not render without the search bar :/
|
||||||
->columns([
|
->columns([
|
||||||
ImageColumn::make('picture')
|
ImageColumn::make('picture')
|
||||||
->visibleFrom('lg')
|
->visibleFrom('lg')
|
||||||
@ -221,7 +227,101 @@ class UserResource extends Resource
|
|||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}),
|
}),
|
||||||
]);
|
])
|
||||||
|
->toolbarActions([
|
||||||
|
CreateAction::make('invite')
|
||||||
|
->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge)
|
||||||
|
->icon('tabler-user-plus')
|
||||||
|
->tooltip('Invite User')
|
||||||
|
->createAnother(false)
|
||||||
|
->authorize(fn () => auth()->user()->can(Permission::ACTION_USER_CREATE, $server))
|
||||||
|
->schema([
|
||||||
|
Grid::make()
|
||||||
|
->columnSpanFull()
|
||||||
|
->columns([
|
||||||
|
'default' => 1,
|
||||||
|
'sm' => 1,
|
||||||
|
'md' => 5,
|
||||||
|
'lg' => 6,
|
||||||
|
])
|
||||||
|
->schema([
|
||||||
|
TextInput::make('email')
|
||||||
|
->email()
|
||||||
|
->inlineLabel()
|
||||||
|
->columnSpan([
|
||||||
|
'default' => 1,
|
||||||
|
'sm' => 1,
|
||||||
|
'md' => 4,
|
||||||
|
'lg' => 5,
|
||||||
|
])
|
||||||
|
->required(),
|
||||||
|
Actions::make([
|
||||||
|
Action::make('assignAll')
|
||||||
|
->label('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,
|
||||||
|
]),
|
||||||
|
Tabs::make()
|
||||||
|
->columnSpanFull()
|
||||||
|
->schema($tabs),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
->modalHeading('Invite User')
|
||||||
|
->modalIcon('tabler-user-plus')
|
||||||
|
->modalSubmitActionLabel('Invite')
|
||||||
|
->successNotificationTitle(null)
|
||||||
|
->failureNotificationTitle(null)
|
||||||
|
->action(function (Action $action, array $data, SubuserCreationService $service) use ($server) {
|
||||||
|
$email = strtolower($data['email']);
|
||||||
|
|
||||||
|
$permissions = collect($data)
|
||||||
|
->forget('email')
|
||||||
|
->flatMap(fn ($permissions, $key) => collect($permissions)->map(fn ($permission) => "$key.$permission"))
|
||||||
|
->push(Permission::ACTION_WEBSOCKET_CONNECT)
|
||||||
|
->unique()
|
||||||
|
->all();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$subuser = $service->handle($server, $email, $permissions);
|
||||||
|
|
||||||
|
Activity::event('server:subuser.create')
|
||||||
|
->subject($subuser->user)
|
||||||
|
->property([
|
||||||
|
'email' => $data['email'],
|
||||||
|
'permissions' => $permissions,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Notification::make()
|
||||||
|
->title('User Invited!')
|
||||||
|
->success()
|
||||||
|
->send();
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
Notification::make()
|
||||||
|
->title('Failed')
|
||||||
|
->body($exception->getMessage())
|
||||||
|
->danger()
|
||||||
|
->send();
|
||||||
|
|
||||||
|
$action->failure();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$action->success();
|
||||||
|
|
||||||
|
return redirect(self::getUrl(tenant: $server));
|
||||||
|
}), ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return array<string, PageRegistration> */
|
/** @return array<string, PageRegistration> */
|
||||||
|
@ -2,28 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Filament\Server\Resources\UserResource\Pages;
|
namespace App\Filament\Server\Resources\UserResource\Pages;
|
||||||
|
|
||||||
use App\Facades\Activity;
|
|
||||||
use App\Filament\Server\Resources\UserResource;
|
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\CanCustomizeHeaderActions;
|
||||||
use App\Traits\Filament\CanCustomizeHeaderWidgets;
|
use App\Traits\Filament\CanCustomizeHeaderWidgets;
|
||||||
use Exception;
|
|
||||||
use Filament\Actions\CreateAction;
|
|
||||||
use Filament\Actions\Action;
|
use Filament\Actions\Action;
|
||||||
use Filament\Actions\ActionGroup;
|
use Filament\Actions\ActionGroup;
|
||||||
use Filament\Facades\Filament;
|
|
||||||
use Filament\Forms\Components\CheckboxList;
|
|
||||||
use Filament\Schemas\Components\Actions;
|
|
||||||
use Filament\Schemas\Components\Grid;
|
|
||||||
use Filament\Schemas\Components\Section;
|
|
||||||
use Filament\Schemas\Components\Tabs;
|
|
||||||
use Filament\Schemas\Components\Tabs\Tab;
|
|
||||||
use Filament\Forms\Components\TextInput;
|
|
||||||
use Filament\Schemas\Components\Utilities\Get;
|
|
||||||
use Filament\Schemas\Components\Utilities\Set;
|
|
||||||
use Filament\Notifications\Notification;
|
|
||||||
use Filament\Resources\Pages\ListRecords;
|
use Filament\Resources\Pages\ListRecords;
|
||||||
|
|
||||||
class ListUsers extends ListRecords
|
class ListUsers extends ListRecords
|
||||||
@ -36,130 +19,7 @@ class ListUsers extends ListRecords
|
|||||||
/** @return array<Action|ActionGroup> */
|
/** @return array<Action|ActionGroup> */
|
||||||
protected function getDefaultHeaderActions(): array
|
protected function getDefaultHeaderActions(): array
|
||||||
{
|
{
|
||||||
/** @var Server $server */
|
return [];
|
||||||
$server = Filament::getTenant();
|
|
||||||
|
|
||||||
$tabs = [];
|
|
||||||
$permissionsArray = [];
|
|
||||||
|
|
||||||
foreach (Permission::permissionData() as $data) {
|
|
||||||
$options = [];
|
|
||||||
$descriptions = [];
|
|
||||||
|
|
||||||
foreach ($data['permissions'] as $permission) {
|
|
||||||
$options[$permission] = str($permission)->headline();
|
|
||||||
$descriptions[$permission] = trans('server/users.permissions.' . $data['name'] . '_' . str($permission)->replace('-', '_'));
|
|
||||||
$permissionsArray[$data['name']][] = $permission;
|
|
||||||
}
|
|
||||||
|
|
||||||
$tabs[] = Tab::make(str($data['name'])->headline())
|
|
||||||
->schema([
|
|
||||||
Section::make()
|
|
||||||
->description(trans('server/users.permissions.' . $data['name'] . '_desc'))
|
|
||||||
->icon($data['icon'])
|
|
||||||
->schema([
|
|
||||||
CheckboxList::make($data['name'])
|
|
||||||
->label('')
|
|
||||||
->bulkToggleable()
|
|
||||||
->columns(2)
|
|
||||||
->options($options)
|
|
||||||
->descriptions($descriptions),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
CreateAction::make('invite')
|
|
||||||
->label('Invite User')
|
|
||||||
->createAnother(false)
|
|
||||||
->authorize(fn () => auth()->user()->can(Permission::ACTION_USER_CREATE, $server))
|
|
||||||
->schema([
|
|
||||||
Grid::make()
|
|
||||||
->columnSpanFull()
|
|
||||||
->columns([
|
|
||||||
'default' => 1,
|
|
||||||
'sm' => 1,
|
|
||||||
'md' => 5,
|
|
||||||
'lg' => 6,
|
|
||||||
])
|
|
||||||
->schema([
|
|
||||||
TextInput::make('email')
|
|
||||||
->email()
|
|
||||||
->inlineLabel()
|
|
||||||
->columnSpan([
|
|
||||||
'default' => 1,
|
|
||||||
'sm' => 1,
|
|
||||||
'md' => 4,
|
|
||||||
'lg' => 5,
|
|
||||||
])
|
|
||||||
->required(),
|
|
||||||
Actions::make([
|
|
||||||
Action::make('assignAll')
|
|
||||||
->label('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,
|
|
||||||
]),
|
|
||||||
Tabs::make()
|
|
||||||
->columnSpanFull()
|
|
||||||
->schema($tabs),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
->modalHeading('Invite User')
|
|
||||||
->modalSubmitActionLabel('Invite')
|
|
||||||
->successNotificationTitle(null)
|
|
||||||
->failureNotificationTitle(null)
|
|
||||||
->action(function (Action $action, array $data, SubuserCreationService $service) use ($server) {
|
|
||||||
$email = strtolower($data['email']);
|
|
||||||
|
|
||||||
$permissions = collect($data)
|
|
||||||
->forget('email')
|
|
||||||
->flatMap(fn ($permissions, $key) => collect($permissions)->map(fn ($permission) => "$key.$permission"))
|
|
||||||
->push(Permission::ACTION_WEBSOCKET_CONNECT)
|
|
||||||
->unique()
|
|
||||||
->all();
|
|
||||||
|
|
||||||
try {
|
|
||||||
$subuser = $service->handle($server, $email, $permissions);
|
|
||||||
|
|
||||||
Activity::event('server:subuser.create')
|
|
||||||
->subject($subuser->user)
|
|
||||||
->property([
|
|
||||||
'email' => $data['email'],
|
|
||||||
'permissions' => $permissions,
|
|
||||||
]);
|
|
||||||
|
|
||||||
Notification::make()
|
|
||||||
->title('User Invited!')
|
|
||||||
->success()
|
|
||||||
->send();
|
|
||||||
} catch (Exception $exception) {
|
|
||||||
Notification::make()
|
|
||||||
->title('Failed')
|
|
||||||
->body($exception->getMessage())
|
|
||||||
->danger()
|
|
||||||
->send();
|
|
||||||
|
|
||||||
$action->failure();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$action->success();
|
|
||||||
|
|
||||||
return redirect(self::getUrl(tenant: $server));
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBreadcrumbs(): array
|
public function getBreadcrumbs(): array
|
||||||
|
Loading…
x
Reference in New Issue
Block a user