From 31b1e920772ce6dd56f3f56b5a882c2f71333c13 Mon Sep 17 00:00:00 2001 From: "Jose M. Guisado" Date: Thu, 27 Jan 2022 16:51:35 +0100 Subject: Add confirmation page when deleting image User can confirm when deleting an image by double checking the information displayed on this page. Adds a new optional field in GenericForm: 'ids'. Used when dealing with ids instead of ips. --- ogcp/forms/action_forms.py | 1 + ogcp/templates/actions/delete_image.html | 20 +++++ ogcp/templates/images.html | 2 +- ogcp/translations/es/LC_MESSAGES/messages.po | 110 ++++++++++++++------------- ogcp/views.py | 36 ++++++--- 5 files changed, 106 insertions(+), 63 deletions(-) create mode 100644 ogcp/templates/actions/delete_image.html diff --git a/ogcp/forms/action_forms.py b/ogcp/forms/action_forms.py index 09197d5..a2cac37 100644 --- a/ogcp/forms/action_forms.py +++ b/ogcp/forms/action_forms.py @@ -17,6 +17,7 @@ from flask_babel import _ class GenericForm(FlaskForm): ips = HiddenField() + ids = HiddenField() submit = SubmitField(label=_l('Submit')) diff --git a/ogcp/templates/actions/delete_image.html b/ogcp/templates/actions/delete_image.html new file mode 100644 index 0000000..608375f --- /dev/null +++ b/ogcp/templates/actions/delete_image.html @@ -0,0 +1,20 @@ +{% extends 'images.html' %} +{% import "bootstrap/wtf.html" as wtf %} + +{% block content %} + +{{ args }} + +

+ {{ _('Delete image %(image_name)s', image_name=image_name) }} +

