ogcp: add move client to scopes management

Add front end for the client/move REST API.
Enable the move of multiple clients selected from the sidebar of
Scopes Management.
Show the target of the move operation as a list of paths in a
dropdown widget in the form. Each path will be structured as:
Server/Center/Room
The path will also contain folders if they are present.
master
Alejandro Sirgo Rica 2024-06-17 12:52:32 +02:00
parent 664ad2bf7b
commit 4a74de1064
4 changed files with 94 additions and 1 deletions

View File

@ -142,6 +142,11 @@ class ClientDetailsForm(FlaskForm):
boot = SelectField(label=_l('Boot Mode'), validate_choice=False)
submit = SubmitField(label=_l('Submit'))
class ClientMoveForm(FlaskForm):
ips = HiddenField()
scopes = SelectField(label=_l('Scopes'), validate_choice=False)
submit = SubmitField(label=_l('Submit'))
class ImportClientsForm(FlaskForm):
server = HiddenField()
room = SelectField(label=_l('Room'))

View File

@ -0,0 +1,25 @@
{% extends 'scopes.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% import "macros.html" as macros %}
{% set sidebar_state = 'disabled' %}
{% set btn_back = true %}
{% block nav_client %} active {% endblock %}
{% block nav_client_move %} active {% endblock %}
{% block content %}
{% set ip_list = form.ips.data.split(' ') %}
{% set ip_count = ip_list | length %}
<h1 class="m-5">
{{ _('Move %(ip_count)d client(s)', ip_count=ip_count) }}
</h1>
{{ macros.cmd_selected_clients(selected_clients) }}
{{ wtf.quick_form(form,
method='post',
button_map={'submit': 'primary'},
extra_classes="mx-5") }}
{% endblock %}

View File

@ -26,6 +26,8 @@
form="scopesForm" formaction="{{ url_for('action_client_add') }}" formmethod="get">
<input class="btn btn-light dropdown-item {% block nav_client_update %}{% endblock %}" type="submit" value="{{ _('Edit client') }}"
form="scopesForm" formaction="{{ url_for('action_client_update') }}" formmethod="get">
<input class="btn btn-light dropdown-item {% block nav_client_move %}{% endblock %}" type="submit" value="{{ _('Move client') }}"
form="scopesForm" formaction="{{ url_for('action_client_move') }}" formmethod="get">
<input class="btn btn-light dropdown-item {% block nav_clients_import %}{% endblock %}" type="submit" value="{{ _('Import clients') }}"
form="scopesForm" formaction="{{ url_for('action_clients_import_get') }}" formmethod="get">
<input class="btn btn-light dropdown-item {% block nav_client_delete %}{% endblock %}" type="submit" value="{{ _('Delete client') }}"

View File

@ -13,7 +13,8 @@ from ogcp.forms.action_forms import (
SessionForm, ImageRestoreForm, ImageCreateForm, SoftwareForm, BootModeForm,
RoomForm, DeleteRoomForm, CenterForm, DeleteCenterForm, OgliveForm,
GenericForm, SelectClientForm, ImageUpdateForm, ImportClientsForm,
ServerForm, DeleteRepositoryForm, RepoForm, FolderForm, CacheForm
ServerForm, DeleteRepositoryForm, RepoForm, FolderForm, CacheForm,
ClientMoveForm
)
from flask_login import (
current_user, LoginManager,
@ -1574,6 +1575,66 @@ def action_client_add():
return render_template('actions/client_add.html', form=form,
parent="scopes.html", scopes=scopes)
def build_client_move_choices(scopes, choices, path):
for scope in scopes.get('scope'):
new_path = f'{path}{scope.get("name")}/'
if scope.get('type') == 'room':
choices.append((f'{scope["id"]} 0', new_path))
for room_child in scope.get('scope'):
if room_child.get('type') == 'folder':
choices.append(
(f'{scope["id"]} {room_child["id"]}',
f'{new_path}{room_child.get("name")}/')
)
else:
build_client_move_choices(scope, choices, new_path)
def get_client_move_choices(scopes):
choices = []
build_client_move_choices(scopes, choices, '')
return choices
@app.route('/action/client/move', methods=['GET', 'POST'])
@login_required
def action_client_move():
form = ClientMoveForm(request.form)
if request.method == 'POST':
ips = form.ips.data.split(' ')
if not validate_elements(ips):
return redirect(url_for('scopes'))
room_id, folder_id = form.scopes.data.split(' ')
payload = {"clients": ips,
"room": int(room_id),
"folder_id": int(folder_id)}
server = get_server_from_clients(ips)
r = server.post('/client/move', payload)
if r.status_code != requests.codes.ok:
flash(_('ogServer: error moving client'),
category='error')
else:
flash(_('Client moved successfully'),
category='info')
return redirect(url_for('scopes'))
else:
ips = parse_elements(request.args.to_dict())
form.ips.data = " ".join(ips)
if not validate_elements(ips):
return redirect(url_for('scopes'))
scopes, clients = get_scopes(set(ips))
form.scopes.choices = get_client_move_choices(scopes)
selected_clients = list(get_selected_clients(scopes['scope']).items())
return render_template('actions/client_move.html', form=form,
selected_clients=selected_clients,
scopes=scopes)
PLACEHOLDER_TEXT = '''host example1 { hardware ethernet 94:c6:91:a6:25:1a; fixed-address 10.141.10.100; }
host example2 { hardware ethernet 94:c6:91:a6:25:1b; fixed-address 10.141.10.101; }
host example3 { hardware ethernet 94:c6:91:a6:25:1c; fixed-address 10.141.10.102; }