mirror of
https://github.com/stefanpejcic/openpanel
synced 2025-06-26 18:28:26 +00:00
256 lines
7.4 KiB
HTML
256 lines
7.4 KiB
HTML
{% extends 'base.html' %}
|
|
|
|
{% block content %}
|
|
|
|
|
|
<div class="row g-3">
|
|
|
|
<p>{{_('Disk usage is the amount of space that is used by the content of your sites, this includes databases, files, videos, images, emails and pages.')}}</p>
|
|
|
|
<div class="col-xl-7">
|
|
<div class="card card-one">
|
|
<div class="card-header">
|
|
<h6 class="card-title">{{_('Disk usage per directory')}}</h6>
|
|
<nav class="nav nav-icon nav-icon-sm ms-auto">
|
|
<a href="#" onclick='location.reload(true); return false;' class="nav-link"><i class="bi bi-arrow-clockwise"></i></a>
|
|
</nav>
|
|
</div><!-- card-header -->
|
|
<div class="card-body">
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
|
|
<canvas id="folderChart" width="400" height="200"></canvas>
|
|
|
|
</div><!-- card-body -->
|
|
</div><!-- card -->
|
|
</div><!-- col -->
|
|
<div class="col-sm-12 col-xl-5">
|
|
<div class="card card-one">
|
|
<div class="card-header">
|
|
<h6 class="card-title">{{_('Browse Directories')}}</h6>
|
|
<nav class="nav nav-icon nav-icon-sm ms-auto">
|
|
<a href="/disk-usage" class="nav-link"><i class="bi bi-house-fill"></i></a>
|
|
</nav>
|
|
</div><!-- card-header -->
|
|
<div class="card-body">
|
|
|
|
<table id="folders_to_navigate" class="table table-hover table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Directory</th>
|
|
<th>Size</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% if request.path != '/disk-usage/' %}
|
|
<tr>
|
|
<td><a href="#" id="goUp"><i class="bi bi-arrow-90deg-up"></i> {{_('Up One Level')}}</a></td>
|
|
<td></td>
|
|
</tr>
|
|
{% endif %}
|
|
{% for line in total_du_output.split('\n') %}
|
|
{% if line.strip() %}
|
|
<tr>
|
|
{% set parts = line.split() %}
|
|
{% set count = parts[0] %}
|
|
{% set directory = parts[1:]|join(' ') %}
|
|
<td class="file-name"><a href="#" onclick="openDirectory('{{ directory }}'); return false;"><i style="color: orange;" class="ri-folder-2-fill"></i> {{ directory }}</a>
|
|
</td>
|
|
<td>{{ count }}</td>
|
|
</tr>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div><!-- card-body -->
|
|
</div><!-- card -->
|
|
</div><!-- col -->
|
|
</div>
|
|
|
|
|
|
<script>
|
|
async function openDirectory(directory) {
|
|
// Display a toast message indicating that disk usage is being calculated for the specified directory
|
|
const toastMessage = `{{_('Calculating disk usage for ')}}` + directory + `..`;
|
|
const toast = toaster({
|
|
body: toastMessage,
|
|
className: `border-0 text-white bg-primary`,
|
|
});
|
|
|
|
// Construct the new URL by appending the directory to the current URL
|
|
var currentUrl = window.location.href;
|
|
var separator = currentUrl.endsWith('/') ? '' : '/';
|
|
var newUrl = currentUrl + separator + directory;
|
|
|
|
try {
|
|
// Send a GET request to the server using the fetch API
|
|
const response = await fetch(newUrl);
|
|
|
|
// Get the response HTML content
|
|
const resultHtml = await response.text();
|
|
|
|
// Parse the HTML string to extract the content of the specific element
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(resultHtml, 'text/html');
|
|
const mainScopeContent = doc.getElementById("main-scope")?.innerHTML;
|
|
|
|
// Replace the content of the element with the ID "main-scope"
|
|
const mainScopeElement = document.getElementById("main-scope");
|
|
if (mainScopeElement) {
|
|
mainScopeElement.innerHTML = mainScopeContent || '';
|
|
}
|
|
|
|
//add to url wothout reloading!
|
|
history.pushState({}, '', newUrl);
|
|
|
|
// Initialize the chart after updating the content and URL
|
|
initializeChart();
|
|
|
|
} catch (error) {
|
|
// Handle errors if the fetch request fails
|
|
console.error('Error fetching data:', error);
|
|
}
|
|
}
|
|
|
|
</script>
|
|
|
|
<script>
|
|
// Function to extract data from the table
|
|
function extractDataFromTable() {
|
|
const data = [];
|
|
const tableRows = document.querySelectorAll("#folders_to_navigate tbody tr");
|
|
|
|
tableRows.forEach((row) => {
|
|
const columns = row.querySelectorAll("td");
|
|
if (columns.length === 2) {
|
|
const directory = columns[0].textContent.trim();
|
|
const disk = parseHumanReadableSize(columns[1].textContent);
|
|
|
|
// Exclude rows with "Up One Level"
|
|
if (directory !== "Up One Level") {
|
|
data.push({ directory, disk });
|
|
}
|
|
}
|
|
});
|
|
|
|
return data;
|
|
}
|
|
|
|
// Function to parse human-readable size strings into MB
|
|
function parseHumanReadableSize(sizeStr) {
|
|
const sizeRegex = /^(\d+(\.\d+)?)\s*([BKMGT])?B?$/;
|
|
const match = sizeStr.match(sizeRegex);
|
|
|
|
if (!match) {
|
|
// Invalid format, return as is
|
|
return sizeStr;
|
|
}
|
|
|
|
const size = parseFloat(match[1]);
|
|
const unit = match[3];
|
|
|
|
switch (unit) {
|
|
case 'B':
|
|
return size / 1024 / 1024; // Convert to MB
|
|
case 'K':
|
|
return size / 1024; // Convert to MB
|
|
case 'M':
|
|
return size; // Already in MB
|
|
case 'G':
|
|
return size * 1024; // Convert to MB
|
|
case 'T':
|
|
return size * 1024 * 1024; // Convert to MB
|
|
default:
|
|
return size; // Unknown unit, return as is
|
|
}
|
|
}
|
|
|
|
// Function to create a chart
|
|
function createChart(data) {
|
|
const labels = data.map((entry) => entry.directory);
|
|
const values = data.map((entry) => entry.disk);
|
|
|
|
const ctx = document.getElementById("folderChart").getContext("2d");
|
|
|
|
const chart = new Chart(ctx, {
|
|
type: "bar",
|
|
data: {
|
|
labels: labels,
|
|
datasets: [
|
|
{
|
|
label: "Disk Usage (MB)",
|
|
data: values, // The values are already in MB
|
|
backgroundColor: "#506fd9",
|
|
},
|
|
],
|
|
},
|
|
});
|
|
// console.log(data);
|
|
}
|
|
|
|
// Function to initialize the chart on page load
|
|
function initializeChart() {
|
|
const tableData = extractDataFromTable();
|
|
createChart(tableData);
|
|
RefreshOnBackLink();
|
|
}
|
|
|
|
// go back link
|
|
function RefreshOnBackLink() {
|
|
const goUpElement = document.getElementById('goUp');
|
|
|
|
if (goUpElement) {
|
|
goUpElement.addEventListener('click', async function() {
|
|
const toastMessage = `{{_('Calculating disk usage for parent directory..')}}`;
|
|
const toast = toaster({
|
|
body: toastMessage,
|
|
className: `border-0 text-white bg-primary`,
|
|
});
|
|
|
|
var currentUrl = window.location.href;
|
|
var parts = currentUrl.split('/');
|
|
parts.pop();
|
|
var newUrl = parts.join('/');
|
|
|
|
try {
|
|
const response = await fetch(newUrl);
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch ${newUrl}`);
|
|
}
|
|
|
|
const resultHtml = await response.text();
|
|
|
|
// Parse the HTML string to extract the content of the specific element
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(resultHtml, 'text/html');
|
|
const mainScopeContent = doc.getElementById("main-scope")?.innerHTML;
|
|
|
|
// Replace the content of the element with the ID "main-scope"
|
|
const mainScopeElement = document.getElementById("main-scope");
|
|
if (mainScopeElement) {
|
|
mainScopeElement.innerHTML = mainScopeContent || '';
|
|
}
|
|
|
|
// Update the browser history
|
|
history.pushState({}, '', newUrl);
|
|
|
|
// Initialize the chart after updating the content and URL
|
|
initializeChart();
|
|
|
|
} catch (error) {
|
|
console.error('Error fetching data:', error);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
</script>
|
|
|
|
|
|
<script>
|
|
initializeChart();
|
|
</script>
|
|
|
|
|
|
|
|
{% endblock %}
|