+ +{{ wtf.quick_form(form, + action=url_for('action_image_delete'), + method='post', + button_map={'submit': 'primary'}, + extra_classes="mx-5") }} + +{% endblock %} + + diff --git a/ogcp/templates/images.html b/ogcp/templates/images.html index e198e6c..2a67e58 100644 --- a/ogcp/templates/images.html +++ b/ogcp/templates/images.html @@ -28,6 +28,6 @@ + form="imagesForm" formaction="{{ url_for('action_image_delete') }}" formmethod="get"> {% endblock %} diff --git a/ogcp/translations/es/LC_MESSAGES/messages.po b/ogcp/translations/es/LC_MESSAGES/messages.po index 4918bdc..33f0e97 100644 --- a/ogcp/translations/es/LC_MESSAGES/messages.po +++ b/ogcp/translations/es/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 1.0.0\n" "Report-Msgid-Bugs-To: opengnsys@soleta.eu\n" -"POT-Creation-Date: 2022-01-20 13:33+0100\n" +"POT-Creation-Date: 2022-01-27 15:17+0100\n" "PO-Revision-Date: 2021-12-23 16:47+0100\n" "Last-Translator: Soleta Networks \n" "Language: es\n" @@ -102,7 +102,7 @@ msgstr "ogServer: error al reiniciar cliente" msgid "Client rebooted successfully" msgstr "Cliente reiniciado con éxito" -#: views.py:835 views.py:967 +#: views.py:835 views.py:968 msgid "OgServer replied with a non ok status code" msgstr "OgServer respondió con un código de estado de error" @@ -142,182 +142,186 @@ msgstr "El servidor respondió con el código de error al eliminar la sala." msgid "Room deleted successfully" msgstr "Sala eliminada con éxito" -#: views.py:969 -msgid "Delete client request processed successfully" -msgstr "Solicitud de eliminar cliente procesada con éxito" +#: views.py:970 +msgid "Image deletion request sent successfully" +msgstr "La imagen ha sido borrada" -#: forms/action_forms.py:20 forms/action_forms.py:28 forms/action_forms.py:137 -#: forms/action_forms.py:142 forms/action_forms.py:151 -#: forms/action_forms.py:156 +#: views.py:977 +msgid "Please select one image to delete" +msgstr "Solo puede seleccionar una imagen para borrar" + +#: forms/action_forms.py:21 forms/action_forms.py:29 forms/action_forms.py:138 +#: forms/action_forms.py:143 forms/action_forms.py:152 +#: forms/action_forms.py:157 msgid "Submit" msgstr "Enviar" -#: forms/action_forms.py:25 forms/action_forms.py:33 forms/action_forms.py:63 +#: forms/action_forms.py:26 forms/action_forms.py:34 forms/action_forms.py:64 #: templates/actions/hardware.html:14 msgid "Type" msgstr "Tipo" -#: forms/action_forms.py:31 forms/action_forms.py:76 forms/action_forms.py:87 +#: forms/action_forms.py:32 forms/action_forms.py:77 forms/action_forms.py:88 msgid "Partition" msgstr "Partición" -#: forms/action_forms.py:49 +#: forms/action_forms.py:50 msgid "Filesystem" msgstr "Sistema de ficheros" -#: forms/action_forms.py:57 +#: forms/action_forms.py:58 msgid "Size (KB)" msgstr "Tamaño (KB)" -#: forms/action_forms.py:58 +#: forms/action_forms.py:59 msgid "Format" msgstr "Formatear" -#: forms/action_forms.py:72 templates/commands.html:25 +#: forms/action_forms.py:73 templates/commands.html:25 msgid "Refresh" msgstr "Actualizar" -#: forms/action_forms.py:77 +#: forms/action_forms.py:78 msgid "View" msgstr "Vista" -#: forms/action_forms.py:78 +#: forms/action_forms.py:79 msgid "Update" msgstr "Actualizar" -#: forms/action_forms.py:82 +#: forms/action_forms.py:83 msgid "Session" msgstr "Sesión" -#: forms/action_forms.py:83 +#: forms/action_forms.py:84 msgid "Run" msgstr "Lanzar" -#: forms/action_forms.py:88 +#: forms/action_forms.py:89 msgid "Image" msgstr "Imagen" -#: forms/action_forms.py:89 +#: forms/action_forms.py:90 msgid "Method" msgstr "Método" -#: forms/action_forms.py:91 +#: forms/action_forms.py:92 msgid "Restore" msgstr "Restaurar" -#: forms/action_forms.py:94 forms/action_forms.py:160 +#: forms/action_forms.py:95 forms/action_forms.py:161 msgid "Name" msgstr "Nombre" -#: forms/action_forms.py:95 +#: forms/action_forms.py:96 msgid "IP" msgstr "IP" -#: forms/action_forms.py:96 +#: forms/action_forms.py:97 msgid "MAC" msgstr "MAC" -#: forms/action_forms.py:97 +#: forms/action_forms.py:98 msgid "Serial Number" msgstr "Número de serie" -#: forms/action_forms.py:98 forms/action_forms.py:149 +#: forms/action_forms.py:99 forms/action_forms.py:150 msgid "Netmask" msgstr "Máscara de red" -#: forms/action_forms.py:99 forms/action_forms.py:122 +#: forms/action_forms.py:100 forms/action_forms.py:123 msgid "ogLive" msgstr "ogLive" -#: forms/action_forms.py:101 +#: forms/action_forms.py:102 msgid "Remote" msgstr "Remoto" -#: forms/action_forms.py:102 +#: forms/action_forms.py:103 msgid "Maintenance" msgstr "Mantenimiento" -#: forms/action_forms.py:103 +#: forms/action_forms.py:104 msgid "Interface" msgstr "Interfaz" -#: forms/action_forms.py:107 +#: forms/action_forms.py:108 msgid "Driver" msgstr "Controlador" -#: forms/action_forms.py:109 +#: forms/action_forms.py:110 msgid "Repository" msgstr "Repositorio" -#: forms/action_forms.py:111 forms/action_forms.py:154 +#: forms/action_forms.py:112 forms/action_forms.py:155 msgid "Room" msgstr "Sala" -#: forms/action_forms.py:112 +#: forms/action_forms.py:113 msgid "Boot Mode" msgstr "Modo de arranque" -#: forms/action_forms.py:113 forms/action_forms.py:131 +#: forms/action_forms.py:114 forms/action_forms.py:132 msgid "Create" msgstr "Crear" -#: forms/action_forms.py:117 +#: forms/action_forms.py:118 msgid "Boot mode" msgstr "Modo de arranque" -#: forms/action_forms.py:118 forms/action_forms.py:123 +#: forms/action_forms.py:119 forms/action_forms.py:124 msgid "Ok" msgstr "OK" -#: forms/action_forms.py:127 +#: forms/action_forms.py:128 msgid "OS" msgstr "SO" -#: forms/action_forms.py:128 +#: forms/action_forms.py:129 msgid "Image name" msgstr "Nombre de la imagen" -#: forms/action_forms.py:130 +#: forms/action_forms.py:131 msgid "Description" msgstr "Descripción" -#: forms/action_forms.py:134 +#: forms/action_forms.py:135 msgid "Center name" msgstr "Nombre del centro" -#: forms/action_forms.py:136 +#: forms/action_forms.py:137 msgid "Comment" msgstr "Comentario" -#: forms/action_forms.py:140 forms/action_forms.py:145 +#: forms/action_forms.py:141 forms/action_forms.py:146 msgid "Center" msgstr "Centro" -#: forms/action_forms.py:147 +#: forms/action_forms.py:148 msgid "Room name" msgstr "Nombre de la sala" -#: forms/action_forms.py:159 +#: forms/action_forms.py:160 msgid "Id" msgstr "Id" -#: forms/action_forms.py:161 +#: forms/action_forms.py:162 msgid "Size (GiB)" msgstr "Tamaño (GiB)" -#: forms/action_forms.py:162 +#: forms/action_forms.py:163 msgid "Datasize (GiB)" msgstr "Tamaño de los datos (GiB)" -#: forms/action_forms.py:163 +#: forms/action_forms.py:164 msgid "Modified" msgstr "Modificado" -#: forms/action_forms.py:164 +#: forms/action_forms.py:165 msgid "Permissions" msgstr "Permisos" -#: forms/action_forms.py:165 +#: forms/action_forms.py:166 msgid "Software id" msgstr "ID de software" @@ -506,6 +510,11 @@ msgstr "Formulario para eliminar un centro" msgid "Delete %(ip_count)d client(s)" msgstr "Elimina %(ip_count)d cliente(s)" +#: templates/actions/delete_image.html:9 +#, python-format +msgid "Delete image %(image_name)s" +msgstr "Borrar imagen %(image_name)s" + #: templates/actions/delete_room.html:6 msgid "Delete room form" msgstr "Formulario para eliminar una sala" @@ -559,4 +568,3 @@ msgstr "Inventario de software" #: templates/actions/legacy/log.html:6 msgid "Client log" msgstr "Registro de clientes" - diff --git a/ogcp/views.py b/ogcp/views.py index 3c587d2..a5e9573 100644 --- a/ogcp/views.py +++ b/ogcp/views.py @@ -953,21 +953,35 @@ def action_image_info(): return render_template('actions/image_details.html', form=form) -@app.route('/action/image/delete', methods=['POST']) +@app.route('/action/image/delete', methods=['GET', 'POST']) @login_required def action_image_delete(): - ids = parse_elements(request.form.to_dict()) - if not validate_elements(ids, max_len=1): + form = GenericForm(request.form) + if request.method == 'POST': + ids = form.ids.data.split(' ') + if not validate_elements(ids, max_len=1): + return redirect(url_for('images')) + id = ids.pop() + payload = {'image': id} + r = g.server.post('/image/delete', payload) + if r.status_code != requests.codes.ok: + flash(_('OgServer replied with a non ok status code'), category='error') + else: + flash(_('Image deletion request sent successfully'), category='info') return redirect(url_for('images')) - - id = ids.pop() - payload = {'image': id} - r = g.server.post('/image/delete', payload) - if r.status_code != requests.codes.ok: - flash(_('OgServer replied with a non ok status code'), category='error') else: - flash(_('Delete client request processed successfully'), category='info') - return redirect(url_for('images')) + images = [(name, imgid) for name, imgid in request.args.to_dict().items() if name != "csrf_token"] + if not validate_elements(images, max_len=1): + return redirect(url_for('images')) + image_name, image_id = images[0] + r = g.server.get('/images') + form.ids.data = image_id + if not validate_elements(images, max_len=1): + flash(_('Please select one image to delete'), category='error') + return redirect(url_for('images')) + return render_template('actions/delete_image.html', form=form, + image_name=image_name.split('_', 1)[0], image_id=image_id, + images=r.json()['images']) @app.route('/action/log', methods=['GET']) @login_required -- cgit v1.2.3-18-g5258