Loading src/webui/service/device/forms.py +16 −2 Original line number Diff line number Diff line Loading @@ -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): Loading @@ -42,3 +42,17 @@ 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!') 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') src/webui/service/device/routes.py +71 −0 Original line number Diff line number Diff line Loading @@ -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() Loading Loading @@ -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') src/webui/service/templates/device/addconfig.html 0 → 100644 +69 −0 Original line number Diff line number Diff line <!-- 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 src/webui/service/templates/device/detail.html +21 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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> Loading @@ -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 --> Loading src/webui/service/templates/device/update.html 0 → 100644 +34 −0 Original line number Diff line number Diff line {% 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 Loading
src/webui/service/device/forms.py +16 −2 Original line number Diff line number Diff line Loading @@ -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): Loading @@ -42,3 +42,17 @@ 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!') 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')
src/webui/service/device/routes.py +71 −0 Original line number Diff line number Diff line Loading @@ -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() Loading Loading @@ -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')
src/webui/service/templates/device/addconfig.html 0 → 100644 +69 −0 Original line number Diff line number Diff line <!-- 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
src/webui/service/templates/device/detail.html +21 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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> Loading @@ -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 --> Loading
src/webui/service/templates/device/update.html 0 → 100644 +34 −0 Original line number Diff line number Diff line {% 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