From 285843634162860b1ba19f71834f06f4fca54583 Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Fri, 1 Dec 2023 15:55:15 +0100 Subject: src: add menu to manage repos The menu includes a list of the repos of each server. The user can select a server or a repo to make changes. As of now, the only action possible is to add a repo to selected server. The work contained in this commit can be structured in: 1. Add the repos menu: - Add a 'repos' button in the menus bar (base.html). - Add repos.html template to create the management repos menu. - In ogcp.js, add function to store in browser's local storage which elements of the sidebar are uncollapsed. This saves the sidebar state after a page refresh. - Add manage_repos() in views.py 2. Allow to add a repo: - Add template with form to add a repo (repos_details.html) - Create RepoForm(FlaskForm) in action_forms.py - Add repo_add_get() and repo_add_post() in views.py --- ogcp/forms/action_forms.py | 6 ++++ ogcp/static/js/ogcp.js | 19 ++++++++++ ogcp/templates/actions/repos_details.html | 16 +++++++++ ogcp/templates/base.html | 3 ++ ogcp/templates/repos.html | 59 +++++++++++++++++++++++++++++++ ogcp/views.py | 43 +++++++++++++++++++++- 6 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 ogcp/templates/actions/repos_details.html create mode 100644 ogcp/templates/repos.html diff --git a/ogcp/forms/action_forms.py b/ogcp/forms/action_forms.py index 6f3f4b9..0a9bd32 100644 --- a/ogcp/forms/action_forms.py +++ b/ogcp/forms/action_forms.py @@ -98,6 +98,12 @@ class ImageRestoreForm(FlaskForm): choices=[('TIPTORRENT', 'TIPTORRENT')]) restore = SubmitField(label=_l('Restore')) +class RepoForm(FlaskForm): + server = HiddenField() + name = StringField(label=_l('Name')) + ip = StringField(label=_l('IP')) + create = SubmitField(label=_l('Create')) + class ClientDetailsForm(FlaskForm): server = HiddenField() name = StringField(label=_l('Name')) diff --git a/ogcp/static/js/ogcp.js b/ogcp/static/js/ogcp.js index 6473373..5028993 100644 --- a/ogcp/static/js/ogcp.js +++ b/ogcp/static/js/ogcp.js @@ -136,6 +136,25 @@ function keepSelectedClients() { }); } +function keepReposTreeState() { + const repos_tree = $('#repos-list .collapse') + + repos_tree.on('hidden.bs.collapse', function (event) { + event.stopPropagation(); + localStorage.removeItem(this.id); + }); + repos_tree.on('shown.bs.collapse', function (event) { + event.stopPropagation(); + localStorage.setItem(this.id, 'show'); + }); + + repos_tree.each(function () { + if (localStorage.getItem(this.id) == 'show') { + $(this).collapse('show'); + } + }); +} + function keepScopesTreeState() { const scopes_tree = $('#scopes .collapse') diff --git a/ogcp/templates/actions/repos_details.html b/ogcp/templates/actions/repos_details.html new file mode 100644 index 0000000..32b96bf --- /dev/null +++ b/ogcp/templates/actions/repos_details.html @@ -0,0 +1,16 @@ +{% extends 'repos.html' %} +{% import "bootstrap/wtf.html" as wtf %} +{% set btn_back = true %} + +{% block nav_repos %} active{% endblock %} +{% block nav_repos_details %} active{% endblock %} +{% block nav_repos_add %}active{% endblock %} +{% block content %} + +

{{_('Repo details')}}

+ +{{ wtf.quick_form(form, + method='post', + button_map={'create': 'primary'}, + extra_classes="mx-5") }} +{% endblock %} diff --git a/ogcp/templates/base.html b/ogcp/templates/base.html index a7e8b94..8ef8f3a 100644 --- a/ogcp/templates/base.html +++ b/ogcp/templates/base.html @@ -37,6 +37,9 @@ + diff --git a/ogcp/templates/repos.html b/ogcp/templates/repos.html new file mode 100644 index 0000000..881057b --- /dev/null +++ b/ogcp/templates/repos.html @@ -0,0 +1,59 @@ +{% extends 'base.html' %} + +{% block nav_repos %}active{% endblock %} + +{% block container %} +
+ +
+ {{ super() }} + +{% endblock %} + +{% block sidebar %} + + +{% endblock %} + +{% block commands %} + + + {% if btn_back %} + + {% endif %} +{% endblock %} diff --git a/ogcp/views.py b/ogcp/views.py index eb6bfec..fb7d6bb 100644 --- a/ogcp/views.py +++ b/ogcp/views.py @@ -13,7 +13,7 @@ from ogcp.forms.action_forms import ( SessionForm, ImageRestoreForm, ImageCreateForm, SoftwareForm, BootModeForm, RoomForm, DeleteRoomForm, CenterForm, DeleteCenterForm, OgliveForm, GenericForm, SelectClientForm, ImageUpdateForm, ImportClientsForm, - ServerForm, DeleteRepositoryForm + ServerForm, DeleteRepositoryForm, RepoForm ) from flask_login import ( current_user, LoginManager, @@ -1475,6 +1475,47 @@ def images(): return render_template('images.html', responses=responses) +@app.route('/repos/', methods=['GET']) +@login_required +def manage_repos(): + responses = multi_request('get', '/repositories') + return render_template('repos.html', repos_resp=responses) + +@app.route('/repo/add', methods=['GET']) +@login_required +def repo_add_get(): + form = RepoForm() + params = request.args.to_dict() + if not params.get('selected-server'): + flash(_('Please, select a server'), category='error') + return redirect(url_for('manage_repos')) + + form.server.data = params['selected-server'] + form.create.render_kw = {"formaction": url_for('repo_add_post')} + + responses = multi_request('get', '/repositories') + return render_template('actions/repos_details.html', form=form, + repos_resp=responses) + +@app.route('/repo/add', methods=['POST']) +@login_required +def repo_add_post(): + form = RepoForm(request.form) + if not form.validate(): + flash(form.errors, category='error') + return redirect(url_for('manage_repos')) + payload = {"name": form.name.data, + "ip": form.ip.data, + "center": 1} + server = get_server_from_ip_port(form.server.data) + r = server.post('/repository/add', payload) + if r.status_code != requests.codes.ok: + flash(_('ogServer: error adding repo'), + category='error') + else: + flash(_('Repo added successfully'), category='info') + return redirect(url_for("manage_repos")) + @app.route('/servers/', methods=['GET']) @login_required def manage_servers(): -- cgit v1.2.3-18-g5258