improve home page design

This commit is contained in:
usmannasir
2025-06-02 00:58:11 +05:00
parent 353a133a1d
commit 2463cea5e2
4 changed files with 228 additions and 63 deletions

View File

@@ -875,6 +875,32 @@ app.controller('dashboardStatsController', function ($scope, $http, $timeout) {
$scope.totalDBs = 0; $scope.totalDBs = 0;
$scope.totalEmails = 0; $scope.totalEmails = 0;
// SSH Logins
$scope.sshLogins = [];
$scope.loadingSSHLogins = true;
$scope.errorSSHLogins = '';
function fetchSSHLogins() {
$scope.loadingSSHLogins = true;
$http.get('/baseTemplate/getRecentSSHLogins').then(function (response) {
$scope.loadingSSHLogins = false;
if (response.data && response.data.logins) {
$scope.sshLogins = response.data.logins;
} else {
$scope.sshLogins = [];
}
}, function (error) {
$scope.loadingSSHLogins = false;
$scope.sshLogins = [];
$scope.errorSSHLogins = 'Failed to load SSH logins.';
});
}
fetchSSHLogins();
var sshPoller = function() {
fetchSSHLogins();
$timeout(sshPoller, 10000);
};
$timeout(sshPoller, 10000);
// Chart.js chart objects // Chart.js chart objects
var trafficChart, diskIOChart, cpuChart; var trafficChart, diskIOChart, cpuChart;
// Data arrays for live graphs // Data arrays for live graphs

View File

@@ -6,60 +6,64 @@
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} --> <!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container"> <div class="container" style="background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); min-height: 100vh; padding: 20px;">
<div id="page-title"> <div id="page-title" style="text-align: center; margin-bottom: 40px; padding: 30px; background: rgba(255,255,255,0.9); border-radius: 20px; backdrop-filter: blur(10px); box-shadow: 0 8px 32px rgba(0,0,0,0.1);">
<h2>{% trans "Home" %}</h2> <h2 style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-size: 2.5rem; font-weight: 700; margin-bottom: 10px; text-shadow: none;">{% trans "Home" %}</h2>
<p>{% trans "Use the tabs to navigate through the control panel." %}</p> <p style="color: #6c757d; font-size: 1.1rem; margin: 0; font-weight: 400;">{% trans "Use the tabs to navigate through the control panel." %}</p>
</div> </div>
<!-- Dashboard Stats Section --> <!-- Dashboard Stats Section -->
<div ng-controller="dashboardStatsController" style="margin-bottom: 30px;"> <div ng-controller="dashboardStatsController" style="margin-bottom: 40px;">
<!-- Info Cards Row --> <!-- Info Cards Row -->
<div style="display: flex; flex-wrap: wrap; gap: 15px; margin-bottom: 30px;"> <div style="display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 40px; justify-content: center;">
<!-- Total Sites Card --> <!-- Total Sites Card -->
<a href="{% url 'listWebsites' %}" style="flex: 1; min-width: 200px; max-width: 300px; text-decoration: none;"> <a href="{% url 'listWebsites' %}" style="flex: 1; min-width: 240px; max-width: 280px; text-decoration: none; transform: translateY(0); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);" onmouseover="this.style.transform='translateY(-10px) scale(1.02)'; this.style.boxShadow='0 20px 40px rgba(0,123,255,0.4)'" onmouseout="this.style.transform='translateY(0) scale(1)'; this.style.boxShadow='0 8px 25px rgba(0,123,255,0.25)'">
<div style="background: linear-gradient(135deg, #007bff 0%, #00c6ff 100%); color: #fff; padding: 20px; border-radius: 15px; box-shadow: 0 4px 15px rgba(0,123,255,0.3); height: 100%; cursor: pointer;"> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff; padding: 25px; border-radius: 20px; box-shadow: 0 8px 25px rgba(0,123,255,0.25); height: 100%; cursor: pointer; position: relative; overflow: hidden;">
<div style="display: flex; align-items: center;"> <div style="position: absolute; top: -50%; right: -50%; width: 100%; height: 100%; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%); pointer-events: none;"></div>
<div style="font-size: 2.5rem; margin-right: 15px; opacity: 0.9;"><i class="fa fa-globe"></i></div> <div style="display: flex; align-items: center; position: relative; z-index: 1;">
<div style="font-size: 3rem; margin-right: 20px; opacity: 0.9; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));"><i class="fa fa-globe"></i></div>
<div> <div>
<div style="font-size: 2.5rem; font-weight: bold; line-height: 1;">{$ totalSites $}</div> <div style="font-size: 2.8rem; font-weight: 700; line-height: 1; text-shadow: 0 2px 4px rgba(0,0,0,0.2);">{$ totalSites $}</div>
<div style="font-size: 0.95rem; opacity: 0.85; margin-top: 5px;">Total Sites</div> <div style="font-size: 1rem; opacity: 0.9; margin-top: 8px; font-weight: 500;">Total Sites</div>
</div> </div>
</div> </div>
</div> </div>
</a> </a>
<!-- WordPress Sites Card --> <!-- WordPress Sites Card -->
<a href="{% url 'ListWPSites' %}?wp=1" style="flex: 1; min-width: 200px; max-width: 300px; text-decoration: none;"> <a href="{% url 'ListWPSites' %}?wp=1" style="flex: 1; min-width: 240px; max-width: 280px; text-decoration: none; transform: translateY(0); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);" onmouseover="this.style.transform='translateY(-10px) scale(1.02)'; this.style.boxShadow='0 20px 40px rgba(111,66,193,0.4)'" onmouseout="this.style.transform='translateY(0) scale(1)'; this.style.boxShadow='0 8px 25px rgba(111,66,193,0.25)'">
<div style="background: linear-gradient(135deg, #6f42c1 0%, #b993ff 100%); color: #fff; padding: 20px; border-radius: 15px; box-shadow: 0 4px 15px rgba(111,66,193,0.3); height: 100%; cursor: pointer;"> <div style="background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%); color: #fff; padding: 25px; border-radius: 20px; box-shadow: 0 8px 25px rgba(111,66,193,0.25); height: 100%; cursor: pointer; position: relative; overflow: hidden;">
<div style="display: flex; align-items: center;"> <div style="position: absolute; top: -50%; right: -50%; width: 100%; height: 100%; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%); pointer-events: none;"></div>
<div style="font-size: 2.5rem; margin-right: 15px; opacity: 0.9;"><i class="fa fa-wordpress"></i></div> <div style="display: flex; align-items: center; position: relative; z-index: 1;">
<div style="font-size: 3rem; margin-right: 20px; opacity: 0.9; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2)); color: #6f42c1;"><i class="fa fa-wordpress"></i></div>
<div> <div>
<div style="font-size: 2.5rem; font-weight: bold; line-height: 1;">{$ totalWPSites $}</div> <div style="font-size: 2.8rem; font-weight: 700; line-height: 1; text-shadow: 0 2px 4px rgba(0,0,0,0.2); color: #6f42c1;">{$ totalWPSites $}</div>
<div style="font-size: 0.95rem; opacity: 0.85; margin-top: 5px;">WordPress Sites</div> <div style="font-size: 1rem; opacity: 0.8; margin-top: 8px; font-weight: 500; color: #6f42c1;">WordPress Sites</div>
</div> </div>
</div> </div>
</div> </div>
</a> </a>
<!-- Total Databases Card --> <!-- Total Databases Card -->
<a href="{% url 'listDBs' %}" style="flex: 1; min-width: 200px; max-width: 300px; text-decoration: none;"> <a href="{% url 'listDBs' %}" style="flex: 1; min-width: 240px; max-width: 280px; text-decoration: none; transform: translateY(0); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);" onmouseover="this.style.transform='translateY(-10px) scale(1.02)'; this.style.boxShadow='0 20px 40px rgba(23,162,184,0.4)'" onmouseout="this.style.transform='translateY(0) scale(1)'; this.style.boxShadow='0 8px 25px rgba(23,162,184,0.25)'">
<div style="background: linear-gradient(135deg, #17a2b8 0%, #6fe7dd 100%); color: #fff; padding: 20px; border-radius: 15px; box-shadow: 0 4px 15px rgba(23,162,184,0.3); height: 100%; cursor: pointer;"> <div style="background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%); color: #fff; padding: 25px; border-radius: 20px; box-shadow: 0 8px 25px rgba(23,162,184,0.25); height: 100%; cursor: pointer; position: relative; overflow: hidden;">
<div style="display: flex; align-items: center;"> <div style="position: absolute; top: -50%; right: -50%; width: 100%; height: 100%; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%); pointer-events: none;"></div>
<div style="font-size: 2.5rem; margin-right: 15px; opacity: 0.9;"><i class="fa fa-database"></i></div> <div style="display: flex; align-items: center; position: relative; z-index: 1;">
<div style="font-size: 3rem; margin-right: 20px; opacity: 0.9; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2)); color: #17a2b8;"><i class="fa fa-database"></i></div>
<div> <div>
<div style="font-size: 2.5rem; font-weight: bold; line-height: 1;">{$ totalDBs $}</div> <div style="font-size: 2.8rem; font-weight: 700; line-height: 1; text-shadow: 0 2px 4px rgba(0,0,0,0.2); color: #17a2b8;">{$ totalDBs $}</div>
<div style="font-size: 0.95rem; opacity: 0.85; margin-top: 5px;">Total Databases</div> <div style="font-size: 1rem; opacity: 0.8; margin-top: 8px; font-weight: 500; color: #17a2b8;">Total Databases</div>
</div> </div>
</div> </div>
</div> </div>
</a> </a>
<!-- Total Emails Card --> <!-- Total Emails Card -->
<a href="{% url 'listEmails' %}" style="flex: 1; min-width: 200px; max-width: 300px; text-decoration: none;"> <a href="{% url 'listEmails' %}" style="flex: 1; min-width: 240px; max-width: 280px; text-decoration: none; transform: translateY(0); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);" onmouseover="this.style.transform='translateY(-10px) scale(1.02)'; this.style.boxShadow='0 20px 40px rgba(255,152,0,0.4)'" onmouseout="this.style.transform='translateY(0) scale(1)'; this.style.boxShadow='0 8px 25px rgba(255,152,0,0.25)'">
<div style="background: linear-gradient(135deg, #ff9800 0%, #ffc107 100%); color: #fff; padding: 20px; border-radius: 15px; box-shadow: 0 4px 15px rgba(255,152,0,0.3); height: 100%; cursor: pointer;"> <div style="background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%); color: #fff; padding: 25px; border-radius: 20px; box-shadow: 0 8px 25px rgba(255,152,0,0.25); height: 100%; cursor: pointer; position: relative; overflow: hidden;">
<div style="display: flex; align-items: center;"> <div style="position: absolute; top: -50%; right: -50%; width: 100%; height: 100%; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%); pointer-events: none;"></div>
<div style="font-size: 2.5rem; margin-right: 15px; opacity: 0.9;"><i class="fa fa-envelope"></i></div> <div style="display: flex; align-items: center; position: relative; z-index: 1;">
<div style="font-size: 3rem; margin-right: 20px; opacity: 0.9; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2)); color: #ff9800;"><i class="fa fa-envelope"></i></div>
<div> <div>
<div style="font-size: 2.5rem; font-weight: bold; line-height: 1;">{$ totalEmails $}</div> <div style="font-size: 2.8rem; font-weight: 700; line-height: 1; text-shadow: 0 2px 4px rgba(0,0,0,0.2); color: #ff9800;">{$ totalEmails $}</div>
<div style="font-size: 0.95rem; opacity: 0.85; margin-top: 5px;">Total Emails</div> <div style="font-size: 1rem; opacity: 0.8; margin-top: 8px; font-weight: 500; color: #ff9800;">Total Emails</div>
</div> </div>
</div> </div>
</div> </div>
@@ -67,13 +71,13 @@
</div> </div>
{% if admin %} {% if admin %}
<div ng-controller="homePageStatus" style="margin-bottom: 30px;"> <div ng-controller="homePageStatus" style="margin-bottom: 40px;">
<div style="display: flex; justify-content: center; gap: 30px; align-items: stretch;"> <div style="display: flex; justify-content: center; gap: 40px; align-items: stretch; flex-wrap: wrap;">
<!-- CPU Usage --> <!-- CPU Usage -->
<div style="background: #fff; border-radius: 15px; box-shadow: 0 2px 10px rgba(255,0,0,0.08); padding: 20px 30px; min-width: 180px; text-align: center;"> <div style="background: rgba(255,255,255,0.95); border-radius: 20px; box-shadow: 0 8px 32px rgba(229,57,53,0.15); padding: 30px 40px; min-width: 200px; text-align: center; backdrop-filter: blur(10px); border: 1px solid rgba(229,57,53,0.1); transform: translateY(0); transition: all 0.3s ease;" onmouseover="this.style.transform='translateY(-5px)'; this.style.boxShadow='0 15px 40px rgba(229,57,53,0.25)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 8px 32px rgba(229,57,53,0.15)'">
<div style="font-size: 1.1rem; color: #e53935; font-weight: 600; margin-bottom: 10px;">{% trans "CPU Usage" %}</div> <div style="font-size: 1.2rem; color: #e53935; font-weight: 700; margin-bottom: 15px; text-transform: uppercase; letter-spacing: 1px;">{% trans "CPU Usage" %}</div>
<div id="redcircle" class="c100 red cpu" style="margin: 0 auto;"> <div id="redcircle" class="c100 red cpu" style="margin: 0 auto; filter: drop-shadow(0 4px 8px rgba(229,57,53,0.2));">
<span>{$ cpuUsage $}%</span> <span style="font-weight: 700; font-size: 1.2rem;">{$ cpuUsage $}%</span>
<div class="slice"> <div class="slice">
<div class="bar"></div> <div class="bar"></div>
<div class="fill"></div> <div class="fill"></div>
@@ -81,10 +85,10 @@
</div> </div>
</div> </div>
<!-- RAM Usage --> <!-- RAM Usage -->
<div style="background: #fff; border-radius: 15px; box-shadow: 0 2px 10px rgba(76,175,80,0.08); padding: 20px 30px; min-width: 180px; text-align: center;"> <div style="background: rgba(255,255,255,0.95); border-radius: 20px; box-shadow: 0 8px 32px rgba(67,160,71,0.15); padding: 30px 40px; min-width: 200px; text-align: center; backdrop-filter: blur(10px); border: 1px solid rgba(67,160,71,0.1); transform: translateY(0); transition: all 0.3s ease;" onmouseover="this.style.transform='translateY(-5px)'; this.style.boxShadow='0 15px 40px rgba(67,160,71,0.25)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 8px 32px rgba(67,160,71,0.15)'">
<div style="font-size: 1.1rem; color: #43a047; font-weight: 600; margin-bottom: 10px;">{% trans "Ram Usage" %}</div> <div style="font-size: 1.2rem; color: #43a047; font-weight: 700; margin-bottom: 15px; text-transform: uppercase; letter-spacing: 1px;">{% trans "Ram Usage" %}</div>
<div id="greencircle" class="c100 p0 green ram" style="margin: 0 auto;"> <div id="greencircle" class="c100 p0 green ram" style="margin: 0 auto; filter: drop-shadow(0 4px 8px rgba(67,160,71,0.2));">
<span>{$ ramUsage $}%</span> <span style="font-weight: 700; font-size: 1.2rem;">{$ ramUsage $}%</span>
<div class="slice"> <div class="slice">
<div class="bar"></div> <div class="bar"></div>
<div class="fill"></div> <div class="fill"></div>
@@ -92,10 +96,10 @@
</div> </div>
</div> </div>
<!-- Disk Usage --> <!-- Disk Usage -->
<div style="background: #fff; border-radius: 15px; box-shadow: 0 2px 10px rgba(233,30,99,0.08); padding: 20px 30px; min-width: 180px; text-align: center;"> <div style="background: rgba(255,255,255,0.95); border-radius: 20px; box-shadow: 0 8px 32px rgba(216,27,96,0.15); padding: 30px 40px; min-width: 200px; text-align: center; backdrop-filter: blur(10px); border: 1px solid rgba(216,27,96,0.1); transform: translateY(0); transition: all 0.3s ease;" onmouseover="this.style.transform='translateY(-5px)'; this.style.boxShadow='0 15px 40px rgba(216,27,96,0.25)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 8px 32px rgba(216,27,96,0.15)'">
<div style="font-size: 1.1rem; color: #d81b60; font-weight: 600; margin-bottom: 10px;">{% trans "Disk Usage '/'" %}</div> <div style="font-size: 1.2rem; color: #d81b60; font-weight: 700; margin-bottom: 15px; text-transform: uppercase; letter-spacing: 1px;">{% trans "Disk Usage '/'" %}</div>
<div id="pinkcircle" class="c100 pink disk" style="margin: 0 auto;"> <div id="pinkcircle" class="c100 pink disk" style="margin: 0 auto; filter: drop-shadow(0 4px 8px rgba(216,27,96,0.2));">
<span>{$ diskUsage $}%</span> <span style="font-weight: 700; font-size: 1.2rem;">{$ diskUsage $}%</span>
<div class="slice"> <div class="slice">
<div class="bar"></div> <div class="bar"></div>
<div class="fill"></div> <div class="fill"></div>
@@ -104,33 +108,74 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Recent SSH Logins Widget -->
<div style="margin-bottom: 40px;">
<div style="background: rgba(255,255,255,0.97); border-radius: 18px; box-shadow: 0 8px 32px rgba(102,126,234,0.10); padding: 25px 30px; max-width: 900px; margin: 0 auto 0 auto;">
<div style="display: flex; align-items: center; margin-bottom: 18px;">
<i class="fa fa-terminal" style="font-size: 1.6rem; color: #667eea; margin-right: 12px;"></i>
<span style="font-size: 1.25rem; font-weight: 700; color: #333; letter-spacing: 0.5px;">Recent SSH Logins</span>
</div>
<div ng-if="loadingSSHLogins" style="text-align: center; padding: 20px; color: #888;">
<i class="fa fa-spinner fa-spin"></i> Loading recent SSH logins...
</div>
<div ng-if="!loadingSSHLogins && sshLogins.length === 0" style="text-align: center; color: #888;">
No recent SSH logins found.
</div>
<div ng-if="!loadingSSHLogins && sshLogins.length > 0" style="overflow-x: auto;">
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff;">
<th style="padding: 10px 8px; border-radius: 8px 0 0 8px; text-align: left;">User</th>
<th style="padding: 10px 8px; text-align: left;">IP</th>
<th style="padding: 10px 8px; text-align: left;">Country</th>
<th style="padding: 10px 8px; text-align: left;">Date/Time</th>
<th style="padding: 10px 8px; border-radius: 0 8px 8px 0; text-align: left;">Session</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="login in sshLogins" style="background: #f8f9fa; border-bottom: 1px solid #e9ecef;">
<td style="padding: 8px 8px; font-weight: 600; color: #333;">{{login.user}}</td>
<td style="padding: 8px 8px; color: #555;">{{login.ip}}</td>
<td style="padding: 8px 8px;">
<span ng-if="login.flag"><img ng-src="{{login.flag}}" alt="{{login.country}}" style="height: 18px; margin-right: 6px; vertical-align: middle;" /></span>
<span ng-if="!login.flag && login.country">{{login.country}}</span>
<span ng-if="!login.flag && !login.country">-</span>
</td>
<td style="padding: 8px 8px; color: #555;">{{login.date}}</td>
<td style="padding: 8px 8px; color: #888;">{{login.session}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{% endif %} {% endif %}
<!-- Graphs Section --> <!-- Graphs Section -->
<div style="background: #fff; border-radius: 15px; box-shadow: 0 2px 10px rgba(0,0,0,0.08); padding: 25px;"> <div style="background: rgba(255,255,255,0.95); border-radius: 25px; box-shadow: 0 12px 40px rgba(0,0,0,0.1); padding: 35px; backdrop-filter: blur(15px); border: 1px solid rgba(255,255,255,0.2);">
<!-- Tab Navigation --> <!-- Tab Navigation -->
<div style="text-align: center; margin-bottom: 20px;"> <div style="text-align: center; margin-bottom: 30px;">
<ul style="list-style: none; padding: 0; margin: 0; display: inline-flex; background: #f5f7fa; border-radius: 10px; padding: 5px; gap: 5px;"> <ul style="list-style: none; padding: 0; margin: 0; display: inline-flex; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; padding: 8px; gap: 8px; box-shadow: 0 8px 25px rgba(102,126,234,0.3);">
<li style="display: inline-block;"> <li style="display: inline-block;">
<a href="#traffic" id="traffic-tab" data-toggle="tab" style="display: block; padding: 12px 24px; background: #007bff; color: white; border-radius: 8px; text-decoration: none; font-weight: 500; transition: all 0.3s;"> <a href="#traffic" id="traffic-tab" data-toggle="tab" style="display: block; padding: 15px 30px; background: rgba(255,255,255,0.9); color: #667eea; border-radius: 12px; text-decoration: none; font-weight: 600; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); text-transform: uppercase; letter-spacing: 0.5px; font-size: 0.9rem;">
<i class="fa fa-exchange"></i> Traffic <i class="fa fa-exchange" style="margin-right: 8px;"></i> Traffic
</a> </a>
</li> </li>
<li style="display: inline-block;"> <li style="display: inline-block;">
<a href="#diskio" id="diskio-tab" data-toggle="tab" style="display: block; padding: 12px 24px; background: transparent; color: #6c757d; border-radius: 8px; text-decoration: none; font-weight: 500; transition: all 0.3s;"> <a href="#diskio" id="diskio-tab" data-toggle="tab" style="display: block; padding: 15px 30px; background: transparent; color: rgba(255,255,255,0.8); border-radius: 12px; text-decoration: none; font-weight: 600; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); text-transform: uppercase; letter-spacing: 0.5px; font-size: 0.9rem;">
<i class="fa fa-hdd-o"></i> Disk IO <i class="fa fa-hdd-o" style="margin-right: 8px;"></i> Disk IO
</a> </a>
</li> </li>
<li style="display: inline-block;"> <li style="display: inline-block;">
<a href="#cpu" id="cpu-tab" data-toggle="tab" style="display: block; padding: 12px 24px; background: transparent; color: #6c757d; border-radius: 8px; text-decoration: none; font-weight: 500; transition: all 0.3s;"> <a href="#cpu" id="cpu-tab" data-toggle="tab" style="display: block; padding: 15px 30px; background: transparent; color: rgba(255,255,255,0.8); border-radius: 12px; text-decoration: none; font-weight: 600; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); text-transform: uppercase; letter-spacing: 0.5px; font-size: 0.9rem;">
<i class="fa fa-microchip"></i> CPU Usage <i class="fa fa-microchip" style="margin-right: 8px;"></i> CPU Usage
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
<!-- Tab Content --> <!-- Tab Content -->
<div class="tab-content" style="background: #f8f9fa; border-radius: 12px; padding: 20px; min-height: 300px; border: 1px solid #e9ecef;"> <div class="tab-content" style="background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); border-radius: 18px; padding: 30px; min-height: 350px; border: 2px solid rgba(255,255,255,0.5); box-shadow: inset 0 2px 10px rgba(0,0,0,0.05);">
<div class="tab-pane fade show active" id="traffic" role="tabpanel"> <div class="tab-pane fade show active" id="traffic" role="tabpanel">
<canvas id="trafficChart" height="80"></canvas> <canvas id="trafficChart" height="80"></canvas>
</div> </div>
@@ -151,12 +196,29 @@
cursor: pointer; cursor: pointer;
} }
#dashboardGraphTabs a[data-toggle="tab"]:hover { #dashboardGraphTabs a[data-toggle="tab"]:hover {
background: #e9ecef !important; background: rgba(255,255,255,0.9) !important;
color: #495057 !important; color: #667eea !important;
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(102,126,234,0.3);
} }
#dashboardGraphTabs a[data-toggle="tab"].active { #dashboardGraphTabs a[data-toggle="tab"].active {
background: #007bff !important; background: rgba(255,255,255,0.9) !important;
color: white !important; color: #667eea !important;
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(102,126,234,0.3);
}
/* Enhanced hover effects for tabs */
a[data-toggle="tab"]:hover {
background: rgba(255,255,255,0.9) !important;
color: #667eea !important;
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(102,126,234,0.3);
}
/* Smooth animations for all interactive elements */
* {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
} }
</style> </style>
@@ -177,7 +239,9 @@
tabs.forEach(function(t) { tabs.forEach(function(t) {
t.classList.remove('active'); t.classList.remove('active');
t.style.background = 'transparent'; t.style.background = 'transparent';
t.style.color = '#6c757d'; t.style.color = 'rgba(255,255,255,0.8)';
t.style.transform = 'translateY(0)';
t.style.boxShadow = 'none';
}); });
document.querySelectorAll('.tab-pane').forEach(function(pane) { document.querySelectorAll('.tab-pane').forEach(function(pane) {
pane.classList.remove('show', 'active'); pane.classList.remove('show', 'active');
@@ -185,8 +249,10 @@
// Add active to clicked tab // Add active to clicked tab
this.classList.add('active'); this.classList.add('active');
this.style.background = '#007bff'; this.style.background = 'rgba(255,255,255,0.9)';
this.style.color = 'white'; this.style.color = '#667eea';
this.style.transform = 'translateY(-2px)';
this.style.boxShadow = '0 4px 15px rgba(102,126,234,0.3)';
// Show corresponding pane // Show corresponding pane
var target = this.getAttribute('href'); var target = this.getAttribute('href');

View File

@@ -19,4 +19,5 @@ urlpatterns = [
re_path(r'^getTrafficStats$', views.getTrafficStats, name='getTrafficStats'), re_path(r'^getTrafficStats$', views.getTrafficStats, name='getTrafficStats'),
re_path(r'^getDiskIOStats$', views.getDiskIOStats, name='getDiskIOStats'), re_path(r'^getDiskIOStats$', views.getDiskIOStats, name='getDiskIOStats'),
re_path(r'^getCPULoadGraph$', views.getCPULoadGraph, name='getCPULoadGraph'), re_path(r'^getCPULoadGraph$', views.getCPULoadGraph, name='getCPULoadGraph'),
re_path(r'^getRecentSSHLogins$', views.getRecentSSHLogins, name='getRecentSSHLogins'),
] ]

View File

@@ -14,12 +14,13 @@ import os
import plogical.CyberCPLogFileWriter as logging import plogical.CyberCPLogFileWriter as logging
from plogical.acl import ACLManager from plogical.acl import ACLManager
from manageServices.models import PDNSStatus from manageServices.models import PDNSStatus
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie, csrf_exempt
from plogical.processUtilities import ProcessUtilities from plogical.processUtilities import ProcessUtilities
from plogical.httpProc import httpProc from plogical.httpProc import httpProc
from websiteFunctions.models import Websites, WPSites from websiteFunctions.models import Websites, WPSites
from databases.models import Databases from databases.models import Databases
from mailServer.models import EUsers from mailServer.models import EUsers
from django.views.decorators.http import require_GET
# Create your views here. # Create your views here.
@@ -516,3 +517,74 @@ def getCPULoadGraph(request):
return HttpResponse(json.dumps(data), content_type='application/json') return HttpResponse(json.dumps(data), content_type='application/json')
except Exception as e: except Exception as e:
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json') return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')
@csrf_exempt
@require_GET
def getRecentSSHLogins(request):
try:
user_id = request.session.get('userID')
if not user_id:
return HttpResponse(json.dumps({'error': 'Not logged in'}), content_type='application/json', status=403)
currentACL = ACLManager.loadedACL(user_id)
if not currentACL.get('admin', 0):
return HttpResponse(json.dumps({'error': 'Admin only'}), content_type='application/json', status=403)
import re, time
from collections import OrderedDict
# Run 'last -n 20' to get recent SSH logins
try:
output = ProcessUtilities.outputExecutioner('last -n 20')
except Exception as e:
return HttpResponse(json.dumps({'error': 'Failed to run last: %s' % str(e)}), content_type='application/json', status=500)
lines = output.strip().split('\n')
logins = []
ip_cache = {}
for line in lines:
if not line.strip() or any(x in line for x in ['reboot', 'system boot', 'wtmp begins']):
continue
# Example: ubuntu pts/0 206.84.168.7 Sun Jun 1 19:41 still logged in
# or: ubuntu pts/0 206.84.169.36 Tue May 27 11:34 - 13:47 (02:13)
parts = re.split(r'\s+', line, maxsplit=5)
if len(parts) < 5:
continue
user, tty, ip, *rest = parts
# Find date/time and session info
date_session = rest[-1] if rest else ''
# Try to extract date/session
date_match = re.search(r'([A-Za-z]{3} [A-Za-z]{3} +\d+ [\d:]+)', line)
date_str = date_match.group(1) if date_match else ''
session_info = ''
if '-' in line:
# Session ended
session_info = line.split('-')[-1].strip()
elif 'still logged in' in line:
session_info = 'still logged in'
# GeoIP lookup (cache per request)
country = flag = ''
if re.match(r'\d+\.\d+\.\d+\.\d+', ip) and ip != '127.0.0.1':
if ip in ip_cache:
country, flag = ip_cache[ip]
else:
try:
geo = requests.get(f'http://ip-api.com/json/{ip}', timeout=2).json()
country = geo.get('countryCode', '')
flag = f"https://flagcdn.com/24x18/{country.lower()}.png" if country else ''
ip_cache[ip] = (country, flag)
except Exception:
country, flag = '', ''
elif ip == '127.0.0.1':
country, flag = 'Local', ''
logins.append({
'user': user,
'ip': ip,
'country': country,
'flag': flag,
'date': date_str,
'session': session_info,
'raw': line
})
return HttpResponse(json.dumps({'logins': logins}), content_type='application/json')
except Exception as e:
return HttpResponse(json.dumps({'error': str(e)}), content_type='application/json', status=500)