summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlejandro Sirgo Rica <asirgo@soleta.eu>2024-06-17 12:52:32 +0200
committerAlejandro Sirgo Rica <asirgo@soleta.eu>2024-06-17 14:03:00 +0200
commit4a74de1064c6cf0ef9ce10934efa24b63e661083 (patch)
tree5da99ed64437aaee27b037313f62940853905930
parent664ad2bf7bad8014c024ce1b0f247f394a2fcaa4 (diff)
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.
-rw-r--r--ogcp/forms/action_forms.py5
-rw-r--r--ogcp/templates/actions/client_move.html25
-rw-r--r--ogcp/templates/scopes.html2
-rw-r--r--ogcp/views.py63
4 files changed, 94 insertions, 1 deletions
diff --git a/ogcp/forms/action_forms.py b/ogcp/forms/action_forms.py
index 718bd3d..9e3a9f6 100644
--- a/ogcp/forms/action_forms.py
+++ b/ogcp/forms/action_forms.py
@@ -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'))
diff --git a/ogcp/templates/actions/client_move.html b/ogcp/templates/actions/client_move.html
new file mode 100644
index 0000000..d9bcaac
--- /dev/null
+++ b/ogcp/templates/actions/client_move.html
@@ -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 %}
diff --git a/ogcp/templates/scopes.html b/ogcp/templates/scopes.html
index 0dde6a6..a96ae62 100644
--- a/ogcp/templates/scopes.html
+++ b/ogcp/templates/scopes.html
@@ -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') }}"
diff --git a/ogcp/views.py b/ogcp/views.py
index af65ddf..0133954 100644
--- a/ogcp/views.py
+++ b/ogcp/views.py
@@ -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; }