diff --git a/arho_feature_template/core/lambda_service.py b/arho_feature_template/core/lambda_service.py index c32171a..afe0898 100644 --- a/arho_feature_template/core/lambda_service.py +++ b/arho_feature_template/core/lambda_service.py @@ -3,7 +3,7 @@ import json import re from http import HTTPStatus -from typing import cast +from typing import Callable, cast from qgis.PyQt.QtCore import QByteArray, QObject, QUrl, pyqtSignal from qgis.PyQt.QtNetwork import QNetworkAccessManager, QNetworkProxy, QNetworkReply, QNetworkRequest @@ -15,6 +15,7 @@ class LambdaService(QObject): jsons_received = pyqtSignal(dict, dict) validation_received = pyqtSignal(dict) + validation_failed = pyqtSignal() ActionAttribute = cast(QNetworkRequest.Attribute, QNetworkRequest.User + 1) ACTION_VALIDATE_PLANS = "validate_plans" ACTION_GET_PLANS = "get_plans" @@ -57,10 +58,28 @@ def _is_api_gateway_request(self) -> bool: match = re.match(r"^https://.*execute-api.*amazonaws\.com.*$", self.lambda_url) return bool(match) + def _get_response_handler(self, action: str) -> Callable[[dict], None]: + handlers = { + self.ACTION_GET_PLANS: self._process_json_reply, + self.ACTION_VALIDATE_PLANS: self._process_validation_reply, + } + return handlers[action] + + def _get_error_handler(self, action: str) -> Callable[[], None]: + handlers = { + self.ACTION_GET_PLANS: lambda: None, + self.ACTION_VALIDATE_PLANS: self._handle_validation_error, + } + return handlers[action] + def _handle_reply(self, reply: QNetworkReply): + action = reply.request().attribute(LambdaService.ActionAttribute) + response_handler = self._get_response_handler(action) + error_handler = self._get_error_handler(action) if reply.error() != QNetworkReply.NoError: error = reply.errorString() - QMessageBox.critical(None, "API Error", f"Lambda call failed: {error}") + QMessageBox.critical(None, "API Virhe", f"Lambda kutsu epäonnistui: {error}") + error_handler() reply.deleteLater() return @@ -72,7 +91,8 @@ def _handle_reply(self, reply: QNetworkReply): # If calling the lambda directly, the response includes status code and body if int(response_json.get("statusCode", 0)) != HTTPStatus.OK: error = response_json["body"] if "body" in response_json else response_json["errorMessage"] - QMessageBox.critical(None, "API Error", f"Lambda call failed: {error}") + QMessageBox.critical(None, "API Virhe", f"Lambda kutsu epäonnistui: {error}") + error_handler() reply.deleteLater() return body = response_json["body"] @@ -80,22 +100,20 @@ def _handle_reply(self, reply: QNetworkReply): body = response_json except (json.JSONDecodeError, KeyError) as e: - QMessageBox.critical(None, "JSON Error", f"Failed to parse response JSON: {e}") + QMessageBox.critical(None, "JSON Virhe", f"Vastauksen JSON-tiedoston jäsennys epäonnistui: {e}") + error_handler() return finally: reply.deleteLater() + response_handler(body) - action = reply.request().attribute(LambdaService.ActionAttribute) - if action == self.ACTION_GET_PLANS: - self._process_json_reply(body) - elif action == self.ACTION_VALIDATE_PLANS: - self._process_validation_reply(body) + def _handle_validation_error(self): + self.validation_failed.emit() def _process_validation_reply(self, response_json: dict): """Processes the validation reply from the lambda and emits a signal.""" validation_errors = response_json.get("ryhti_responses") - self.validation_received.emit(validation_errors) def _process_json_reply(self, response_json: dict): diff --git a/arho_feature_template/gui/docks/validation_dock.py b/arho_feature_template/gui/docks/validation_dock.py index 9658d1c..575df9f 100644 --- a/arho_feature_template/gui/docks/validation_dock.py +++ b/arho_feature_template/gui/docks/validation_dock.py @@ -29,6 +29,7 @@ def __init__(self, parent=None): self.lambda_service = LambdaService() self.lambda_service.validation_received.connect(self.list_validation_errors) + self.lambda_service.validation_failed.connect(self.enable_validation) self.validate_button.clicked.connect(self.validate) def validate(self): @@ -48,15 +49,25 @@ def validate(self): self.lambda_service.validate_plan(active_plan_id) + def enable_validation(self): + """Hide progress bar and re-enable the button""" + self.progress_bar.setVisible(False) + self.validate_button.setEnabled(True) + self.validation_result_tree_view.expandAll() + self.validation_result_tree_view.resizeColumnToContents(0) + def list_validation_errors(self, validation_json): """Slot for listing validation errors and warnings.""" + if not validation_json: iface.messageBar().pushMessage("Virhe", "Validaatio json puuttuu.", level=1) + self.enable_validation() return - if not validation_json: - # If no errors or warnings, display a message and exit + # If no errors or warnings, display a message and exit + if not any(validation_json.values()): iface.messageBar().pushMessage("Virhe", "Ei virheitä havaittu.", level=1) + self.enable_validation() return for error_data in validation_json.values(): @@ -79,8 +90,5 @@ def list_validation_errors(self, validation_json): warning.get("message", ""), ) - # Hide progress bar and re-enable the button - self.progress_bar.setVisible(False) - self.validate_button.setEnabled(True) - self.validation_result_tree_view.expandAll() - self.validation_result_tree_view.resizeColumnToContents(0) + # Always enable validation at the end + self.enable_validation()