@@ -1,101 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace App\Livewire;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Livewire\Attributes\On;
 | 
					 | 
				
			||||||
use Livewire\Component;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class RunCommand extends Component
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public $selected_uuid = 'default';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $servers = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $containers = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function mount($servers)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->servers = $servers;
 | 
					 | 
				
			||||||
        $this->containers = $this->getAllActiveContainers();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private function getAllActiveContainers()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return collect($this->servers)->flatMap(function ($server) {
 | 
					 | 
				
			||||||
            if (! $server->isFunctional()) {
 | 
					 | 
				
			||||||
                return [];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return $server->definedResources()
 | 
					 | 
				
			||||||
                ->filter(function ($resource) {
 | 
					 | 
				
			||||||
                    $status = method_exists($resource, 'realStatus') ? $resource->realStatus() : (method_exists($resource, 'status') ? $resource->status() : 'exited');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return str_starts_with($status, 'running:');
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                ->map(function ($resource) use ($server) {
 | 
					 | 
				
			||||||
                    if (isDev()) {
 | 
					 | 
				
			||||||
                        if (data_get($resource, 'name') === 'coolify-db') {
 | 
					 | 
				
			||||||
                            $container_name = 'coolify-db';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            return [
 | 
					 | 
				
			||||||
                                'name' => $resource->name,
 | 
					 | 
				
			||||||
                                'connection_name' => $container_name,
 | 
					 | 
				
			||||||
                                'uuid' => $resource->uuid,
 | 
					 | 
				
			||||||
                                'status' => 'running',
 | 
					 | 
				
			||||||
                                'server' => $server,
 | 
					 | 
				
			||||||
                                'server_uuid' => $server->uuid,
 | 
					 | 
				
			||||||
                            ];
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (class_basename($resource) === 'Application') {
 | 
					 | 
				
			||||||
                        if (! $server->isSwarm()) {
 | 
					 | 
				
			||||||
                            $current_containers = getCurrentApplicationContainerStatus($server, $resource->id, includePullrequests: true);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        $status = $resource->status;
 | 
					 | 
				
			||||||
                    } elseif (class_basename($resource) === 'Service') {
 | 
					 | 
				
			||||||
                        $current_containers = getCurrentServiceContainerStatus($server, $resource->id);
 | 
					 | 
				
			||||||
                        $status = $resource->status();
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        $status = getContainerStatus($server, $resource->uuid);
 | 
					 | 
				
			||||||
                        if ($status === 'running') {
 | 
					 | 
				
			||||||
                            $current_containers = collect([
 | 
					 | 
				
			||||||
                                'Names' => $resource->name,
 | 
					 | 
				
			||||||
                            ]);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    if ($server->isSwarm()) {
 | 
					 | 
				
			||||||
                        $container_name = $resource->uuid.'_'.$resource->uuid;
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        $container_name = data_get($current_containers->first(), 'Names');
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return [
 | 
					 | 
				
			||||||
                        'name' => $resource->name,
 | 
					 | 
				
			||||||
                        'connection_name' => $container_name,
 | 
					 | 
				
			||||||
                        'uuid' => $resource->uuid,
 | 
					 | 
				
			||||||
                        'status' => $status,
 | 
					 | 
				
			||||||
                        'server' => $server,
 | 
					 | 
				
			||||||
                        'server_uuid' => $server->uuid,
 | 
					 | 
				
			||||||
                    ];
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function updatedSelectedUuid($value)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->connectToContainer();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[On('connectToContainer')]
 | 
					 | 
				
			||||||
    public function connectToContainer()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $container = collect($this->containers)->firstWhere('uuid', $this->selected_uuid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->dispatch('send-terminal-command',
 | 
					 | 
				
			||||||
            isset($container),
 | 
					 | 
				
			||||||
            $container['connection_name'] ?? $this->selected_uuid,
 | 
					 | 
				
			||||||
            $container['server_uuid'] ?? $this->selected_uuid
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -3,15 +3,70 @@
 | 
				
			|||||||
namespace App\Livewire\Terminal;
 | 
					namespace App\Livewire\Terminal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Models\Server;
 | 
					use App\Models\Server;
 | 
				
			||||||
 | 
					use Livewire\Attributes\On;
 | 
				
			||||||
use Livewire\Component;
 | 
					use Livewire\Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Index extends Component
 | 
					class Index extends Component
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    public $selected_uuid = 'default';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $servers = [];
 | 
					    public $servers = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $containers = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function mount()
 | 
					    public function mount()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (! auth()->user()->isAdmin()) {
 | 
				
			||||||
 | 
					            abort(403);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        $this->servers = Server::isReachable()->get();
 | 
					        $this->servers = Server::isReachable()->get();
 | 
				
			||||||
 | 
					        $this->containers = $this->getAllActiveContainers();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function getAllActiveContainers()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return collect($this->servers)->flatMap(function ($server) {
 | 
				
			||||||
 | 
					            if (! $server->isFunctional()) {
 | 
				
			||||||
 | 
					                return [];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $server->loadAllContainers()->map(function ($container) use ($server) {
 | 
				
			||||||
 | 
					                $state = data_get_str($container, 'State')->lower();
 | 
				
			||||||
 | 
					                if ($state->contains('running')) {
 | 
				
			||||||
 | 
					                    return [
 | 
				
			||||||
 | 
					                        'name' => data_get($container, 'Names'),
 | 
				
			||||||
 | 
					                        'connection_name' => data_get($container, 'Names'),
 | 
				
			||||||
 | 
					                        'uuid' => data_get($container, 'Names'),
 | 
				
			||||||
 | 
					                        'status' => data_get_str($container, 'State')->lower(),
 | 
				
			||||||
 | 
					                        'server' => $server,
 | 
				
			||||||
 | 
					                        'server_uuid' => $server->uuid,
 | 
				
			||||||
 | 
					                    ];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            })->filter();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function updatedSelectedUuid()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->connectToContainer();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[On('connectToContainer')]
 | 
				
			||||||
 | 
					    public function connectToContainer()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->selected_uuid === 'default') {
 | 
				
			||||||
 | 
					            $this->dispatch('error', 'Please select a server or a container.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $container = collect($this->containers)->firstWhere('uuid', $this->selected_uuid);
 | 
				
			||||||
 | 
					        $this->dispatch('send-terminal-command',
 | 
				
			||||||
 | 
					            isset($container),
 | 
				
			||||||
 | 
					            $container['connection_name'] ?? $this->selected_uuid,
 | 
				
			||||||
 | 
					            $container['server_uuid'] ?? $this->selected_uuid
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function render()
 | 
					    public function render()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -775,6 +775,18 @@ $schema://$host {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function loadAllContainers(): Collection
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->isFunctional()) {
 | 
				
			||||||
 | 
					            $containers = instant_remote_process(["docker ps -a --format '{{json .}}'"], $this);
 | 
				
			||||||
 | 
					            $containers = format_docker_command_output_to_json($containers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return collect($containers);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return collect([]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function loadUnmanagedContainers(): Collection
 | 
					    public function loadUnmanagedContainers(): Collection
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->isFunctional()) {
 | 
					        if ($this->isFunctional()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ return [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // The release version of your application
 | 
					    // The release version of your application
 | 
				
			||||||
    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
					    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
				
			||||||
    'release' => '4.0.0-beta.337',
 | 
					    'release' => '4.0.0-beta.338',
 | 
				
			||||||
    // When left empty or `null` the Laravel environment will be used
 | 
					    // When left empty or `null` the Laravel environment will be used
 | 
				
			||||||
    'environment' => config('app.env'),
 | 
					    'environment' => config('app.env'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,3 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return '4.0.0-beta.337';
 | 
					return '4.0.0-beta.338';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,7 +110,7 @@ services:
 | 
				
			|||||||
      retries: 10
 | 
					      retries: 10
 | 
				
			||||||
      timeout: 2s
 | 
					      timeout: 2s
 | 
				
			||||||
  soketi:
 | 
					  soketi:
 | 
				
			||||||
    image: 'ghcr.io/coollabsio/coolify-realtime:1.0.0'
 | 
					    image: 'ghcr.io/coollabsio/coolify-realtime:1.0.1'
 | 
				
			||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      - "${SOKETI_PORT:-6001}:6001"
 | 
					      - "${SOKETI_PORT:-6001}:6001"
 | 
				
			||||||
      - "6002:6002"
 | 
					      - "6002:6002"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -123,7 +123,6 @@ async function handleCommand(ws, command, userId) {
 | 
				
			|||||||
        cols: 80,
 | 
					        cols: 80,
 | 
				
			||||||
        rows: 30,
 | 
					        rows: 30,
 | 
				
			||||||
        cwd: process.env.HOME,
 | 
					        cwd: process.env.HOME,
 | 
				
			||||||
        env: process.env
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // NOTE: - Initiates a process within the Terminal container
 | 
					    // NOTE: - Initiates a process within the Terminal container
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,7 +110,7 @@ services:
 | 
				
			|||||||
      retries: 10
 | 
					      retries: 10
 | 
				
			||||||
      timeout: 2s
 | 
					      timeout: 2s
 | 
				
			||||||
  soketi:
 | 
					  soketi:
 | 
				
			||||||
    image: 'ghcr.io/coollabsio/coolify-realtime:1.0.0'
 | 
					    image: 'ghcr.io/coollabsio/coolify-realtime:1.0.1'
 | 
				
			||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      - "${SOKETI_PORT:-6001}:6001"
 | 
					      - "${SOKETI_PORT:-6001}:6001"
 | 
				
			||||||
      - "6002:6002"
 | 
					      - "6002:6002"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,16 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "coolify": {
 | 
					    "coolify": {
 | 
				
			||||||
        "v4": {
 | 
					        "v4": {
 | 
				
			||||||
            "version": "4.0.0-beta.337"
 | 
					            "version": "4.0.0-beta.338"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "nightly": {
 | 
					        "nightly": {
 | 
				
			||||||
            "version": "4.0.0-beta.338"
 | 
					            "version": "4.0.0-beta.339"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "helper": {
 | 
					        "helper": {
 | 
				
			||||||
            "version": "1.0.1"
 | 
					            "version": "1.0.1"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "realtime": {
 | 
					        "realtime": {
 | 
				
			||||||
            "version": "1.0.0"
 | 
					            "version": "1.0.1"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -67,6 +67,12 @@
 | 
				
			|||||||
                    socket.onerror = (e) => {
 | 
					                    socket.onerror = (e) => {
 | 
				
			||||||
                        console.error('WebSocket error:', e);
 | 
					                        console.error('WebSocket error:', e);
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					                    socket.onclose = () => {
 | 
				
			||||||
 | 
					                        console.log('WebSocket connection closed');
 | 
				
			||||||
 | 
					                        setInterval(() => {
 | 
				
			||||||
 | 
					                            $wire.dispatch('error', 'Connection to terminal lost, please refresh the page.');
 | 
				
			||||||
 | 
					                        }, 2000);
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -209,8 +215,8 @@
 | 
				
			|||||||
                    term.resize(termWidth, termHeight);
 | 
					                    term.resize(termWidth, termHeight);
 | 
				
			||||||
                    socket.send(JSON.stringify({
 | 
					                    socket.send(JSON.stringify({
 | 
				
			||||||
                        resize: {
 | 
					                        resize: {
 | 
				
			||||||
                            cols: termWidth,
 | 
					                            cols: 600,
 | 
				
			||||||
                            rows: termHeight
 | 
					                            rows: 600
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }));
 | 
					                    }));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
<div>
 | 
					 | 
				
			||||||
    <form class="flex flex-col gap-2 justify-center xl:items-end xl:flex-row"
 | 
					 | 
				
			||||||
        wire:submit="$dispatchSelf('connectToContainer')">
 | 
					 | 
				
			||||||
        <x-forms.select id="server" required wire:model.live="selected_uuid">
 | 
					 | 
				
			||||||
            @foreach ($servers as $server)
 | 
					 | 
				
			||||||
                @if ($loop->first)
 | 
					 | 
				
			||||||
                    <option disabled value="default">Select a server or container</option>
 | 
					 | 
				
			||||||
                @endif
 | 
					 | 
				
			||||||
                <option value="{{ $server->uuid }}">{{ $server->name }}</option>
 | 
					 | 
				
			||||||
                @foreach ($containers as $container)
 | 
					 | 
				
			||||||
                    @if ($container['server_uuid'] == $server->uuid)
 | 
					 | 
				
			||||||
                        <option value="{{ $container['uuid'] }}">
 | 
					 | 
				
			||||||
                            {{ $server->name }} -> {{ $container['name'] }}
 | 
					 | 
				
			||||||
                        </option>
 | 
					 | 
				
			||||||
                    @endif
 | 
					 | 
				
			||||||
                @endforeach
 | 
					 | 
				
			||||||
            @endforeach
 | 
					 | 
				
			||||||
        </x-forms.select>
 | 
					 | 
				
			||||||
        <x-forms.button type="submit">Connect</x-forms.button>
 | 
					 | 
				
			||||||
    </form>
 | 
					 | 
				
			||||||
    <livewire:project.shared.terminal />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -8,11 +8,27 @@
 | 
				
			|||||||
        <x-helper
 | 
					        <x-helper
 | 
				
			||||||
            helper="If you're having trouble connecting to your server, make sure that the port is open.<br><br><a class='underline' href='https://coolify.io/docs/knowledge-base/server/firewall/#terminal' target='_blank'>Documentation</a>"></x-helper>
 | 
					            helper="If you're having trouble connecting to your server, make sure that the port is open.<br><br><a class='underline' href='https://coolify.io/docs/knowledge-base/server/firewall/#terminal' target='_blank'>Documentation</a>"></x-helper>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    @if ($servers->count() > 0)
 | 
					 | 
				
			||||||
        <livewire:run-command :servers="$servers" />
 | 
					 | 
				
			||||||
    @else
 | 
					 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
            <div>No servers found. Without a server, you won't be able to do much.</div>
 | 
					        <form class="flex flex-col gap-2 justify-center xl:items-end xl:flex-row"
 | 
				
			||||||
        </div>
 | 
					            wire:submit="$dispatchSelf('connectToContainer')">
 | 
				
			||||||
 | 
					            <x-forms.select id="server" required wire:model.live="selected_uuid">
 | 
				
			||||||
 | 
					                @foreach ($servers as $server)
 | 
				
			||||||
 | 
					                    @if ($loop->first)
 | 
				
			||||||
 | 
					                        <option disabled value="default">Select a server or container</option>
 | 
				
			||||||
                    @endif
 | 
					                    @endif
 | 
				
			||||||
 | 
					                    <option value="{{ $server->uuid }}">{{ $server->name }}</option>
 | 
				
			||||||
 | 
					                    @foreach ($containers as $container)
 | 
				
			||||||
 | 
					                        @if ($container['server_uuid'] == $server->uuid)
 | 
				
			||||||
 | 
					                            <option value="{{ $container['uuid'] }}">
 | 
				
			||||||
 | 
					                                {{ $server->name }} -> {{ $container['name'] }}
 | 
				
			||||||
 | 
					                            </option>
 | 
				
			||||||
 | 
					                        @endif
 | 
				
			||||||
 | 
					                    @endforeach
 | 
				
			||||||
 | 
					                @endforeach
 | 
				
			||||||
 | 
					            </x-forms.select>
 | 
				
			||||||
 | 
					            <x-forms.button type="submit">Connect</x-forms.button>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					        <livewire:project.shared.terminal />
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,16 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "coolify": {
 | 
					    "coolify": {
 | 
				
			||||||
        "v4": {
 | 
					        "v4": {
 | 
				
			||||||
            "version": "4.0.0-beta.337"
 | 
					            "version": "4.0.0-beta.338"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "nightly": {
 | 
					        "nightly": {
 | 
				
			||||||
            "version": "4.0.0-beta.338"
 | 
					            "version": "4.0.0-beta.339"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "helper": {
 | 
					        "helper": {
 | 
				
			||||||
            "version": "1.0.1"
 | 
					            "version": "1.0.1"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "realtime": {
 | 
					        "realtime": {
 | 
				
			||||||
            "version": "1.0.0"
 | 
					            "version": "1.0.1"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user