diff --git a/plogical/DockerSites.py b/plogical/DockerSites.py index 37038bc54..f54888442 100644 --- a/plogical/DockerSites.py +++ b/plogical/DockerSites.py @@ -672,32 +672,25 @@ services: FilerValue = self.DockerAppName - # First try to find the containers by name pattern - containers = [] - - # List all containers - all_containers = client.containers.list(all=True) - - # Filter containers that match our app name pattern (both exact and related containers like DB) - for container in all_containers: - if FilerValue in container.name: - containers.append(container) - + # Define the label to filter containers + label_filter = {'name': FilerValue} + + + # List containers matching the label filter + containers = client.containers.list(filters=label_filter) + json_data = "[" checker = 0 for container in containers: - # Get environment variables - environment = container.attrs.get('Config', {}).get('Env', []) - + dic = { 'id': container.short_id, 'name': container.name, 'status': container.status, - 'volumes': container.attrs['HostConfig']['Binds'] if 'HostConfig' in container.attrs and 'Binds' in container.attrs['HostConfig'] else [], + 'volumes': container.attrs['HostConfig']['Binds'] if 'HostConfig' in container.attrs else [], 'logs_50': container.logs(tail=50).decode('utf-8'), - 'ports': container.attrs['HostConfig']['PortBindings'] if 'HostConfig' in container.attrs and 'PortBindings' in container.attrs['HostConfig'] else {}, - 'environment': environment + 'ports': container.attrs['HostConfig']['PortBindings'] if 'HostConfig' in container.attrs else {} } if checker == 0: diff --git a/websiteFunctions/dockerviews.py b/websiteFunctions/dockerviews.py index 61f614086..2d4c6136c 100644 --- a/websiteFunctions/dockerviews.py +++ b/websiteFunctions/dockerviews.py @@ -8,8 +8,6 @@ from django.shortcuts import redirect from loginSystem.views import loadLoginPage from django.views.decorators.csrf import csrf_exempt from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging -import datetime -import requests def require_login(view_func): def wrapper(request, *args, **kwargs): @@ -166,243 +164,6 @@ def restartContainer(request): return HttpResponse('Not allowed') except Exception as e: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': str(e) - })) - -@csrf_exempt -@require_login -def n8n_container_operation(request): - try: - if request.method == 'POST': - userID = request.session['userID'] - currentACL = ACLManager.loadedACL(userID) - admin = Administrator.objects.get(pk=userID) - - data = json.loads(request.body) - container_id = data.get('container_id') - operation = data.get('operation') - - # Get the container - docker_manager = DockerManager() - container = docker_manager.get_container(container_id) - - if not container: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Container not found' - })) - - # Determine the port where n8n is running - container_info = container.attrs - port_bindings = container_info.get('HostConfig', {}).get('PortBindings', {}) - n8n_port = None - - for container_port, host_ports in port_bindings.items(): - if container_port.startswith('5678'): - n8n_port = host_ports[0]['HostPort'] - break - - if not n8n_port: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Could not determine n8n port' - })) - - # Set up n8n base URL - host_ip = request.get_host().split(':')[0] - - # Try different authentication methods - # Method 1: Try direct access to REST API (in some setups, this works without auth) - direct_api_url = f"http://{host_ip}:{n8n_port}/rest" - - # Method 2: Try API v1 with various auth methods - api_v1_url = f"http://{host_ip}:{n8n_port}/api/v1" - - # Extract authentication info from environment variables - environment_vars = container_info.get('Config', {}).get('Env', []) - - # Initialize default headers - headers = { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - } - - # Variables for auth info - n8n_basic_auth_user = None - n8n_basic_auth_password = None - n8n_api_key = None - n8n_jwt_auth = None - - # Extract auth information from environment variables - for env_var in environment_vars: - if env_var.startswith('N8N_API_KEY='): - n8n_api_key = env_var.split('=', 1)[1] - elif env_var.startswith('N8N_BASIC_AUTH_USER='): - n8n_basic_auth_user = env_var.split('=', 1)[1] - elif env_var.startswith('N8N_BASIC_AUTH_PASSWORD='): - n8n_basic_auth_password = env_var.split('=', 1)[1] - elif env_var.startswith('N8N_JWT_AUTH_ACTIVE=') and 'true' in env_var.lower(): - n8n_jwt_auth = True - elif env_var.startswith('N8N_AUTH_ACTIVE=') and 'true' not in env_var.lower(): - # If auth is explicitly disabled, we can use direct access - pass - - # Log the authentication methods available - logging.writeToFile(f"N8N auth methods - API Key: {n8n_api_key is not None}, Basic Auth: {n8n_basic_auth_user is not None}, JWT: {n8n_jwt_auth is not None}") - - # Handle different operations - if operation == 'create_backup': - try: - # Get backup options from request - backup_options = data.get('options', {}) - include_credentials = backup_options.get('includeCredentials', True) - include_executions = backup_options.get('includeExecutions', False) - - # Initialize the backup data dictionary - backup_data = {} - - # Try to fetch workflows using different authentication methods - workflows_response = None - auth = None - - # Try direct access first - try: - logging.writeToFile(f"Trying direct access to n8n REST API") - workflows_response = requests.get(f"{direct_api_url}/workflows", headers=headers, timeout=5) - if workflows_response.status_code == 200: - logging.writeToFile(f"Direct REST API access successful") - api_url = direct_api_url - except Exception as e: - logging.writeToFile(f"Direct REST API access failed: {str(e)}") - - # If direct access failed, try with API key - if not workflows_response or workflows_response.status_code != 200: - if n8n_api_key: - try: - logging.writeToFile(f"Trying API key authentication") - api_headers = headers.copy() - api_headers['X-N8N-API-KEY'] = n8n_api_key - workflows_response = requests.get(f"{api_v1_url}/workflows", headers=api_headers, timeout=5) - if workflows_response.status_code == 200: - logging.writeToFile(f"API key authentication successful") - api_url = api_v1_url - headers = api_headers - except Exception as e: - logging.writeToFile(f"API key authentication failed: {str(e)}") - - # If API key failed, try basic auth - if not workflows_response or workflows_response.status_code != 200: - if n8n_basic_auth_user and n8n_basic_auth_password: - try: - logging.writeToFile(f"Trying basic authentication") - auth = (n8n_basic_auth_user, n8n_basic_auth_password) - workflows_response = requests.get(f"{api_v1_url}/workflows", headers=headers, auth=auth, timeout=5) - if workflows_response.status_code == 200: - logging.writeToFile(f"Basic authentication successful") - api_url = api_v1_url - except Exception as e: - logging.writeToFile(f"Basic authentication failed: {str(e)}") - - # If all authentication methods failed - if not workflows_response or workflows_response.status_code != 200: - # Last resort: try without any authentication at the Admin UI port - try: - logging.writeToFile(f"Trying Admin UI direct access") - admin_url = f"http://{host_ip}:{n8n_port}" - workflows_response = requests.get(f"{admin_url}/rest/workflows", headers=headers, timeout=5) - if workflows_response.status_code == 200: - logging.writeToFile(f"Admin UI direct access successful") - api_url = f"{admin_url}/rest" - except Exception as e: - logging.writeToFile(f"Admin UI direct access failed: {str(e)}") - - # Check if any method succeeded - if not workflows_response or workflows_response.status_code != 200: - error_message = "Failed to authenticate with n8n API. Please check the container logs for more information." - if workflows_response: - error_message = f"Authentication failed: {workflows_response.text}" - logging.writeToFile(f"All authentication methods failed: {error_message}") - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': error_message - })) - - # If we made it here, one of the authentication methods worked - backup_data['workflows'] = workflows_response.json() - - # Get credentials if requested - if include_credentials: - try: - if auth: - credentials_response = requests.get(f"{api_url}/credentials", headers=headers, auth=auth, timeout=5) - else: - credentials_response = requests.get(f"{api_url}/credentials", headers=headers, timeout=5) - - if credentials_response.status_code == 200: - backup_data['credentials'] = credentials_response.json() - else: - logging.writeToFile(f"Failed to fetch n8n credentials: {credentials_response.status_code} - {credentials_response.text}") - except Exception as e: - logging.writeToFile(f"Error fetching credentials: {str(e)}") - - # Get execution data if requested - if include_executions: - try: - if auth: - executions_response = requests.get(f"{api_url}/executions", headers=headers, auth=auth, timeout=5) - else: - executions_response = requests.get(f"{api_url}/executions", headers=headers, timeout=5) - - if executions_response.status_code == 200: - backup_data['executions'] = executions_response.json() - else: - logging.writeToFile(f"Failed to fetch n8n executions: {executions_response.status_code} - {executions_response.text}") - except Exception as e: - logging.writeToFile(f"Error fetching executions: {str(e)}") - - # Include metadata - backup_data['metadata'] = { - 'timestamp': datetime.datetime.now().isoformat(), - 'container_id': container_id, - 'container_name': container.name, - 'include_credentials': include_credentials, - 'include_executions': include_executions - } - - # Create a response with the backup data - return HttpResponse(json.dumps({ - 'status': 1, - 'message': 'Backup created successfully', - 'backup': backup_data, - 'filename': f'n8n-backup-{container.name}-{datetime.datetime.now().strftime("%Y%m%d-%H%M%S")}.json' - })) - - except Exception as e: - logging.writeToFile(f"Error creating n8n backup: {str(e)}") - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': f'Error creating backup: {str(e)}' - })) - - elif operation == 'restore_backup': - # Similar approach for restore operation... - # Will implement the same authentication handling for restore operation - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Restore operation temporarily unavailable while we update authentication methods' - })) - - else: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': f'Unknown operation: {operation}' - })) - - return HttpResponse('Not allowed') - except Exception as e: - logging.writeToFile(f"Error in n8n_container_operation: {str(e)}") return HttpResponse(json.dumps({ 'status': 0, 'error_message': str(e) diff --git a/websiteFunctions/n8n_api.py b/websiteFunctions/n8n_api.py deleted file mode 100644 index dd6c6e6a3..000000000 --- a/websiteFunctions/n8n_api.py +++ /dev/null @@ -1,259 +0,0 @@ -import json -import logging -import requests -import docker -from django.http import HttpResponse -from django.views.decorators.csrf import csrf_exempt -from .models import DockerSites -from loginSystem.models import Administrator -from plogical.acl import ACLManager -from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging - -class N8nAPI: - def __init__(self, container, host, port): - self.container = container - self.base_url = f"http://{host}:{port}" - self.client = requests.Session() - - def get_workflows(self): - try: - response = self.client.get(f"{self.base_url}/rest/workflows") - if response.status_code == 200: - return response.json() - return None - except Exception as e: - logging.writeToFile(f"Error fetching workflows: {str(e)}") - return None - - def get_workflow_executions(self, workflow_id): - try: - response = self.client.get(f"{self.base_url}/rest/executions", - params={"workflowId": workflow_id}) - if response.status_code == 200: - return response.json() - return None - except Exception as e: - logging.writeToFile(f"Error fetching workflow executions: {str(e)}") - return None - - def toggle_workflow_active(self, workflow_id, active): - try: - response = self.client.patch(f"{self.base_url}/rest/workflows/{workflow_id}/activate", - json={"active": active}) - if response.status_code in [200, 201]: - return True - return False - except Exception as e: - logging.writeToFile(f"Error toggling workflow status: {str(e)}") - return False - - def get_credentials(self): - try: - response = self.client.get(f"{self.base_url}/rest/credentials") - if response.status_code == 200: - return response.json() - return None - except Exception as e: - logging.writeToFile(f"Error fetching credentials: {str(e)}") - return None - - def create_backup(self, include_credentials=True, include_executions=False): - try: - response = self.client.post(f"{self.base_url}/rest/export", - json={ - "includeCredentials": include_credentials, - "includeExecutions": include_executions - }) - if response.status_code == 200: - return response.json() - return None - except Exception as e: - logging.writeToFile(f"Error creating backup: {str(e)}") - return None - - def restore_backup(self, backup_data): - try: - response = self.client.post(f"{self.base_url}/rest/import", - json=backup_data) - if response.status_code in [200, 201]: - return True - return False - except Exception as e: - logging.writeToFile(f"Error restoring backup: {str(e)}") - return False - - -@csrf_exempt -def get_n8n_workflows(request): - try: - if request.method == 'POST': - userID = request.session['userID'] - currentACL = ACLManager.loadedACL(userID) - admin = Administrator.objects.get(pk=userID) - - data = json.loads(request.body) - container_id = data.get('container_id') - - # Get container info - client = docker.from_env() - container = client.containers.get(container_id) - - # Extract container metadata - container_info = container.attrs - n8n_port = None - - # Find the n8n port - ports = container_info.get('NetworkSettings', {}).get('Ports', {}) - if '5678/tcp' in ports and ports['5678/tcp']: - n8n_port = ports['5678/tcp'][0].get('HostPort') - - if not n8n_port: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Could not find n8n port mapping' - })) - - # Create N8nAPI instance - n8n_api = N8nAPI(container, 'localhost', n8n_port) - - # Get workflows - workflows = n8n_api.get_workflows() - - if workflows: - return HttpResponse(json.dumps({ - 'status': 1, - 'workflows': workflows - })) - else: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Failed to fetch workflows' - })) - - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Invalid request method' - })) - except Exception as e: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': str(e) - })) - -@csrf_exempt -def toggle_workflow(request): - try: - if request.method == 'POST': - userID = request.session['userID'] - currentACL = ACLManager.loadedACL(userID) - admin = Administrator.objects.get(pk=userID) - - data = json.loads(request.body) - container_id = data.get('container_id') - workflow_id = data.get('workflow_id') - active = data.get('active', False) - - # Get container info - client = docker.from_env() - container = client.containers.get(container_id) - - # Extract container metadata - container_info = container.attrs - n8n_port = None - - # Find the n8n port - ports = container_info.get('NetworkSettings', {}).get('Ports', {}) - if '5678/tcp' in ports and ports['5678/tcp']: - n8n_port = ports['5678/tcp'][0].get('HostPort') - - if not n8n_port: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Could not find n8n port mapping' - })) - - # Create N8nAPI instance - n8n_api = N8nAPI(container, 'localhost', n8n_port) - - # Toggle workflow status - success = n8n_api.toggle_workflow_active(workflow_id, active) - - if success: - return HttpResponse(json.dumps({ - 'status': 1, - 'message': f"Workflow {'activated' if active else 'deactivated'} successfully" - })) - else: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Failed to update workflow status' - })) - - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Invalid request method' - })) - except Exception as e: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': str(e) - })) - -@csrf_exempt -def create_n8n_backup(request): - try: - if request.method == 'POST': - userID = request.session['userID'] - currentACL = ACLManager.loadedACL(userID) - admin = Administrator.objects.get(pk=userID) - - data = json.loads(request.body) - container_id = data.get('container_id') - include_credentials = data.get('include_credentials', True) - include_executions = data.get('include_executions', False) - - # Get container info - client = docker.from_env() - container = client.containers.get(container_id) - - # Extract container metadata - container_info = container.attrs - n8n_port = None - - # Find the n8n port - ports = container_info.get('NetworkSettings', {}).get('Ports', {}) - if '5678/tcp' in ports and ports['5678/tcp']: - n8n_port = ports['5678/tcp'][0].get('HostPort') - - if not n8n_port: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Could not find n8n port mapping' - })) - - # Create N8nAPI instance - n8n_api = N8nAPI(container, 'localhost', n8n_port) - - # Create backup - backup = n8n_api.create_backup(include_credentials, include_executions) - - if backup: - return HttpResponse(json.dumps({ - 'status': 1, - 'backup': backup - })) - else: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Failed to create backup' - })) - - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': 'Invalid request method' - })) - except Exception as e: - return HttpResponse(json.dumps({ - 'status': 0, - 'error_message': str(e) - })) \ No newline at end of file diff --git a/websiteFunctions/static/websiteFunctions/DockerContainers.js b/websiteFunctions/static/websiteFunctions/DockerContainers.js index a623cb720..4614497eb 100644 --- a/websiteFunctions/static/websiteFunctions/DockerContainers.js +++ b/websiteFunctions/static/websiteFunctions/DockerContainers.js @@ -13,12 +13,6 @@ app.controller('ListDockersitecontainer', function ($scope, $http) { return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } - // Helper function to truncate container IDs - $scope.truncateId = function(id) { - if (!id) return ''; - return id.substring(0, 12); - }; - $scope.getcontainer = function () { $('#cyberpanelLoading').show(); url = "/docker/getDockersiteList"; @@ -206,229 +200,8 @@ app.controller('ListDockersitecontainer', function ($scope, $http) { // Initialize $scope.getcontainer(); - // Version Management Functions for n8n - - // Check for updates - $scope.checkForUpdates = function(container) { - $scope.cyberpanelLoading = false; - $('#cyberpanelLoading').show(); - - // Initialize version management if it doesn't exist - if (!container.n8nVersion) { - // Set a default version - container.n8nVersion = '0.214.3'; - container.versionHistory = [ - { - version: '0.214.3', - date: new Date('2023-06-15') - } - ]; - } - - // Simulate checking for updates - setTimeout(function() { - $scope.$apply(function() { - $scope.cyberpanelLoading = true; - $('#cyberpanelLoading').hide(); - - // Set the latest version (in a real implementation, this would come from an API) - container.latestVersion = '0.215.0'; - - // Check if an update is available - container.updateAvailable = (container.latestVersion !== container.n8nVersion); - - new PNotify({ - title: 'Success!', - text: container.updateAvailable ? - 'Update available: ' + container.latestVersion : - 'Your n8n is up to date.', - type: 'success' - }); - }); - }, 1500); - }; - - // Update n8n - $scope.updateN8N = function(container) { - $scope.cyberpanelLoading = false; - $('#cyberpanelLoading').show(); - - // Simulate updating n8n - setTimeout(function() { - $scope.$apply(function() { - $scope.cyberpanelLoading = true; - $('#cyberpanelLoading').hide(); - - // Update the version history - if (!container.versionHistory) { - container.versionHistory = []; - } - - container.versionHistory.unshift({ - version: container.latestVersion, - date: new Date() - }); - - // Update the current version - container.n8nVersion = container.latestVersion; - - // Reset update available flag - container.updateAvailable = false; - - new PNotify({ - title: 'Success!', - text: 'n8n updated to version ' + container.n8nVersion, - type: 'success' - }); - }); - }, 3000); - }; - - // Show release notes - $scope.showReleaseNotes = function(container) { - // Simulate opening release notes - in a real implementation, you would fetch these from n8n's GitHub or website - window.open('https://github.com/n8n-io/n8n/releases/tag/n8n@' + container.latestVersion, '_blank'); - }; - - // Show version change details - $scope.showVersionChanges = function(container, version) { - // Simulate opening version details - in a real implementation, you would fetch these from n8n's GitHub or website - window.open('https://github.com/n8n-io/n8n/releases/tag/n8n@' + version.version, '_blank'); - }; - - // Function to display top processes for a container - $scope.showTop = function(containerId) { - $scope.cyberpanelLoading = false; - $('#cyberpanelLoading').show(); - - var url = "/docker/containerTop"; - - var data = { - 'name': $('#sitename').html(), - 'id': containerId - }; - - var config = { - headers: { - 'X-CSRFToken': getCookie('csrftoken') - } - }; - - $http.post(url, data, config).then(function(response) { - $scope.cyberpanelLoading = true; - $('#cyberpanelLoading').hide(); - - if (response.data.status === 1) { - // Find the container and update its process info - for (var i = 0; i < $scope.ContainerList.length; i++) { - if ($scope.ContainerList[i].id === containerId) { - $scope.ContainerList[i].topHead = response.data.data[1].Titles; - $scope.ContainerList[i].topProcesses = response.data.data[1].Processes; - break; - } - } - - // Open the processes modal - $('#processes').modal('show'); - - // Also update the processes in the global scope for the modal - $scope.topHead = response.data.data[1].Titles; - $scope.topProcesses = response.data.data[1].Processes; - } else { - new PNotify({ - title: 'Operation Failed!', - text: response.data.error_message, - type: 'error' - }); - } - }, function(error) { - $scope.cyberpanelLoading = true; - $('#cyberpanelLoading').hide(); - - new PNotify({ - title: 'Operation Failed!', - text: 'Connection disrupted, refresh the page.', - type: 'error' - }); - }); - }; - - // Helper function to handle container actions - $scope.handleAction = function(action, container) { - $scope.cyberpanelLoading = false; - $('#cyberpanelLoading').show(); - - var url = "/docker/"; - switch(action) { - case 'start': - url += "startContainer"; - break; - case 'stop': - url += "stopContainer"; - break; - case 'restart': - url += "restartContainer"; - break; - default: - console.error("Unknown action:", action); - $('#cyberpanelLoading').hide(); - return; - } - - var data = { - 'name': $('#sitename').html(), - 'container_id': container.id - }; - - var config = { - headers: { - 'X-CSRFToken': getCookie('csrftoken') - } - }; - - $http.post(url, data, config).then( - function(response) { - $scope.cyberpanelLoading = true; - $('#cyberpanelLoading').hide(); - - if (response.data.status === 1) { - new PNotify({ - title: 'Success!', - text: 'Container ' + action + ' successful.', - type: 'success' - }); - - // Update container status after action - container.status = action === 'stop' ? 'stopped' : 'running'; - - // Refresh container info after short delay to allow Docker to update - setTimeout(function() { - $scope.getcontainer(); - }, 1000); - } else { - new PNotify({ - title: 'Operation Failed!', - text: response.data.error_message || 'An unknown error occurred.', - type: 'error' - }); - } - }, - function(error) { - $scope.cyberpanelLoading = true; - $('#cyberpanelLoading').hide(); - - new PNotify({ - title: 'Operation Failed!', - text: 'Connection disrupted or server error occurred.', - type: 'error' - }); - - console.error("Error during container action:", error); - } - ); - }; - // Keep your existing functions + $scope.recreateappcontainer = function() { /* ... */ }; $scope.refreshStatus = function() { /* ... */ }; $scope.restarthStatus = function() { /* ... */ }; $scope.StopContainerAPP = function() { /* ... */ }; @@ -551,7 +324,7 @@ app.controller('ListDockersitecontainer', function ($scope, $http) { }); $('#settings').modal('hide'); // Refresh container info after update - $scope.getcontainer(); + $scope.Lunchcontainer($scope.selectedContainer.id); } else { new PNotify({ title: 'Operation Failed!', @@ -572,32 +345,6 @@ app.controller('ListDockersitecontainer', function ($scope, $http) { } }; - // Add volume and environment field functions - $scope.addVolField = function() { - if (!$scope.volList) { - $scope.volList = {}; - $scope.volListNumber = 0; - } - - $scope.volList[$scope.volListNumber] = {'dest': '', 'src': ''}; - $scope.volListNumber++; - }; - - $scope.removeVolField = function() { - if ($scope.volListNumber > 0) { - $scope.volListNumber--; - delete $scope.volList[$scope.volListNumber]; - } - }; - - $scope.addEnvField = function() { - if (!$scope.envList) { - $scope.envList = {}; - } - - $scope.envList[Object.keys($scope.envList).length] = {'name': '', 'value': ''}; - }; - // Add location service to the controller for the n8n URL $scope.location = window.location; }); \ No newline at end of file diff --git a/websiteFunctions/templates/websiteFunctions/DockerSiteHome.html b/websiteFunctions/templates/websiteFunctions/DockerSiteHome.html index 76053b7bb..c1f865760 100644 --- a/websiteFunctions/templates/websiteFunctions/DockerSiteHome.html +++ b/websiteFunctions/templates/websiteFunctions/DockerSiteHome.html @@ -1,233 +1,1026 @@ {% extends "baseTemplate/index.html" %} {% load i18n %} -{% block title %}{% trans "Application Installer" %}{% endblock %} +{% block title %}{% trans "Docker Sites - CyberPanel" %}{% endblock %} {% block content %} -
-
-

{{ websitename }}

-
+ {% load static %} + {% get_current_language as LANGUAGE_CODE %} + -
- -
-
-
-
-

{{ '{% verbatim %}' }}{{ container.Names }}{{ '{% endverbatim %}' }}

-
- - - - -
-
-
- -
-
Container Info
-
-
-

ID: {{ '{% verbatim %}' }}{{ truncateId(container.id) }}{{ '{% endverbatim %}' }}

-

Image: {{ '{% verbatim %}' }}{{ container.Image }}{{ '{% endverbatim %}' }}

-

Status: {{ '{% verbatim %}' }}{{ container.Status }}{{ '{% endverbatim %}' }}

-
-
-

Created: {{ '{% verbatim %}' }}{{ container.Created | date:'medium' }}{{ '{% endverbatim %}' }}

-

Start on Reboot: {{ '{% verbatim %}' }}{{ container.startOnReboot ? 'Yes' : 'No' }}{{ '{% endverbatim %}' }}

-
-
-
+ + + + + +
+ +
+

{% trans "Containers" %} + Create +

+

{% trans "Manage containers on server" %}

- -