diff --git a/src/webui/service/device/forms.py b/src/webui/service/device/forms.py index 3d728ade13205edb8a0febd649f74992e3477ff2..3aae96cc05bacb31567e3e0b8f6cda2d5e0ddc88 100644 --- a/src/webui/service/device/forms.py +++ b/src/webui/service/device/forms.py @@ -16,7 +16,7 @@ from flask_wtf import FlaskForm from wtforms import StringField, SelectField, TextAreaField, SubmitField, BooleanField, Form from wtforms.validators import DataRequired, Length, NumberRange, Regexp, ValidationError -from common.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum +from common.proto.context_pb2 import DeviceOperationalStatusEnum from webui.utils.form_validators import key_value_validator class AddDeviceForm(FlaskForm): @@ -41,4 +41,18 @@ class AddDeviceForm(FlaskForm): def validate_operational_status(form, field): if field.data not in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_number: - raise ValidationError('The operational status value selected is incorrect!') \ No newline at end of file + raise ValidationError('The operational status value selected is incorrect!') + +class ConfigForm(FlaskForm): + device_key_config = StringField('Key configuration') + device_value_config = StringField('Value configuration') + submit = SubmitField('Add') + + +class UpdateDeviceForm(FlaskForm): + config_operational_status = SelectField('Operational Status', + choices=[(-1, 'Select...'), (0, 'Undefined'), (1, 'Disabled'), (2, 'Enabled')], + coerce=int, + validators=[NumberRange(min=0)]) + + submit = SubmitField('Update') diff --git a/src/webui/service/device/routes.py b/src/webui/service/device/routes.py index 220a3a33ce0c34c0cde6c5923b6e3990816f458e..105fe3b98137ecfa75ae2d657e21d3b0b7dd6923 100644 --- a/src/webui/service/device/routes.py +++ b/src/webui/service/device/routes.py @@ -24,6 +24,8 @@ from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from webui.service.device.forms import AddDeviceForm from common.DeviceTypes import DeviceTypeEnum +from webui.service.device.forms import ConfigForm +from webui.service.device.forms import UpdateDeviceForm device = Blueprint('device', __name__, url_prefix='/device') context_client = ContextClient() @@ -161,3 +163,72 @@ def delete(device_uuid): flash(f'Problem deleting device "{device_uuid}": {e.details()}', 'danger') current_app.logger.exception(e) return redirect(url_for('device.home')) + +@device.route('<path:device_uuid>/addconfig', methods=['GET', 'POST']) +def addconfig(device_uuid): + form = ConfigForm() + request = DeviceId() + request.device_uuid.uuid = device_uuid + context_client.connect() + response = context_client.GetDevice(request) + context_client.close() + + if form.validate_on_submit(): + device = Device() + device.CopyFrom(response) + config_rule = device.device_config.config_rules.add() + config_rule.action = ConfigActionEnum.CONFIGACTION_SET + config_rule.custom.resource_key = form.device_key_config.data + config_rule.custom.resource_value = form.device_value_config.data + try: + device_client.connect() + response: DeviceId = device_client.ConfigureDevice(device) + device_client.close() + flash(f'New configuration was created with ID "{response.device_uuid.uuid}".', 'success') + return redirect(url_for('device.home')) + except Exception as e: + flash(f'Problem adding the device. {e.details()}', 'danger') + + return render_template('device/addconfig.html', form=form, submit_text='Add New Configuration') + +@device.route('updateconfig', methods=['GET', 'POST']) +def updateconfig(): + + + return render_template('device/updateconfig.html') + + +@device.route('<path:device_uuid>/update', methods=['GET', 'POST']) +def update(device_uuid): + form = UpdateDeviceForm() + request = DeviceId() + request.device_uuid.uuid = device_uuid + context_client.connect() + response = context_client.GetDevice(request) + context_client.close() + + ## listing enum values + #form.operational_status.choices = [] + #for key, value in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_name.items(): + # form.operational_status.choices.append((DeviceOperationalStatusEnum.Value(key), key.replace('DEVICEOPERATIONALSTATUS_', ''))) +# + #form.operational_status.default = response.device_operational_status + print(form.errors) + if form.is_submitted(): + print("submitted") + if form.validate(): + print("valid") + print(form.errors) + #if form.validate_on_submit(): + # device = Device() + # device.CopyFrom(response) + # device.device_operational_status = form.operational_status.data + # try: + # device_client.connect() + # response: DeviceId = device_client.ConfigureDevice(device) + # device_client.close() + # flash(f'New configuration was created with ID "{response.device_uuid.uuid}".', 'success') + # return redirect(url_for('device.home')) + # except Exception as e: + # flash(f'Problem adding the device. {e.details()}', 'danger') + return render_template('device/update.html', device=response, form=form, submit_text='Update Device') diff --git a/src/webui/service/templates/device/addconfig.html b/src/webui/service/templates/device/addconfig.html new file mode 100644 index 0000000000000000000000000000000000000000..c6a17e0a5919c974f168c92bf2248980b39a2332 --- /dev/null +++ b/src/webui/service/templates/device/addconfig.html @@ -0,0 +1,69 @@ +<!-- + Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +{% extends 'base.html' %} + +{% block content %} +<h1>Add New Configuration</h1> +<br /> +<form id="add_device" method="POST"> + {{ form.hidden_tag() }} + <fieldset> + <div class="row mb-3"> + {{ form.device_key_config.label(class="col-sm-2 col-form-label") }} + <div class="col-sm-10"> + {% if form.device_key_config.errors %} + {{ form.device_key_config(class="form-control is-invalid") }} + <div class="invalid-feedback"> + {% for error in form.device_key_config.errors %} + <span>{{ error }}</span> + {% endfor %} + </div> + {% else %} + {{ form.device_key_config(class="form-control") }} + {% endif %} + </div> + </div> + <br /> + <div class="row mb-3"> + {{ form.device_value_config.label(class="col-sm-2 col-form-label") }} + <div class="col-sm-10"> + {% if form.device_value_config.errors %} + {{ form.device_value_config(class="form-control is-invalid") }} + <div class="invalid-feedback"> + {% for error in form.device_value_config.errors %} + <span>{{ error }}</span> + {% endfor %} + </div> + {% else %} + {{ form.device_value_config(class="form-control") }} + {% endif %} + </div> + </div> + <br /> + <div class="d-grid gap-2 d-md-flex justify-content-md-start"> + <button type="submit" class="btn btn-primary"> + <i class="bi bi-plus-circle-fill"></i> + {{ submit_text }} + </button> + <button type="button" class="btn btn-block btn-secondary" onclick="javascript: history.back()"> + <i class="bi bi-box-arrow-in-left"></i> + Cancel + </button> + </div> + </fieldset> +</form> +{% endblock %} \ No newline at end of file diff --git a/src/webui/service/templates/device/detail.html b/src/webui/service/templates/device/detail.html index f07b9c985c1e6dfdd46a6f13a0852c80280543d9..e49396c4f7971cb19fff5780d3830082f9422a5b 100644 --- a/src/webui/service/templates/device/detail.html +++ b/src/webui/service/templates/device/detail.html @@ -27,7 +27,7 @@ </button> </div> <div class="col-sm-3"> - <a id="update" class="btn btn-secondary" href="#"> + <a id="update" class="btn btn-secondary" href="{{ url_for('device.update',device_uuid=device.device_id.device_uuid.uuid) }}"> <i class="bi bi-pencil-square"></i> Update </a> @@ -79,11 +79,14 @@ </div> <b>Configurations:</b> + <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Key</th> <th scope="col">Value</th> + <th scope="col"></th> + <th scope="col"></th> </tr> </thead> <tbody> @@ -100,11 +103,28 @@ {% endfor %} </ul> </td> + <td> + <a id="update" class="btn btn-secondary" href="{{ url_for('device.updateconfig')}}"> + <i class="bi bi-pencil-square"></i> + </a> + </td> + <td> + <!-- <button type="button" class="btn btn-danger"><i class="bi bi-x-square"></i>Delete device</button> --> + <button type="button" class="btn btn-danger"> + <i class="bi bi-x-square"></i> + </button> + </td> </tr> {% endif %} {% endfor %} </tbody> </table> +<div class="col"> + <a href="{{ url_for('device.addconfig', device_uuid=device.device_id.device_uuid.uuid) }}" class="btn btn-primary" style="margin-bottom: 10px;"> + <i class="bi bi-plus"></i> + Add New Configuration + </a> +</div> <!-- Modal --> diff --git a/src/webui/service/templates/device/update.html b/src/webui/service/templates/device/update.html new file mode 100644 index 0000000000000000000000000000000000000000..3b25da9c189b50603f56a4681ea4c3bd0efe301d --- /dev/null +++ b/src/webui/service/templates/device/update.html @@ -0,0 +1,34 @@ +{% extends 'base.html' %} + +{% block content %} +<h1>Update Device {{ device.device_id.device_uuid.uuid }}</h1> +<br /> +<form id="update_device" method="POST"> + <fieldset> + <div class="row mb-3"> + {{ form.config_operational_status.label(class="col-sm-2 col-form-label") }} + <div class="col-sm-10"> + {% if form.config_operational_status.errors %} + {{ form.config_operational_status(class="form-control is-invalid") }} + <div class="invalid-feedback"> + {% for error in form.config_operational_status.errors %} + <span>{{ error }}</span> + {% endfor %} + </div> + {% else %} + {{ form.config_operational_status(class="form-select") }} + {% endif %} + </div> + </div> + <button type="submit" class="btn btn-primary"> + <i class="bi bi-plus-circle-fill"></i> + {{ submit_text }} + </button> + <button type="button" class="btn btn-block btn-secondary" onclick="javascript: history.back()"> + <i class="bi bi-box-arrow-in-left"></i> + Cancel + </button> + </div> + </fieldset> +</form> +{% endblock %} \ No newline at end of file diff --git a/src/webui/service/templates/device/updateconfig.html b/src/webui/service/templates/device/updateconfig.html new file mode 100644 index 0000000000000000000000000000000000000000..de217733d7674b3fc27df7e44705630b5fafeba3 --- /dev/null +++ b/src/webui/service/templates/device/updateconfig.html @@ -0,0 +1,18 @@ +<!-- + Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + + +{% extends 'base.html' %} \ No newline at end of file