Compare commits

...

14 commits

Author SHA1 Message Date
Bozhidar
2dd5c109c8 Update DockerContainerResource.php 2024-04-27 21:25:40 +03:00
Bozhidar
2c6a461ac5 Update logs.blade.php 2024-04-27 21:22:45 +03:00
Bozhidar
6d225b58b1 Update DockerTemplateResource.php.stop-for-now 2024-04-27 21:21:44 +03:00
Bozhidar
d4c78480df update 2024-04-27 21:21:27 +03:00
Bozhidar
671399b606 update 2024-04-27 20:59:59 +03:00
Bozhidar
02e6953022 Update 2024_04_19_222101_create_docker_containers_table.php 2024-04-27 20:49:14 +03:00
Bozhidar
e48682965c Update DockerContainerResource.php 2024-04-27 20:37:57 +03:00
Bozhidar
5ae6773758 Update DockerTemplateResource.php 2024-04-27 19:48:54 +03:00
Bozhidar
ed2c7f1c43 add docker templates 2024-04-27 15:15:01 +03:00
Bozhidar
3be82bde08 update 2024-04-27 14:24:41 +03:00
Bozhidar
5a3a3611d0 update 2024-04-27 14:09:53 +03:00
Bozhidar
35a6305d93 update 2024-04-27 14:05:27 +03:00
Bozhidar
11d32fcefe update 2024-04-27 13:58:44 +03:00
Bozhidar
9ffc1cf1fa make docker on separated navigation 2024-04-27 13:49:43 +03:00
34 changed files with 690 additions and 59 deletions

View file

@ -37,6 +37,9 @@ class DockerContainer extends Model
'external_port',
'volume_mapping',
'environment_variables',
'build_type',
'docker_template_id',
'docker_compose'
];
protected $casts = [
@ -81,7 +84,12 @@ class DockerContainer extends Model
$dockerContainerApi->setName(Str::slug($model->name.'-phyre-'.$nextId));
$dockerContainerApi->setExternalPort($model->external_port);
if ($model->build_type == 'template') {
$dockerContainerApi->setDockerCompose($model->docker_compose);
}
$createContainer = $dockerContainerApi->run();
if (!isset($createContainer['ID'])) {
return false;
}

View file

@ -0,0 +1,22 @@
<?php
namespace Modules\Docker\App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class DockerTemplate extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*/
protected $fillable = [
'name',
'description',
'docker_compose',
];
}

View file

@ -29,6 +29,10 @@ return new class extends Migration
$table->string('state')->nullable();
$table->string('status')->nullable();
$table->string('build_type')->nullable();
$table->integer('docker_template_id')->nullable();
$table->longText('docker_compose')->nullable();
$table->string('memory_limit')->nullable();
$table->tinyInteger('unlimited_memory')->nullable();
$table->tinyInteger('automatic_start')->nullable();

View file

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('docker_templates', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('description')->nullable();
$table->longText('docker_compose')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('docker_templates');
}
};

View file

