*/
public ?array $data = [];
public function form(Form $form): Form
{
/** @var Server $server */
$server = Filament::getTenant();
Activity::event('server:file.read')
->property('file', $this->path)
->log();
return $form
->schema([
Section::make('Editing: ' . $this->path)
->footerActions([
Action::make('save_and_close')
->label('Save & Close')
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
->icon('tabler-device-floppy')
->keyBindings('mod+shift+s')
->action(function (array $data) {
$this->getDaemonFileRepository()
->putContent($this->path, $data['editor'] ?? '');
Activity::event('server:file.write')
->property('file', $this->path)
->log();
Notification::make()
->success()
->title('File saved')
->body(fn () => $this->path)
->send();
$this->redirect(ListFiles::getUrl(['path' => dirname($this->path)]));
}),
Action::make('save')
->label('Save')
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_UPDATE, $server))
->icon('tabler-device-floppy')
->keyBindings('mod+s')
->action(function (array $data) {
$this->getDaemonFileRepository()
->putContent($this->path, $data['editor'] ?? '');
Activity::event('server:file.write')
->property('file', $this->path)
->log();
Notification::make()
->success()
->title('File saved')
->body(fn () => $this->path)
->send();
}),
Action::make('cancel')
->label('Cancel')
->color('danger')
->icon('tabler-x')
->url(fn () => ListFiles::getUrl(['path' => dirname($this->path)])),
])
->footerActionsAlignment(Alignment::End)
->schema([
Select::make('lang')
->label('Syntax Highlighting')
->live()
->options(EditorLanguages::class)
->selectablePlaceholder(false)
->afterStateUpdated(fn ($state) => $this->dispatch('setLanguage', lang: $state))
->default(fn () => EditorLanguages::fromWithAlias(pathinfo($this->path, PATHINFO_EXTENSION))),
MonacoEditor::make('editor')
->hiddenLabel()
->showPlaceholder(false)
->default(function () {
try {
return $this->getDaemonFileRepository()
->getContent($this->path, config('panel.files.max_edit_size'));
} catch (FileSizeTooLargeException) {
AlertBanner::make()
->title('File too large!')
->body('' . $this->path . '
Max is ' . convert_bytes_to_readable(config('panel.files.max_edit_size')))
->danger()
->closable()
->send();
$this->redirect(ListFiles::getUrl());
} catch (FileNotFoundException) {
AlertBanner::make()
->title('File Not found!')
->body('' . $this->path . '
')
->danger()
->closable()
->send();
$this->redirect(ListFiles::getUrl());
} catch (FileNotEditableException) {
AlertBanner::make()
->title('Could not edit directory!')
->body('' . $this->path . '
')
->danger()
->closable()
->send();
$this->redirect(ListFiles::getUrl());
}
})
->language(fn (Get $get) => $get('lang'))
->view('filament.plugins.monaco-editor'),
]),
]);
}
public function mount(string $path): void
{
$this->authorizeAccess();
$this->path = $path;
$this->form->fill();
if (str($path)->endsWith('.pelicanignore')) {
AlertBanner::make('.pelicanignore_info')
->title('You\'re editing a .pelicanignore
file!')
->body('Any files or directories listed in here will be excluded from backups. Wildcards are supported by using an asterisk (*
).
You can negate a prior rule by prepending an exclamation point (!
).')
->info()
->closable()
->send();
}
}
protected function authorizeAccess(): void
{
abort_unless(auth()->user()->can(Permission::ACTION_FILE_READ_CONTENT, Filament::getTenant()), 403);
}
/**
* @return array
*/
protected function getForms(): array
{
return [
'form' => $this->form(static::getResource()::form(
$this->makeForm()
->statePath($this->getFormStatePath())
->columns($this->hasInlineLabels() ? 1 : 2)
->inlineLabel($this->hasInlineLabels()),
)),
];
}
public function getFormStatePath(): ?string
{
return 'data';
}
public function getBreadcrumbs(): array
{
$resource = static::getResource();
$breadcrumbs = [
$resource::getUrl() => $resource::getBreadcrumb(),
];
$previousParts = '';
foreach (explode('/', $this->path) as $part) {
$previousParts = $previousParts . '/' . $part;
$breadcrumbs[self::getUrl(['path' => ltrim($previousParts, '/')])] = $part;
}
return $breadcrumbs;
}
private function getDaemonFileRepository(): DaemonFileRepository
{
/** @var Server $server */
$server = Filament::getTenant();
$this->fileRepository ??= (new DaemonFileRepository())->setServer($server);
return $this->fileRepository;
}
public static function route(string $path): PageRegistration
{
return new PageRegistration(
page: static::class,
route: fn (Panel $panel): Route => RouteFacade::get($path, static::class)
->middleware(static::getRouteMiddleware($panel))
->withoutMiddleware(static::getWithoutRouteMiddleware($panel))
->where('path', '.*'),
);
}
}