mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-05-07 14:17:06 +02:00
Initial commit for v2.4.3
This commit is contained in:
415
websiteFunctions/static/websiteFunctions/DockerContainers.js
Normal file
415
websiteFunctions/static/websiteFunctions/DockerContainers.js
Normal file
@@ -0,0 +1,415 @@
|
||||
var app = angular.module('CyberCP');
|
||||
|
||||
app.controller('ListDockersitecontainer', function ($scope, $http) {
|
||||
$scope.cyberPanelLoading = true;
|
||||
$scope.cyberpanelLoading = true;
|
||||
$scope.conatinerview = true;
|
||||
$scope.ContainerList = [];
|
||||
$('#cyberpanelLoading').hide();
|
||||
|
||||
// Format bytes to human readable
|
||||
function formatBytes(bytes, decimals = 2) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
$scope.getcontainer = function () {
|
||||
$('#cyberpanelLoading').show();
|
||||
url = "/docker/getDockersiteList";
|
||||
|
||||
var data = {'name': $('#sitename').html()};
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
$http.post(url, data, config).then(ListInitialData, cantLoadInitialData);
|
||||
|
||||
function ListInitialData(response) {
|
||||
$('#cyberpanelLoading').hide();
|
||||
if (response.data.status === 1) {
|
||||
$scope.cyberPanelLoading = true;
|
||||
var finalData = JSON.parse(response.data.data[1]);
|
||||
$scope.ContainerList = finalData;
|
||||
$("#listFail").hide();
|
||||
} else {
|
||||
$("#listFail").fadeIn();
|
||||
$scope.errorMessage = response.data.error_message;
|
||||
}
|
||||
}
|
||||
|
||||
function cantLoadInitialData(response) {
|
||||
$scope.cyberPanelLoading = true;
|
||||
$('#cyberpanelLoading').hide();
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: 'Connection disrupted, refresh the page.',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.Lunchcontainer = function (containerid) {
|
||||
$scope.cyberpanelLoading = false;
|
||||
$('#cyberpanelLoading').show();
|
||||
var url = "/docker/getContainerAppinfo";
|
||||
|
||||
var data = {
|
||||
'name': $('#sitename').html(),
|
||||
'id': containerid
|
||||
};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
$http.post(url, data, config).then(ListInitialData, cantLoadInitialData);
|
||||
|
||||
function ListInitialData(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
$('#cyberpanelLoading').hide();
|
||||
|
||||
if (response.data.status === 1) {
|
||||
var containerInfo = response.data.data[1];
|
||||
console.log("Full container info:", containerInfo);
|
||||
|
||||
// Find the container in the list and update its information
|
||||
for (var i = 0; i < $scope.ContainerList.length; i++) {
|
||||
if ($scope.ContainerList[i].id === containerid) {
|
||||
// Basic Information
|
||||
$scope.ContainerList[i].status = containerInfo.status;
|
||||
$scope.ContainerList[i].created = new Date(containerInfo.created);
|
||||
$scope.ContainerList[i].uptime = containerInfo.uptime;
|
||||
$scope.ContainerList[i].image = containerInfo.image;
|
||||
|
||||
// Environment Variables - ensure it's properly set
|
||||
if (containerInfo.environment) {
|
||||
console.log("Setting environment:", containerInfo.environment);
|
||||
$scope.ContainerList[i].environment = containerInfo.environment;
|
||||
console.log("Container after env update:", $scope.ContainerList[i]);
|
||||
} else {
|
||||
console.log("No environment in container info");
|
||||
}
|
||||
|
||||
// Resource Usage
|
||||
var memoryBytes = containerInfo.memory_usage;
|
||||
$scope.ContainerList[i].memoryUsage = formatBytes(memoryBytes);
|
||||
$scope.ContainerList[i].memoryUsagePercent = (memoryBytes / (1024 * 1024 * 1024)) * 100;
|
||||
$scope.ContainerList[i].cpuUsagePercent = (containerInfo.cpu_usage / 10000000000) * 100;
|
||||
|
||||
// Network & Ports
|
||||
$scope.ContainerList[i].ports = containerInfo.ports;
|
||||
|
||||
// Volumes
|
||||
$scope.ContainerList[i].volumes = containerInfo.volumes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get container logs
|
||||
$scope.getcontainerlog(containerid);
|
||||
} else {
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: response.data.error_message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function cantLoadInitialData(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
$('#cyberpanelLoading').hide();
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: 'Connection disrupted, refresh the page.',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.getcontainerlog = function (containerid) {
|
||||
$scope.cyberpanelLoading = false;
|
||||
var url = "/docker/getContainerApplog";
|
||||
|
||||
var data = {
|
||||
'name': $('#sitename').html(),
|
||||
'id': containerid
|
||||
};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
$http.post(url, data, config).then(ListInitialData, cantLoadInitialData);
|
||||
|
||||
function ListInitialData(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
$scope.conatinerview = false;
|
||||
$('#cyberpanelLoading').hide();
|
||||
|
||||
if (response.data.status === 1) {
|
||||
// Find the container in the list and update its logs
|
||||
for (var i = 0; i < $scope.ContainerList.length; i++) {
|
||||
if ($scope.ContainerList[i].id === containerid) {
|
||||
$scope.ContainerList[i].logs = response.data.data[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: response.data.error_message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function cantLoadInitialData(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
$('#cyberpanelLoading').hide();
|
||||
$scope.conatinerview = false;
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: 'Connection disrupted, refresh the page.',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Auto-refresh container info every 30 seconds
|
||||
var refreshInterval;
|
||||
$scope.$watch('conatinerview', function(newValue, oldValue) {
|
||||
if (newValue === false) { // When container view is shown
|
||||
refreshInterval = setInterval(function() {
|
||||
if ($scope.cid) {
|
||||
$scope.Lunchcontainer($scope.cid);
|
||||
}
|
||||
}, 30000); // 30 seconds
|
||||
} else { // When container view is hidden
|
||||
if (refreshInterval) {
|
||||
clearInterval(refreshInterval);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Clean up on controller destruction
|
||||
$scope.$on('$destroy', function() {
|
||||
if (refreshInterval) {
|
||||
clearInterval(refreshInterval);
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize
|
||||
$scope.getcontainer();
|
||||
|
||||
// Keep your existing functions
|
||||
$scope.recreateappcontainer = function() { /* ... */ };
|
||||
$scope.refreshStatus = function() { /* ... */ };
|
||||
$scope.restarthStatus = function() { /* ... */ };
|
||||
$scope.StopContainerAPP = function() { /* ... */ };
|
||||
$scope.cAction = function(action) {
|
||||
$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);
|
||||
return;
|
||||
}
|
||||
|
||||
var data = {
|
||||
'name': $('#sitename').html(),
|
||||
'container_id': $scope.selectedContainer.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
|
||||
$scope.selectedContainer.status = action === 'stop' ? 'stopped' : 'running';
|
||||
|
||||
// Refresh container info
|
||||
$scope.Lunchcontainer($scope.selectedContainer.id);
|
||||
} 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);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// Update the container selection when actions are triggered
|
||||
$scope.setSelectedContainer = function(container) {
|
||||
$scope.selectedContainer = container;
|
||||
};
|
||||
|
||||
// Update the button click handlers to set selected container
|
||||
$scope.handleAction = function(action, container) {
|
||||
$scope.setSelectedContainer(container);
|
||||
$scope.cAction(action);
|
||||
};
|
||||
|
||||
// Add specific action functions that are referenced in the template
|
||||
$scope.startContainer = function(containerId, containerName) {
|
||||
$scope.selectedContainer = { id: containerId, name: containerName };
|
||||
$scope.cAction('start');
|
||||
};
|
||||
|
||||
$scope.stopContainer = function(containerId, containerName) {
|
||||
$scope.selectedContainer = { id: containerId, name: containerName };
|
||||
$scope.cAction('stop');
|
||||
};
|
||||
|
||||
$scope.restartContainer = function(containerId, containerName) {
|
||||
$scope.selectedContainer = { id: containerId, name: containerName };
|
||||
$scope.cAction('restart');
|
||||
};
|
||||
|
||||
$scope.openSettings = function(container) {
|
||||
$scope.selectedContainer = container;
|
||||
$('#settings').modal('show');
|
||||
};
|
||||
|
||||
$scope.saveSettings = function() {
|
||||
$scope.cyberpanelLoading = false;
|
||||
$('#cyberpanelLoading').show();
|
||||
|
||||
var url = "/docker/updateContainerSettings";
|
||||
var data = {
|
||||
'name': $('#sitename').html(),
|
||||
'id': $scope.selectedContainer.id,
|
||||
'memoryLimit': $scope.selectedContainer.memoryLimit,
|
||||
'startOnReboot': $scope.selectedContainer.startOnReboot
|
||||
};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
$http.post(url, data, config).then(ListInitialData, cantLoadInitialData);
|
||||
|
||||
function ListInitialData(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
$('#cyberpanelLoading').hide();
|
||||
|
||||
if (response.data.status === 1) {
|
||||
new PNotify({
|
||||
title: 'Success!',
|
||||
text: 'Container settings updated successfully.',
|
||||
type: 'success'
|
||||
});
|
||||
$('#settings').modal('hide');
|
||||
// Refresh container info after update
|
||||
$scope.Lunchcontainer($scope.selectedContainer.id);
|
||||
} else {
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: response.data.error_message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function cantLoadInitialData(response) {
|
||||
$scope.cyberpanelLoading = true;
|
||||
$('#cyberpanelLoading').hide();
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: 'Connection disrupted, refresh the page.',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Add location service to the controller for the n8n URL
|
||||
$scope.location = window.location;
|
||||
|
||||
// Function to extract n8n version from environment variables
|
||||
$scope.getN8nVersion = function(container) {
|
||||
console.log('getN8nVersion called with container:', container);
|
||||
|
||||
if (!container || !container.environment) {
|
||||
console.log('No container or environment data');
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
console.log('Container environment:', container.environment);
|
||||
|
||||
var version = null;
|
||||
|
||||
// Try to find NODE_VERSION first
|
||||
version = container.environment.find(function(env) {
|
||||
return env && env.startsWith('NODE_VERSION=');
|
||||
});
|
||||
|
||||
if (version) {
|
||||
console.log('Found NODE_VERSION:', version);
|
||||
return version.split('=')[1];
|
||||
}
|
||||
|
||||
// Try to find N8N_VERSION
|
||||
version = container.environment.find(function(env) {
|
||||
return env && env.startsWith('N8N_VERSION=');
|
||||
});
|
||||
|
||||
if (version) {
|
||||
console.log('Found N8N_VERSION:', version);
|
||||
return version.split('=')[1];
|
||||
}
|
||||
|
||||
console.log('No version found in environment');
|
||||
return 'unknown';
|
||||
};
|
||||
});
|
||||
15
websiteFunctions/static/websiteFunctions/docker-init.js
Normal file
15
websiteFunctions/static/websiteFunctions/docker-init.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// Wait for Angular to be ready
|
||||
angular.element(document).ready(function() {
|
||||
// Ensure the CyberCP module exists
|
||||
if (typeof angular.module('CyberCP') === 'undefined') {
|
||||
console.error('CyberCP module not found!');
|
||||
return;
|
||||
}
|
||||
|
||||
// Bootstrap Angular manually if needed
|
||||
var element = document.querySelector('[ng-controller="ListDockersitecontainer"]');
|
||||
if (element && !angular.element(element).data('$scope')) {
|
||||
console.log('Manually bootstrapping Angular for Docker container page');
|
||||
angular.bootstrap(element, ['CyberCP']);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,143 @@
|
||||
// Resource Monitoring
|
||||
let cpuChart, memoryChart, diskChart;
|
||||
let cpuData = [], memoryData = [], diskData = [];
|
||||
const maxDataPoints = 30;
|
||||
|
||||
function initializeCharts() {
|
||||
const chartOptions = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: 100,
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
return value + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
duration: 750
|
||||
}
|
||||
};
|
||||
|
||||
// CPU Chart
|
||||
const cpuCtx = document.getElementById('cpuChart').getContext('2d');
|
||||
cpuChart = new Chart(cpuCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'CPU Usage (%)',
|
||||
data: [],
|
||||
borderColor: '#2563eb',
|
||||
backgroundColor: 'rgba(37, 99, 235, 0.1)',
|
||||
borderWidth: 2,
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: chartOptions
|
||||
});
|
||||
|
||||
// Memory Chart
|
||||
const memoryCtx = document.getElementById('memoryChart').getContext('2d');
|
||||
memoryChart = new Chart(memoryCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Memory Usage (%)',
|
||||
data: [],
|
||||
borderColor: '#00b894',
|
||||
backgroundColor: 'rgba(0, 184, 148, 0.1)',
|
||||
borderWidth: 2,
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: chartOptions
|
||||
});
|
||||
|
||||
// Disk Chart
|
||||
const diskCtx = document.getElementById('diskChart').getContext('2d');
|
||||
diskChart = new Chart(diskCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Disk Usage (%)',
|
||||
data: [],
|
||||
borderColor: '#ff9800',
|
||||
backgroundColor: 'rgba(255, 152, 0, 0.1)',
|
||||
borderWidth: 2,
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: chartOptions
|
||||
});
|
||||
}
|
||||
|
||||
function updateCharts(data) {
|
||||
const now = new Date();
|
||||
const timeLabel = now.toLocaleTimeString();
|
||||
|
||||
// Update CPU Chart
|
||||
cpuData.push(data.cpu_usage);
|
||||
if (cpuData.length > maxDataPoints) cpuData.shift();
|
||||
cpuChart.data.labels.push(timeLabel);
|
||||
if (cpuChart.data.labels.length > maxDataPoints) cpuChart.data.labels.shift();
|
||||
cpuChart.data.datasets[0].data = cpuData;
|
||||
cpuChart.update('none'); // Use 'none' mode for better performance
|
||||
|
||||
// Update Memory Chart
|
||||
memoryData.push(data.memory_usage);
|
||||
if (memoryData.length > maxDataPoints) memoryData.shift();
|
||||
memoryChart.data.labels.push(timeLabel);
|
||||
if (memoryChart.data.labels.length > maxDataPoints) memoryChart.data.labels.shift();
|
||||
memoryChart.data.datasets[0].data = memoryData;
|
||||
memoryChart.update('none');
|
||||
|
||||
// Update Disk Chart
|
||||
diskData.push(data.disk_percent);
|
||||
if (diskData.length > maxDataPoints) diskData.shift();
|
||||
diskChart.data.labels.push(timeLabel);
|
||||
if (diskChart.data.labels.length > maxDataPoints) diskChart.data.labels.shift();
|
||||
diskChart.data.datasets[0].data = diskData;
|
||||
diskChart.update('none');
|
||||
}
|
||||
|
||||
function fetchResourceUsage() {
|
||||
$.ajax({
|
||||
url: '/websites/get_website_resources/',
|
||||
type: 'POST',
|
||||
data: JSON.stringify({
|
||||
'domain': $('#domainNamePage').text().trim()
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(data) {
|
||||
if (data.status === 1) {
|
||||
updateCharts(data);
|
||||
} else {
|
||||
console.error('Error fetching resource data:', data.error_message);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Failed to fetch resource usage:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize charts when the page loads
|
||||
$(document).ready(function() {
|
||||
if (document.getElementById('cpuChart')) {
|
||||
initializeCharts();
|
||||
// Fetch resource usage every 5 seconds
|
||||
setInterval(fetchResourceUsage, 5000);
|
||||
// Initial fetch
|
||||
fetchResourceUsage();
|
||||
}
|
||||
});
|
||||
162
websiteFunctions/static/websiteFunctions/js/websiteFunctions.js
Normal file
162
websiteFunctions/static/websiteFunctions/js/websiteFunctions.js
Normal file
@@ -0,0 +1,162 @@
|
||||
// Resource Monitoring
|
||||
let cpuChart, memoryChart, diskChart;
|
||||
let cpuData = [], memoryData = [], diskData = [];
|
||||
const maxDataPoints = 30;
|
||||
|
||||
function initializeCharts() {
|
||||
// CPU Chart
|
||||
const cpuCtx = document.getElementById('cpuChart').getContext('2d');
|
||||
cpuChart = new Chart(cpuCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'CPU Usage (%)',
|
||||
data: [],
|
||||
borderColor: '#2563eb',
|
||||
backgroundColor: 'rgba(37, 99, 235, 0.1)',
|
||||
borderWidth: 2,
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: 100,
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
return value + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Memory Chart
|
||||
const memoryCtx = document.getElementById('memoryChart').getContext('2d');
|
||||
memoryChart = new Chart(memoryCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Memory Usage (%)',
|
||||
data: [],
|
||||
borderColor: '#00b894',
|
||||
backgroundColor: 'rgba(0, 184, 148, 0.1)',
|
||||
borderWidth: 2,
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: 100,
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
return value + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Disk Chart
|
||||
const diskCtx = document.getElementById('diskChart').getContext('2d');
|
||||
diskChart = new Chart(diskCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Disk Usage (%)',
|
||||
data: [],
|
||||
borderColor: '#ff9800',
|
||||
backgroundColor: 'rgba(255, 152, 0, 0.1)',
|
||||
borderWidth: 2,
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: 100,
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
return value + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateCharts(data) {
|
||||
const now = new Date();
|
||||
const timeLabel = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
|
||||
|
||||
// Update CPU Chart
|
||||
cpuData.push(data.cpu_usage);
|
||||
if (cpuData.length > maxDataPoints) cpuData.shift();
|
||||
cpuChart.data.labels.push(timeLabel);
|
||||
if (cpuChart.data.labels.length > maxDataPoints) cpuChart.data.labels.shift();
|
||||
cpuChart.data.datasets[0].data = cpuData;
|
||||
cpuChart.update();
|
||||
|
||||
// Update Memory Chart
|
||||
memoryData.push(data.memory_usage);
|
||||
if (memoryData.length > maxDataPoints) memoryData.shift();
|
||||
memoryChart.data.labels.push(timeLabel);
|
||||
if (memoryChart.data.labels.length > maxDataPoints) memoryChart.data.labels.shift();
|
||||
memoryChart.data.datasets[0].data = memoryData;
|
||||
memoryChart.update();
|
||||
|
||||
// Update Disk Chart
|
||||
diskData.push(data.disk_percent);
|
||||
if (diskData.length > maxDataPoints) diskData.shift();
|
||||
diskChart.data.labels.push(timeLabel);
|
||||
if (diskChart.data.labels.length > maxDataPoints) diskChart.data.labels.shift();
|
||||
diskChart.data.datasets[0].data = diskData;
|
||||
diskChart.update();
|
||||
}
|
||||
|
||||
function fetchResourceUsage() {
|
||||
$.ajax({
|
||||
url: '/website/get_website_resources/',
|
||||
type: 'POST',
|
||||
data: JSON.stringify({
|
||||
'domain': $('#domainNamePage').text()
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(data) {
|
||||
if (data.status === 1) {
|
||||
updateCharts(data);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
console.error('Error fetching resource usage data');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize charts when the page loads
|
||||
$(document).ready(function() {
|
||||
initializeCharts();
|
||||
// Fetch resource usage every 5 seconds
|
||||
setInterval(fetchResourceUsage, 5000);
|
||||
// Initial fetch
|
||||
fetchResourceUsage();
|
||||
});
|
||||
285
websiteFunctions/static/websiteFunctions/websiteFunctions.css
Normal file
285
websiteFunctions/static/websiteFunctions/websiteFunctions.css
Normal file
@@ -0,0 +1,285 @@
|
||||
.current-pack {
|
||||
padding-top: 1.5%;
|
||||
color: #3e4855;
|
||||
font-weight: bold;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.website-content-box {
|
||||
border-radius: 25px;
|
||||
border-color: #3498db
|
||||
}
|
||||
|
||||
.table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > th {
|
||||
color: #777777;
|
||||
font-weight: 400;
|
||||
border-color: #cccccc;
|
||||
border-width: 1px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.table {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: separate;
|
||||
border-radius: 5px;
|
||||
background: #fdfdfd;
|
||||
padding: 0px 12px;
|
||||
margin: 10px 12px;
|
||||
}
|
||||
|
||||
.table > tbody > tr > td, .table > tbody > tr > th, .table > tfoot > tr > td, .table > tfoot > tr > th, .table > thead > tr > td, .table > thead > tr > th {
|
||||
/* padding: 10px; */
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mt-5 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.mt-10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.mt-20 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.mt-30 {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.mr-10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mb-10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ml-10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.my-10 {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.mx-5 {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.mx-10 {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.title-hero {
|
||||
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
margin: 0 0 15px;
|
||||
padding: 0;
|
||||
text-transform: none;
|
||||
font-size: 14px;
|
||||
opacity: 1;
|
||||
color: #777777;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.bs-badge {
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
line-height: 19px;
|
||||
display: inline-block;
|
||||
min-width: 20px;
|
||||
padding: 0 5px 0 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.row-title {
|
||||
color: #778899;
|
||||
}
|
||||
|
||||
/*span.h4 {
|
||||
white-space: nowrap;
|
||||
}*/
|
||||
/*.panel-body {
|
||||
white-space: nowrap;
|
||||
}
|
||||
*/
|
||||
.bg-gradient-9 {
|
||||
background: #0daeff; /* Old browsers */
|
||||
background: -moz-linear-gradient(-45deg, #0daeff 0%, #3939ad 30%); /* FF3.6-15 */
|
||||
background: -webkit-linear-gradient(-45deg, #0daeff 0%, #3939ad 30%); /* Chrome10-25,Safari5.1-6 */
|
||||
background: linear-gradient(-45deg, #0daeff 0%, #3939ad 30%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3939ad', endColorstr='#0daeff', GradientType=1); /* IE6-9 fallback on horizontal gradient */
|
||||
}
|
||||
|
||||
#page-header .user-account-btn > a.user-profile .glyph-icon, .logo-bg {
|
||||
background-color: rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #29A329 !important;
|
||||
}
|
||||
|
||||
.alert-success, .alert-success a, .parsley-success {
|
||||
color: #1e620f;
|
||||
border-color: #7cd362;
|
||||
background: #E4FFE4;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.text-bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tile-box-shortcut .tile-header {
|
||||
background: 0 0;
|
||||
padding: 1.85em 1.75em;
|
||||
position: absolute;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
left: 1.75em;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.tile-box-shortcut .tile-content-wrapper > .glyph-icon {
|
||||
position: absolute;
|
||||
left: 25px;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.fa {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 FontAwesome;
|
||||
font-size: 1.75em;
|
||||
text-rendering: auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 28px;
|
||||
}
|
||||
|
||||
.bs-badge {
|
||||
font-size: 18px;
|
||||
font-weight: 100;
|
||||
line-height: 19px;
|
||||
display: inline-block;
|
||||
min-width: 20px;
|
||||
padding: 0 5px 0 4px;
|
||||
border-radius: 2px;
|
||||
color: #afeeee;
|
||||
}
|
||||
|
||||
.tile-box-shortcut .bs-badge {
|
||||
left: auto;
|
||||
right: 10px;
|
||||
top: 30px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#sidebar-menu {
|
||||
background: #EAEAF1;
|
||||
}
|
||||
|
||||
#page-sidebar ul li a .glyph-icon {
|
||||
color: #191970;
|
||||
}
|
||||
|
||||
#header-logo .logo-content-big, .logo-content-small {
|
||||
height: 40px;
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
#mobile-navigation .logo-content-small {
|
||||
width: 50px;
|
||||
display: block;
|
||||
left: 75px;
|
||||
}
|
||||
|
||||
#header-nav-left {
|
||||
margin: 0 20px;
|
||||
}
|
||||
|
||||
#page-content {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
#sb-site, .sb-site-container {
|
||||
min-height: 250vh;
|
||||
}
|
||||
|
||||
.service-panel {
|
||||
background: #A1BDC6 !important;
|
||||
}
|
||||
|
||||
.serviceImg img {
|
||||
box-shadow: 0 0 2px 1px rgba(0, 0, 0, .05);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
margin: 0px auto;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tab-mod {
|
||||
color: #777777;
|
||||
background: transparent;
|
||||
border-color: #dddddd;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #33ADFF;
|
||||
border-color: #0099FF;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary:focus {
|
||||
background: #5CBDFF;
|
||||
border-color: #33ADFF;
|
||||
}
|
||||
|
||||
.btn-min-width {
|
||||
min-width: 275px;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 425px) {
|
||||
|
||||
.tile-box-shortcut .tile-header {
|
||||
left: .5em;
|
||||
font-size: 16px;
|
||||
padding: 1.75em .5em;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
.fa {
|
||||
font-size: 1.5em;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
[class^='col-'] {
|
||||
padding-left: 0px;
|
||||
}
|
||||
}
|
||||
18803
websiteFunctions/static/websiteFunctions/websiteFunctions.js
Normal file
18803
websiteFunctions/static/websiteFunctions/websiteFunctions.js
Normal file
File diff suppressed because it is too large
Load Diff
107
websiteFunctions/static/websiteFunctions/wpBackupFunctions.js
Normal file
107
websiteFunctions/static/websiteFunctions/wpBackupFunctions.js
Normal file
@@ -0,0 +1,107 @@
|
||||
// WordPress Backup and Staging Functions Extension
|
||||
// Simple fixes for backup and staging functionality
|
||||
|
||||
$(document).ready(function() {
|
||||
// Override getCreationStatus to show progress
|
||||
if (typeof window.getCreationStatus === 'undefined') {
|
||||
window.getCreationStatus = function() {
|
||||
var url = "/websites/installWordpressStatus";
|
||||
var data = {
|
||||
statusFile: window.statusFile
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: url,
|
||||
data: JSON.stringify(data),
|
||||
contentType: 'application/json',
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.abort === 1) {
|
||||
// Operation complete
|
||||
$('#wordpresshomeloading').hide();
|
||||
$('#createBackupBtn').prop('disabled', false).html('<i class="fas fa-download"></i> Create Backup');
|
||||
$('button[ng-click="CreateStagingNow()"]')
|
||||
.prop('disabled', false).html('<i class="fas fa-clone"></i> Create Staging Site');
|
||||
|
||||
// Hide progress bar, show success/error
|
||||
if (response.installStatus === 1) {
|
||||
if (window.statusFile && window.statusFile.includes('backup')) {
|
||||
$('#backupStatus').html('<span style="color: #10b981;">✓ Backup created successfully!</span>');
|
||||
// Show new progress section as success
|
||||
$('#backupProgressSection').show();
|
||||
$('#backupStatusMessage').show();
|
||||
$('#backupCurrentStatus').text('Backup successfully created.');
|
||||
$('#backupProgressBar').css('width', '100%').attr('aria-valuenow', 100);
|
||||
$('#backupProgressPercent').text('100%');
|
||||
$('#backupErrorBox').hide();
|
||||
$('#backupSuccessBox').show();
|
||||
} else {
|
||||
$('#stagingStatus').html('<span style="color: #10b981;">✓ Staging site created successfully!</span>');
|
||||
var scope = angular.element($('[ng-controller="WPsiteHome"]')).scope();
|
||||
if (scope && scope.fetchstaging) {
|
||||
scope.$apply(function() {
|
||||
scope.fetchstaging();
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var errorMsg = response.error_message || 'Operation failed';
|
||||
if (window.statusFile && window.statusFile.includes('backup')) {
|
||||
$('#backupStatus').html('<span style="color: #ef4444;">✗ ' + errorMsg + '</span>');
|
||||
// Show error in new progress section
|
||||
$('#backupProgressSection').show();
|
||||
$('#backupStatusMessage').hide();
|
||||
$('#backupProgressBar').css('width', '0%').attr('aria-valuenow', 0);
|
||||
$('#backupProgressPercent').text('0%');
|
||||
$('#backupErrorBox').show();
|
||||
$('#backupErrorMessage').text(errorMsg);
|
||||
$('#backupSuccessBox').hide();
|
||||
} else {
|
||||
$('#stagingStatus').html('<span style="color: #ef4444;">✗ ' + errorMsg + '</span>');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Still in progress
|
||||
var status = response.currentStatus || 'Processing...';
|
||||
var progress = response.installationProgress || 0;
|
||||
var statusHtml = '<i class="fas fa-spinner fa-pulse"></i> ' + status + ' (' + progress + '%)';
|
||||
if (window.statusFile && window.statusFile.includes('backup')) {
|
||||
$('#backupStatus').html(statusHtml);
|
||||
// Show and update progress bar
|
||||
$('#backupProgressSection').show();
|
||||
$('#backupStatusMessage').show();
|
||||
$('#backupCurrentStatus').text(status);
|
||||
$('#backupProgressBar').css('width', progress + '%').attr('aria-valuenow', progress);
|
||||
$('#backupProgressPercent').text(progress + '%');
|
||||
$('#backupErrorBox').hide();
|
||||
$('#backupSuccessBox').hide();
|
||||
} else {
|
||||
$('#stagingStatus').html(statusHtml);
|
||||
}
|
||||
setTimeout(window.getCreationStatus, 1000);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#wordpresshomeloading').hide();
|
||||
$('#createBackupBtn').prop('disabled', false).html('<i class="fas fa-download"></i> Create Backup');
|
||||
$('button[ng-click="CreateStagingNow()"]')
|
||||
.prop('disabled', false).html('<i class="fas fa-clone"></i> Create Staging Site');
|
||||
// Show error in progress section if backup
|
||||
if (window.statusFile && window.statusFile.includes('backup')) {
|
||||
$('#backupProgressSection').show();
|
||||
$('#backupStatusMessage').hide();
|
||||
$('#backupProgressBar').css('width', '0%').attr('aria-valuenow', 0);
|
||||
$('#backupProgressPercent').text('0%');
|
||||
$('#backupErrorBox').show();
|
||||
$('#backupErrorMessage').text('Error loading backup status.');
|
||||
$('#backupSuccessBox').hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user