@ -14,6 +14,8 @@ class DockerContainerApi
public $port = '';
public $externalPort = '';
public $dockerCompose = '';
public function setName($name)
{
$name = trim($name);
@ -47,6 +49,11 @@ class DockerContainerApi
$this->externalPort = $externalPort;
}
public function setDockerCompose($dockerCompose)
{
$this->dockerCompose = $dockerCompose;
}
public function recreate($containerId)
{
shell_exec('docker stop ' . $containerId);
@ -59,14 +66,18 @@ class DockerContainerApi
{
$commandId = rand(10000, 99999);
$dockerComposeFileContent = view('docker::actions.docker-compose-yml', [
'name' => $this->name,
'image' => $this->image,
'port' => $this->port,
'externalPort' => $this->externalPort,
'environmentVariables' => $this->environmentVariables,
'volumeMapping' => $this->volumeMapping,
])->render();
if (!empty($this->dockerCompose)) {
$dockerComposeFileContent = $this->dockerCompose;
} else {
$dockerComposeFileContent = view('docker::actions.docker-compose-yml', [
'name' => $this->name,
'image' => $this->image,
'port' => $this->port,
'externalPort' => $this->externalPort,
'environmentVariables' => $this->environmentVariables,
'volumeMapping' => $this->volumeMapping,
])->render();
}
$dockerContaienrPath = storage_path('docker/'.$this->name);
if (!is_dir($dockerContaienrPath)) {

View file

@ -26,13 +26,17 @@ class DockerCatalog extends Page implements HasForms
{
use InteractsWithForms;
// protected static ?string $navigationGroup = 'Docker';
protected static ?string $navigationGroup = 'Docker';
protected static ?string $cluster = DockerCluster::class;
protected static ?string $navigationLabel = 'Catalog';
protected static ?string $navigationIcon = 'heroicon-o-cog';
protected static ?string $slug = 'docker/catalog';
protected static ?int $navigationSort = 1;
// protected static ?string $cluster = DockerCluster::class;
protected static ?string $navigationIcon = 'docker-catalog';
protected static ?int $navigationSort = 2;
protected static string $view = 'docker::filament.pages.docker-catalog';
@ -67,7 +71,7 @@ class DockerCatalog extends Page implements HasForms
$this->pullLogPulling = false;
$this->dispatch('close-modal', id: 'pull-docker-image');
return $this->redirect(route('filament.admin.docker.resources.docker-containers.create') . '?dockerImage=' . $this->pullImageName);
return $this->redirect('/admin/docker/containers/create?dockerImage=' . $this->pullImageName);
}
}

View file

@ -13,10 +13,14 @@ class Settings extends BaseSettings
{
protected static ?string $navigationGroup = 'Docker';
protected static ?string $cluster = DockerCluster::class;
protected static ?string $navigationLabel = 'Settings';
// protected static ?string $cluster = DockerCluster::class;
protected static ?string $navigationIcon = 'heroicon-o-cog';
protected static ?string $slug = 'docker/settings';
protected static ?int $navigationSort = 3;
public function schema(): array

View file

@ -10,23 +10,31 @@ use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Modules\Docker\App\Models\DockerContainer;
use Modules\Docker\App\Models\DockerTemplate;
use Modules\Docker\DockerApi;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerContainerResource\Pages\CreateDockerContainer;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerContainerResource\Pages\EditDockerContainer;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerContainerResource\Pages\ListDockerContainers;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerContainerResource\Pages\ViewDockerContainer;
use Modules\Docker\Filament\Clusters\DockerCluster;
use Riodwanto\FilamentAceEditor\AceEditor;
class DockerContainerResource extends Resource
{
protected static ?string $navigationGroup = 'Docker';
protected static ?string $navigationLabel = 'Containers';
protected static ?string $slug = 'docker/containers';
protected static ?string $model = DockerContainer::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $navigationIcon = 'docker-logo';
protected static ?string $cluster = DockerCluster::class;
// protected static ?string $cluster = DockerCluster::class;
protected static ?int $navigationSort = 2;
protected static ?int $navigationSort = 1;
public static function form(Form $form): Form
{
@ -69,12 +77,61 @@ class DockerContainerResource extends Resource
$defaultPort = 83;
}
$dockerTemplateContent = '';
$dockerTemplateId = request()->get('docker_template_id', null);
$findDockerTemplate = DockerTemplate::find($dockerTemplateId);
if ($findDockerTemplate) {
$dockerTemplateContent = $findDockerTemplate->docker_compose;
}
$buildType = request()->get('build_type', null);
return $form
->schema([
Forms\Components\TextInput::make('name')
->default($dockerFullImageName)
->label('Container Name')->columnSpanFull(),
Forms\Components\Select::make('build_type')
->label('Build container from')
->live()
->default('image')
->options([
// 'template'=>'Docker Template',
'image'=>'Docker Image'
])
->columnSpanFull(),
Forms\Components\Select::make('docker_template_id')
->label('Template')
->default($dockerTemplateId)
->hidden(function (Forms\Get $get) {
return $get('build_type') != 'template';
})
->live()
->afterStateUpdated(function (Forms\Get $get, Forms\Set $set, ?string $old, ?string $state) {
return redirect('/admin/docker/containers/create?build_type=template&docker_template_id=' . $state);
})
->options(DockerTemplate::all()->pluck('name', 'id'))
->columnSpanFull(),
Forms\Components\Select::make('image')
->label('Image')
->hidden(function (Forms\Get $get) {
return $get('build_type') != 'image';
})
->options([$dockerImage=>$dockerFullImageName])
->default($dockerImage)->columnSpanFull(),
AceEditor::make('docker_compose')
->hidden(function (Forms\Get $get) {
return $get('build_type') != 'template';
})
->mode('yml')
->theme('github')
->default($dockerTemplateContent)
->columnSpanFull()
->darkTheme('dracula'),
Forms\Components\TextInput::make('memory_limit')
->label('Memory Limit (MB)')
->default(512)
@ -90,28 +147,34 @@ class DockerContainerResource extends Resource
Forms\Components\TextInput::make('port')
->label('Port')
->hidden(function (Forms\Get $get) {
return $get('build_type') != 'image';
})
// ->disabled()
->default($defaultPort)
->columnSpan(1),
Forms\Components\TextInput::make('external_port')
->label('External Port')
->hidden(function (Forms\Get $get) {
return $get('build_type') != 'image';
})
// ->disabled()
->default($defaultExternalPort)
->columnSpan(1),
Forms\Components\Select::make('image')
->label('Image')
->options([$dockerImage=>$dockerFullImageName])
->default($dockerImage)->columnSpanFull(),
Forms\Components\KeyValue::make('volume_mapping')
->label('Volume Mapping')
->hidden(function (Forms\Get $get) {
return $get('build_type') != 'image';
})
->columnSpanFull(),
Forms\Components\KeyValue::make('environment_variables')
->label('Environment Variables')
->hidden(function (Forms\Get $get) {
return $get('build_type') != 'image';
})
->default($environmentVariables)
->columnSpanFull(),
@ -122,7 +185,13 @@ class DockerContainerResource extends Resource
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('state')->badge(),
Tables\Columns\TextColumn::make('status'),
Tables\Columns\TextColumn::make('image'),
Tables\Columns\TextColumn::make('port'),
Tables\Columns\TextColumn::make('external_port'),
])
->filters([
//

View file

@ -36,33 +36,33 @@ class ViewDockerContainer extends ViewRecord
return $infolist
->schema([
ViewEntry::make('status')
->columnSpanFull()
->view('docker::filament.infolists.docker-container.actions')
->registerActions([
Actions\Action::make('stop')
->label('Stop')
->color('primary'),
Actions\Action::make('start')
->label('Start')
->color('primary'),
Actions\Action::make('restart')
->label('Restart')
->color('success'),
Actions\Action::make('recreate')
->label('Recreate')
->action('recreate')
->color('info'),
Actions\Action::make('delete')
->label('Delete')
->color('danger'),
]),
// ViewEntry::make('status')
// ->columnSpanFull()
// ->view('docker::filament.infolists.docker-container.actions')
// ->registerActions([
// Actions\Action::make('stop')
// ->label('Stop')
// ->color('primary'),
//
// Actions\Action::make('start')
// ->label('Start')
// ->color('primary'),
//
// Actions\Action::make('restart')
// ->label('Restart')
// ->color('success'),
//
//
// Actions\Action::make('recreate')
// ->label('Recreate')
// ->action('recreate')
// ->color('info'),
//
//
// Actions\Action::make('delete')
// ->label('Delete')
// ->color('danger'),
// ]),
ViewEntry::make('containerLogs')
->columnSpanFull()

View file

@ -0,0 +1,135 @@
<?php
namespace Modules\Docker\Filament\Clusters\Docker\Resources;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Modules\Docker\App\Models\DockerTemplate;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource\Pages\CreateDockerTemplate;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource\Pages\EditDockerTemplate;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource\Pages\ListDockerTemplates;
use Riodwanto\FilamentAceEditor\AceEditor;
class DockerTemplateResource extends Resource
{
protected static ?string $navigationGroup = 'Docker';
protected static ?string $navigationLabel = 'Templates';
protected static ?string $slug = 'docker/templates';
protected static ?string $model = DockerTemplate::class;
protected static ?string $navigationIcon = 'docker-templates';
protected static ?int $navigationSort = 3;
public static function form(Form $form): Form
{
$dockerTemplate = request()->get('docker_template', null);
try {
$dockerTemplateContent = file_get_contents(module_path('Docker', 'resources/views/docker-templates/' . $dockerTemplate . '.yml'));
} catch (\Exception $e) {
$dockerTemplateContent = '';
}
return $form
->schema([
Forms\Components\TextInput::make('name')
->label('Name')
->unique('docker_templates', 'name')
->default(ucfirst($dockerTemplate))
->required()
->placeholder('Enter the name of the template'),
// Forms\Components\TextInput::make('description')
// ->label('Description')
// ->placeholder('Enter the description of the template'),
Forms\Components\Select::make('docker_template')
->label('Docker Template')
->columnSpanFull()
->hidden(function($record) {
return $record;
})
->live()
->default($dockerTemplate)
->options([
'microweber' => 'Microweber',
'wordpress' => 'Wordpress',
// 'opencart' => 'Opencart',
'prestashop' => 'Prestashop',
// 'magento' => 'Magento',
'drupal' => 'Drupal',
'joomla' => 'Joomla',
'redis' => 'Redis',
'mysql' => 'Mysql',
'postgres' => 'Postgres',
'mongo' => 'Mongo',
])->afterStateUpdated(function (Forms\Get $get, Forms\Set $set, ?string $old, ?string $state) {
return redirect('/admin/docker/templates/create?docker_template=' . $state);
//$set('docker_compose', $state);
}),
// Forms\Components\Textarea::make('docker_compose')
// ->label('Docker compose')
// ->required()
// ->columnSpanFull()
// ->placeholder('Enter the Dockerfile content'),
AceEditor::make('docker_compose')
->mode('yml')
->theme('github')
->default($dockerTemplateContent)
->columnSpanFull()
->darkTheme('dracula'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
// Tables\Columns\TextColumn::make('description'),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => ListDockerTemplates::route('/'),
'create' => CreateDockerTemplate::route('/create'),
'edit' => EditDockerTemplate::route('/{record}/edit'),
];
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource\Pages;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateDockerTemplate extends CreateRecord
{
protected static string $resource = DockerTemplateResource::class;
}

View file

@ -0,0 +1,19 @@
<?php
namespace Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource\Pages;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditDockerTemplate extends EditRecord
{
protected static string $resource = DockerTemplateResource::class;
protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource\Pages;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
use Modules\Docker\Filament\Clusters\Docker\Resources\DockerTemplateResource;
class ListDockerTemplates extends ListRecords
{
protected static string $resource = DockerTemplateResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View file

@ -8,6 +8,6 @@ class DockerCluster extends Cluster
{
protected static ?string $navigationIcon = 'docker-logo';
protected static ?string $navigationGroup = 'Server Management';
protected static ?string $navigationGroup = 'Docker';
}

View file

@ -6,7 +6,7 @@
"priority": 0,
"logoIcon": "docker-logo",
"category": "DevOps",
"adminUrl": "/admin/docker/docker-catalog",
"adminUrl": "/admin/docker/containers",
"providers": [
"Modules\\Docker\\App\\Providers\\DockerServiceProvider"
],

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 32 32">
<path fill="currentColor" d="M17 24h4v4h-4zm7 0h4v4h-4zm-7-7h4v4h-4zm7 0h4v4h-4z"></path>
<path fill="currentColor" d="M28 11h-6V7c0-1.7-1.3-3-3-3h-6c-1.7 0-3 1.3-3 3v4H4c-.6 0-1 .4-1 1v.2l1.9 12.1c.1 1 1 1.7 2 1.7H15v-2H6.9L5.2 13H28zM12 7c0-.6.4-1 1-1h6c.6 0 1 .4 1 1v4h-8z"></path>
</svg>

After

Width:  |  Height:  |  Size: 386 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512">
<path fill="currentColor" d="M512 169.844L342.694 256V85.032zM330.694 90.948l-154.031 75.938V337.83l154.03-75.916zm-166.031 75.914L0 85.032V256l164.663 81.807zm178.03 102.602v157.504L512 340.788v-157.48z"></path>
</svg>

After

Width:  |  Height:  |  Size: 312 B

View file

@ -0,0 +1,31 @@
version: '3.1'
services:
drupal:
image: drupal
restart: always
ports:
- 8080:80
environment:
DB_HOST: db
DB_USER: exampleuser
DB_PASSWORD: examplepass
DB_NAME: exampledb
volumes:
- drupal:/var/www/html
db:
image: mysql:8.0
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
drupal:
db:

View file

@ -0,0 +1,19 @@
version: '3.1'
services:
joomla:
image: joomla
restart: always
links:
- joomladb:mysql
ports:
- 8080:80
environment:
JOOMLA_DB_HOST: joomladb
JOOMLA_DB_PASSWORD: example
joomladb:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: example

View file

@ -0,0 +1,31 @@
version: '3.1'
services:
microweber:
image: microweber
restart: always
ports:
- 8080:80
environment:
DB_HOST: db
DB_USER: exampleuser
DB_PASSWORD: examplepass
DB_NAME: exampledb
volumes:
- microweber:/var/www/html
db:
image: mysql:8.0
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
microweber:
db:

View file

@ -0,0 +1,22 @@
# Use root/example as user/password credentials
version: '3.1'
services:
mongo:
image: mongo
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
mongo-express:
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: example
ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/
ME_CONFIG_BASICAUTH: false

View file

@ -0,0 +1,15 @@
services:
mysql-db:
image: mysql:8.0
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
db:

View file

@ -0,0 +1,23 @@
version: '3.9'
services:
db:
image: postgres
restart: always
# set shared memory limit when using docker-compose
shm_size: 128mb
# or set shared memory limit when deploy via swarm stack
#volumes:
# - type: tmpfs
# target: /dev/shm
# tmpfs:
# size: 134217728 # 128*2^20 bytes = 128Mb
environment:
POSTGRES_PASSWORD: example
adminer:
image: adminer
restart: always
ports:
- 8080:8080

View file

@ -0,0 +1,31 @@
services:
prestashop:
image: prestashop/prestashop:latest
restart: always
ports:
- 8080:80
environment:
DB_HOST: db
DB_USER: exampleuser
DB_PASSWORD: examplepass
DB_NAME: exampledb
ADMIN_MAIL: exampledb@email.com
ADMIN_PASSWD: examplepass
volumes:
- prestashop:/var/www/html
db:
image: mysql:8.0
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
prestashop:
db:

View file

@ -0,0 +1,6 @@
version: '3.1'
services:
redis:
image: redis
restart: always

View file

@ -0,0 +1,31 @@
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- wordpress:/var/www/html
db:
image: mysql:8.0
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
wordpress:
db:

View file

@ -1,5 +1,5 @@
<div>
<div class="bg-black/5 p-4 rounded">
<div class="bg-black/5 dark:bg-white/5 dark:text-green-500 p-4 rounded">
{!! $this->containerLog !!}
</div>
</div>

View file

@ -67,7 +67,7 @@
<x-filament::button id="docker-container-details-{{ $dockerContainer['id'] }}"
tag="a"
href="{{route('filament.admin.docker.resources.docker-containers.view', $dockerContainer['id'])}}"
href="{{url('admin/docker/containers/'. $dockerContainer['id'])}}"
size="md" outlined>
<div class="flex gap-2 items-center">
@ -79,7 +79,7 @@
</x-filament::button>
<x-filament::button id="docker-container-logs-{{ $dockerContainer['id'] }}"
tag="a"
href="{{route('filament.admin.docker.resources.docker-containers.view', $dockerContainer['id'])}}"
href="{{url('admin/docker/containers/'. $dockerContainer['id'])}}"
size="md" outlined>
<div class="flex gap-2 items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6" viewBox="0 0 15 15">
@ -91,7 +91,7 @@
<x-filament::button id="docker-container-settings-{{ $dockerContainer['id'] }}"
tag="a"
href="{{route('filament.admin.docker.resources.docker-containers.edit', $dockerContainer['id'])}}"
href="{{url('admin/docker/containers/'. $dockerContainer['id'])}}"
size="md" outlined>
<div class="flex gap-2 items-center">

View file

@ -47,6 +47,7 @@ class AdminPanelProvider extends PanelProvider
// ->brandLogo(fn () => view('filament.admin.logo'))
->navigationGroups([
'Hosting Services' => NavigationGroup::make()->label('Hosting Services'),
'Docker' => NavigationGroup::make()->label('Docker'),
'Server Management' => NavigationGroup::make()->label('Server Management'),
])
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')

View file

@ -25,6 +25,7 @@
"outerweb/filament-settings": "^1.2",
"phpseclib/phpseclib": "^3.0",
"postare/blade-mdi": "^1.1",
"riodwanto/filament-ace-editor": "^1.0",
"spatie/ssh": "^1.10",
"stechstudio/filament-impersonate": "^3.8",
"symfony/process": "^6.3",

74
web/composer.lock generated
View file

@ -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": "24c114639ffad26d47dac674a59e408e",
"content-hash": "6e65fe2d2aeaae5d8f903e679ebff837",
"packages": [
{
"name": "acmephp/core",
@ -6339,6 +6339,78 @@
],
"time": "2023-11-08T05:53:05+00:00"
},
{
"name": "riodwanto/filament-ace-editor",
"version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/riodwanto/filament-ace-editor.git",
"reference": "06894ad2ff03e6bd6f7768febdb7e9c2dd86a930"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/riodwanto/filament-ace-editor/zipball/06894ad2ff03e6bd6f7768febdb7e9c2dd86a930",
"reference": "06894ad2ff03e6bd6f7768febdb7e9c2dd86a930",
"shasum": ""
},
"require": {
"illuminate/contracts": "^10.0",
"php": "^8.1",
"spatie/laravel-package-tools": "^1.15.0"
},
"require-dev": {
"filament/filament": "^3.0",
"nunomaduro/collision": "^7.9",
"orchestra/testbench": "^8.0",
"pestphp/pest": "^2.0",
"pestphp/pest-plugin-arch": "^2.0",
"pestphp/pest-plugin-laravel": "^2.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Riodwanto\\FilamentAceEditor\\FilamentAceEditorServiceProvider"
],
"aliases": {
"FilamentAceEditor": "Riodwanto\\FilamentAceEditor\\Facades\\FilamentAceEditor"
}
}
},
"autoload": {
"psr-4": {
"Riodwanto\\FilamentAceEditor\\": "src/",
"Riodwanto\\FilamentAceEditor\\Database\\Factories\\": "database/factories/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rio Dewanto P",
"email": "rdp.tech@gmail.com",
"role": "Developer"
}
],
"description": "Ace Editor implementation for Filament 3 Form",
"homepage": "https://github.com/riodwanto/filament-ace-editor",
"keywords": [
"code-editor",
"filament",
"filament-ace-editor",
"filament-field",
"filament-form-field",
"laravel",
"riodwanto"
],
"support": {
"issues": "https://github.com/riodwanto/filament-ace-editor/issues",
"source": "https://github.com/riodwanto/filament-ace-editor"
},
"time": "2024-03-03T11:54:56+00:00"
},
{
"name": "ryangjchandler/blade-capture-directive",
"version": "v1.0.0",

View file

@ -2,5 +2,7 @@
"LetsEncrypt": true,
"Microweber": true,
"Docker": true,
"Customer": true
"Customer": true,
"Model": true,
"DockerTemplate": true
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
function m({state:r,statePath:o,placeholder:s,aceUrl:a,extensions:n,config:h={},options:c={},darkTheme:l,disableDarkTheme:d}){return{state:r,statePath:o,placeholder:s,options:c,darkTheme:l,disableDarkTheme:d,editor:null,observer:null,async init(){if(!await this.importAceEditor(a)){console.error("Failed to load the ACE editor core.");return}await this.importExtensions(n)||console.error("Failed to load ACE editor extensions."),this.configureAce(h),this.initializeEditor(),this.applyInitialTheme(),this.observeDarkModeChanges()},async importAceEditor(t){try{return await import(t),!0}catch(e){return console.error("Error importing the ACE editor core:",e),!1}},async importExtensions(t){try{let e=Object.values(t).map(i=>import(i));return await Promise.all(e),!0}catch(e){return console.error("Error importing ACE editor extensions:",e),!1}},configureAce(t){Object.entries(t).forEach(([e,i])=>ace.config.set(e,i))},initializeEditor(){this.editor=ace.edit(this.$refs.aceCodeEditor),this.editor.setOptions(this.options),this.editor.setValue(this.state?this.state:this.placeholder),this.editor.session.on("change",()=>{this.state=this.editor.getValue()})},applyInitialTheme(){this.disableDarkTheme?this.editor.setTheme(this.options.theme):this.setTheme()},observeDarkModeChanges(){if(this.disableDarkTheme)return;let t=document.querySelector("html");this.observer=new MutationObserver(()=>this.setTheme()),this.observer.observe(t,{attributes:!0,attributeFilter:["class"]})},setTheme(){let e=document.querySelector("html").classList.contains("dark")?this.darkTheme:this.options.theme;this.editor&&this.editor.setTheme(e)}}}export{m as default};