summaryrefslogtreecommitdiffstats
path: root/ogcp
diff options
context:
space:
mode:
Diffstat (limited to 'ogcp')
-rw-r--r--ogcp/static/js/ogcp.js44
-rw-r--r--ogcp/templates/actions/setup.html159
-rw-r--r--ogcp/templates/base.html2
-rw-r--r--ogcp/views.py45
4 files changed, 188 insertions, 62 deletions
diff --git a/ogcp/static/js/ogcp.js b/ogcp/static/js/ogcp.js
index b70b49d..9e6fd4f 100644
--- a/ogcp/static/js/ogcp.js
+++ b/ogcp/static/js/ogcp.js
@@ -341,50 +341,6 @@ function unfoldAll() {
$('#scopes .collapse').collapse('show');
}
-function AddPartition(evt) {
- const target = $($(evt).data("target"));
- const oldrow = target.find("[data-toggle=fieldset-entry]:last");
- const row = oldrow.clone(true, true);
- const elem_id = row.find(".form-control")[0].id;
- const elem_num = parseInt(elem_id.replace(/(.*)-(\d{1,4})/m, '$2')) + 1;
- // Increment WTForms unique identifiers
- row.find('.form-control').each(function() {
- const id = $(this).attr('id').replace(/(.*)-(\d{1,4})-(.*)/, `$1-${elem_num}-$3`);
- $(this).attr('name', id).attr('id', id).val('').removeAttr("checked");
- });
- let part_field = row.find('td').filter(':first')[0];
- part_field.innerText = elem_num + 1;
- row.show();
- oldrow.after(row);
-}
-
-function RemovePartition(evt) {
- const target = $(evt).parent().parent();
- const table = target.parent();
-
- if (table[0].children.length > 1) {
- target.remove();
- // Reassign rows ids
- table.find('tr').each(function(index) {
- function update_references() {
- const id = $(this).attr('id').replace(/(.*)-(\d{1,4})-(.*)/, `$1-${index}-$3`);
- $(this).attr('name', id).attr('id', id);
- }
-
- let part_field = $(this).find('td').filter(':first')[0];
- part_field.innerText = index + 1;
- $(this).find('input').filter(':first').each(update_references);
- $(this).find('.form-control').each(update_references);
- });
- } else {
- table.find('tr').each(function(index) {
- $(this).find('.form-control').each(function() {
- $(this).val('').removeAttr("checked");
- });
- });
- }
-}
-
function checkImageServer() {
const images = $('input:checkbox[form|="imagesForm"][name!="image-server"]')
diff --git a/ogcp/templates/actions/setup.html b/ogcp/templates/actions/setup.html
index fafcb87..934d72f 100644
--- a/ogcp/templates/actions/setup.html
+++ b/ogcp/templates/actions/setup.html
@@ -58,7 +58,7 @@
<td>{{ partition.partition.data }}</td>
<td>{{ partition.part_type(class_="form-control") }}</td>
<td>{{ partition.fs(class_="form-control") }}</td>
- <td>{{ partition.size(class_="form-control") }}</td>
+ <td>{{ partition.size(class_="form-control", oninput="handleEdit(this)") }}</td>
<td>
<button class="btn btn-danger" type="button" onclick="RemovePartition(this)">
{{ _('Remove') }}
@@ -78,4 +78,161 @@
{{ _('Accept') }}
</button>
+<div class="card text-center">
+ <div class="card-header">
+ {{ _('Partition graph') }}
+ </div>
+ <div class="card-body mx-auto col-7">
+ <canvas id="partitionChart" class="mb-2"></canvas>
+ </div>
+</div>
+
+<!-- jQuery -->
+<script src="{{ url_for('static', filename='AdminLTE/plugins/jquery/jquery.min.js') }}"></script>
+<!-- ChartJS -->
+<script src="{{ url_for('static', filename='AdminLTE/plugins/chart.js/Chart.min.js') }}"></script>
+<script>
+ const usedColor = 'rgb(255, 99, 132)';
+ const freeColor = 'rgb(54, 162, 235)';
+ let diskSize = {{ disk_size }};
+
+ let chartConfig = {
+ type: 'doughnut',
+ data: {
+ labels: [],
+ datasets: [
+ {
+ label: 'Partitions',
+ data: [],
+ backgroundColor: [],
+ },
+ ],
+ },
+ options: {
+ responsive: true,
+ plugins: {
+ legend: {
+ position: 'top',
+ },
+ title: {
+ display: true,
+ text: 'Chart.js Doughnut Chart'
+ },
+ },
+ },
+ };
+
+ let partitionChart = new Chart(
+ document.getElementById('partitionChart'),
+ chartConfig,
+ );
+
+ function addPartitionToChart(chart, label, value, bgColor) {
+ chart.data.labels.push(label)
+ chart.data.datasets[0].data.push(value);
+ chart.data.datasets[0].backgroundColor.push(bgColor);
+ }
+
+ function resetChart() {
+ partitionChart.data.labels = [];
+ partitionChart.data.datasets[0].data = [];
+ partitionChart.data.datasets[0].backgroundColor = [];
+ }
+
+ function updateChart() {
+ resetChart();
+
+ let freeSpace = diskSize;
+ let partNum = 1;
+ $('#partitionsTable tr').each(function() {
+ let partitionSize = parseInt($(this).find('td').eq(3).find('input').val().trim());
+ if (isNaN(partitionSize)) {
+ partitionSize = 0;
+ }
+ freeSpace -= partitionSize;
+ addPartitionToChart(partitionChart, 'Partition ' + partNum, partitionSize, usedColor);
+ partNum++;
+ });
+
+ addPartitionToChart(partitionChart, 'Free', Math.max(freeSpace, 0), freeColor);
+ partitionChart.update();
+ }
+
+ $(document).ready(function() {
+ updateChart();
+ });
+
+ function handleEdit(element) {
+ const numericValue = parseInt(element.value);
+
+ if (isNaN(numericValue)) {
+ updateChart();
+ return;
+ }
+
+ let freeSpace = diskSize;
+ $('#partitionsTable tr').each(function() {
+ let partitionSize = parseInt($(this).find('td').eq(3).find('input').val().trim());
+ if (isNaN(partitionSize)) {
+ partitionSize = 0;
+ }
+ freeSpace -= partitionSize;
+ });
+
+ if (freeSpace < 0) {
+ element.value = numericValue + freeSpace;
+ }
+
+ updateChart();
+ }
+
+ function AddPartition(evt) {
+ const target = $($(evt).data("target"));
+ const oldrow = target.find("[data-toggle=fieldset-entry]:last");
+ const row = oldrow.clone(true, true);
+ const elem_id = row.find(".form-control")[0].id;
+ const elem_num = parseInt(elem_id.replace(/(.*)-(\d{1,4})/m, '$2')) + 1;
+ // Increment WTForms unique identifiers
+ row.find('.form-control').each(function() {
+ const id = $(this).attr('id').replace(/(.*)-(\d{1,4})-(.*)/, `$1-${elem_num}-$3`);
+ $(this).attr('name', id).attr('id', id).val('').removeAttr("checked");
+ });
+ let part_field = row.find('td').filter(':first')[0];
+ part_field.innerText = elem_num + 1;
+ row.show();
+ oldrow.after(row);
+
+ updateChart();
+ }
+
+ function RemovePartition(evt) {
+ const target = $(evt).parent().parent();
+ const table = target.parent();
+
+ if (table[0].children.length > 1) {
+ target.remove();
+ // Reassign rows ids
+ table.find('tr').each(function(index) {
+ function update_references() {
+ const id = $(this).attr('id').replace(/(.*)-(\d{1,4})-(.*)/, `$1-${index}-$3`);
+ $(this).attr('name', id).attr('id', id);
+ }
+
+ let part_field = $(this).find('td').filter(':first')[0];
+ part_field.innerText = index + 1;
+ $(this).find('input').filter(':first').each(update_references);
+ $(this).find('.form-control').each(update_references);
+ });
+ } else {
+ table.find('tr').each(function(index) {
+ $(this).find('.form-control').each(function() {
+ $(this).val('').removeAttr("checked");
+ });
+ });
+ }
+ updateChart();
+ }
+
+</script>
+
{% endblock %}
diff --git a/ogcp/templates/base.html b/ogcp/templates/base.html
index 0099c27..cd030e8 100644
--- a/ogcp/templates/base.html
+++ b/ogcp/templates/base.html
@@ -108,7 +108,7 @@
<!-- ChartJS -->
<script src="{{ url_for('static', filename='AdminLTE/plugins/chart.js/Chart.min.js') }}"></script>
- <script src="{{ url_for('static', filename='js/ogcp.js') }}?v=15"></script>
+ <script src="{{ url_for('static', filename='js/ogcp.js') }}?v=16"></script>
<script>
// error messages
diff --git a/ogcp/views.py b/ogcp/views.py
index 8b544eb..007ca91 100644
--- a/ogcp/views.py
+++ b/ogcp/views.py
@@ -682,6 +682,7 @@ def action_setup_select():
@login_required
def action_setup_show():
args = request.args.copy()
+ disk_size = None
default_disk = 1
selected_disk = int(args.pop('disk', default_disk))
@@ -694,35 +695,47 @@ def action_setup_show():
ips = set(args['ips'].split(' '))
base_client = args['selected_client']
- try:
- db_partitions = get_client_setup(base_client)
- except ServerError:
- return ogserver_down('commands')
- except ServerErrorCode:
- return ogserver_error('commands')
- if not db_partitions:
+ for ip in ips:
+ try:
+ setup_data = get_client_setup(ip)
+ except ServerError:
+ return ogserver_down('commands')
+ except ServerErrorCode:
+ return ogserver_error('commands')
+
+ filtered_partitions = [p for p in setup_data
+ if p.get('disk') == selected_disk]
+ if not filtered_partitions:
+ continue
+
+ if ip == base_client:
+ target_partitions = filtered_partitions
+
+ client_disk_size = filtered_partitions[0]['size'] // 1024
+ if disk_size:
+ disk_size = min(disk_size, client_disk_size)
+ else:
+ disk_size = client_disk_size
+
+ if not target_partitions:
flash(_('Partition information is not available. Boot client in ogLive mode to obtain it'), category='error')
return redirect(url_for('commands'))
- filtered_partitions = [p for p in db_partitions
- if p.get('disk') == selected_disk]
disk_partition = 0
- disks = [d.get('disk') for d in db_partitions
+ disks = [d.get('disk') for d in target_partitions
if d.get('partition') == disk_partition]
form = SetupForm()
form.ips.data = ips_str
form.disk.data = selected_disk
# If partition table is empty, set MSDOS
- form.disk_type.data = filtered_partitions[0]['code'] or 1
-
- disk_size = filtered_partitions[0]['size'] // 1024
+ form.disk_type.data = target_partitions[0]['code'] or 1
- # Make form.partition length equal to (filtered_partitions - 1) length
- diff = len(filtered_partitions) - 1 - len(form.partitions)
+ # Make form.partition length equal to (target_partitions - 1) length
+ diff = len(target_partitions) - 1 - len(form.partitions)
[form.partitions.append_entry() for unused in range(diff)]
- for partition, db_part in zip(form.partitions, filtered_partitions[1:]):
+ for partition, db_part in zip(form.partitions, target_partitions[1:]):
partition.partition.data = str(db_part['partition'])
partition.part_type.data = db_part['code']
partition.fs.data = db_part['filesystem']