mirror of https://git.48k.eu/ogcp
Add new partition button in setup action
This patch adds a way to add a new partition to the setup.html template. This button opens a modal dialog with a new form and calls a new endpoint to create the new partition (this endpoint does nothing, it's needed to be implemented in the future). I've followed the initial design for this template, with one form per each partition, so every button will call a function and reload the page. It's possible to do all actions at once, but that will require a rework of this, to do that we can just define an unique form in the whole html, remove all the "Modify" buttons and add just one "Apply" button at the end. But maybe that option is a lot complex in the backend because will require to validate all the changes at once. This patch also improves the setup.html form without using flask-bootstrap and rendering the form in the template directly with the bootstrap4 classes.multi-ogserver
parent
288654722d
commit
42dc44323e
|
@ -38,6 +38,22 @@ class PartitionForm(FlaskForm):
|
|||
modify = SubmitField(label=_('Modify'))
|
||||
delete = SubmitField(label=_('Delete'))
|
||||
|
||||
|
||||
class NewPartitionForm(FlaskForm):
|
||||
ips = HiddenField()
|
||||
part_type = SelectField(label=_('Type'),
|
||||
choices=[('LINUX', 'Linux'),
|
||||
('NTFS', 'NTFS'),
|
||||
('EMPTY', 'Empty')])
|
||||
fs = SelectField(label=_('Filesystem'),
|
||||
choices=[('EXT4', 'EXT4'),
|
||||
('NTFS', 'NTFS'),
|
||||
('DISK', 'Disk'),
|
||||
('EMPTY', 'Empty')])
|
||||
size = IntegerField(label=_('Size (KB)'))
|
||||
create = SubmitField(label=_('Create'))
|
||||
|
||||
|
||||
class HardwareForm(FlaskForm):
|
||||
ips = HiddenField()
|
||||
refresh = SubmitField(label=_('Refresh'))
|
||||
|
|
|
@ -1,19 +1,82 @@
|
|||
{% extends 'commands.html' %}
|
||||
{% import "bootstrap/wtf.html" as wtf %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1 class="m-5">{{_('Partition and Format')}}</h1>
|
||||
|
||||
{% for form in forms %}
|
||||
<table class="table">
|
||||
<thead class="text-center">
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Filesytem</th>
|
||||
<th>Size (KB)</th>
|
||||
<th>Format?</th>
|
||||
<th colspan="2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
{{ wtf.quick_form(form,
|
||||
method='post',
|
||||
form_type='inline',
|
||||
extra_classes='mx-5 pb-3',
|
||||
button_map={'modify': 'primary',
|
||||
'delete': 'danger'}) }}
|
||||
<tbody>
|
||||
{% for form in forms %}
|
||||
<form class="form-inline" method="POST">
|
||||
<tr>
|
||||
{{ form.hidden_tag() }}
|
||||
<td>{{ form.part_type(class_="form-control") }}</td>
|
||||
<td>{{ form.fs(class_="form-control") }}</td>
|
||||
<td>{{ form.size(class_="form-control") }}</td>
|
||||
<td>{{ form.format_partition(class_="form-control") }}</td>
|
||||
<td>{{ form.modify(class_="form-control btn-primary") }}</td>
|
||||
<td>{{ form.delete(class_="form-control btn-danger") }}</td>
|
||||
</tr>
|
||||
</form>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% endfor %}
|
||||
<button class="btn btn-primary" data-toggle="modal" data-target="#newPartitionModal">
|
||||
{{ _('Add a new Partition') }}
|
||||
</button>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="newPartitionModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form class="form" method="POST">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">{{ _('Create a new partition') }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ new_partition_form.hidden_tag() }}
|
||||
|
||||
<div class="form-group">
|
||||
<label for="{{ new_partition_form.part_type.id }}">{{ new_partition_form.part_type.label }}</label>
|
||||
{{ new_partition_form.part_type(class_="form-control") }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ new_partition_form.fs.id }}">{{ new_partition_form.fs.label }}</label>
|
||||
{{ new_partition_form.fs(class_="form-control") }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ new_partition_form.size.id }}">{{ new_partition_form.size.label }}</label>
|
||||
{% if new_partition_form.size.errors %}
|
||||
{{ new_partition_form.size(class_="form-control is-invalid") }}
|
||||
{% else %}
|
||||
{{ new_partition_form.size(class_="form-control") }}
|
||||
{% endif %}
|
||||
{% for error in new_partition_form.size.errors %}
|
||||
<div class="invalid-feedback">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{{ new_partition_form.create(class_="btn btn-primary") }}
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
<!-- ChartJS -->
|
||||
<script src="{{ url_for('static', filename='AdminLTE/plugins/chart.js/Chart.min.js') }}"></script>
|
||||
|
||||
<script src="{{ url_for('static', filename='js/ogcp.js') }}"></script>
|
||||
|
||||
<script>
|
||||
// error messages
|
||||
{% for category, message in get_flashed_messages(with_categories=True) %}
|
||||
|
|
|
@ -9,9 +9,9 @@ from flask import (
|
|||
g, render_template, url_for, flash, redirect, request, jsonify, make_response
|
||||
)
|
||||
from ogcp.forms.action_forms import (
|
||||
WOLForm, PartitionForm, ClientDetailsForm, HardwareForm, SessionForm,
|
||||
ImageRestoreForm, ImageCreateForm, SoftwareForm, BootModeForm, RoomForm,
|
||||
DeleteRoomForm
|
||||
WOLForm, PartitionForm, NewPartitionForm, ClientDetailsForm, HardwareForm,
|
||||
SessionForm, ImageRestoreForm, ImageCreateForm, SoftwareForm, BootModeForm,
|
||||
RoomForm, DeleteRoomForm
|
||||
)
|
||||
from flask_login import (
|
||||
current_user, LoginManager,
|
||||
|
@ -226,12 +226,19 @@ def action_wol():
|
|||
|
||||
@app.route('/action/setup', methods=['GET'])
|
||||
@login_required
|
||||
def action_setup_show():
|
||||
ips = parse_ips(request.args.to_dict())
|
||||
def action_setup_show(ips=None, new_partition_form=None):
|
||||
if not ips:
|
||||
ips = parse_ips(request.args.to_dict())
|
||||
|
||||
db_partitions = get_client_setup(ips)
|
||||
forms = [PartitionForm() for _ in db_partitions]
|
||||
forms = list(forms)
|
||||
|
||||
if not new_partition_form:
|
||||
new_partition_form = NewPartitionForm()
|
||||
new_partition_form.ips.data = " ".join(ips)
|
||||
new_partition_form.create.render_kw = {"formaction": url_for('action_setup_create')}
|
||||
|
||||
for form, db_part in zip(forms, db_partitions):
|
||||
form.ips.data = " ".join(ips)
|
||||
form.disk.data = db_part['disk']
|
||||
|
@ -249,8 +256,25 @@ def action_setup_show():
|
|||
scopes, _clients = get_scopes(ips)
|
||||
return render_template('actions/setup.html',
|
||||
forms=forms,
|
||||
new_partition_form=new_partition_form,
|
||||
scopes=scopes)
|
||||
|
||||
@app.route('/action/setup/create', methods=['POST'])
|
||||
@login_required
|
||||
def action_setup_create():
|
||||
form = NewPartitionForm(request.form)
|
||||
ips = form.ips.data.split(' ')
|
||||
|
||||
if form.validate():
|
||||
# TODO: create the real partition
|
||||
flash(_('Partition created successfully'), category='info')
|
||||
return redirect(url_for('action_setup_show', ips=ips))
|
||||
|
||||
flash(_('Invalid partition configuration'), category='error')
|
||||
# This return will maintain the new partition form state, but will break
|
||||
# the F5 behavior in the browser
|
||||
return action_setup_show(ips, form)
|
||||
|
||||
@app.route('/action/setup/modify', methods=['POST'])
|
||||
@login_required
|
||||
def action_setup_modify():
|
||||
|
|
Loading…
Reference in New Issue