Add the POST endpoint and the infrastructure to allow the calculator form to be developed.

This commit is contained in:
Phil Elson 2020-11-03 16:40:00 +01:00
parent f2644a720d
commit adfd4058d9
5 changed files with 188 additions and 1 deletions

9
.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
__pycache__
.ipynb_checkpoints
*.egg-info
# Editor stuff
*.swp
.idea
.vscode

View file

@ -7,7 +7,17 @@
## Development guide
### Building the docker image for local execution
### Running the COVID calculator app locally
```
pip install -e . # At the root of the repository
python -m cara.apps.calculator
```
Then visit http://localhost:8080/calculator.
### Building the whole environment for local execution
**Simulate the docker build that takes place on openshift with:**

View file

@ -0,0 +1,55 @@
import json
from pathlib import Path
from tornado.web import Application, RequestHandler, StaticFileHandler
import cara.models
def build_model(request: dict) -> cara.models.Model:
return None
def build_response(model: cara.models.Model):
return {'items': 'foobar'}
class ConcentrationModel(RequestHandler):
def post(self):
requested_model_config = {
name: self.get_argument(name) for name in self.request.arguments
}
try:
model = build_model(requested_model_config)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as err:
response_json = {'code': 400, 'error': f'Your request was invalid {err}'}
self.set_status(400)
self.finish(json.dumps(response_json))
return
response_json = build_response(model)
response_json['room_name'] = requested_model_config.get('room_name', 'unknown')
self.write(response_json)
def make_app(debug=False, prefix='/calculator'):
static_dir = Path(__file__).absolute().parent / 'static'
urls = [
(
prefix + r'()', StaticFileHandler, {'path': static_dir / 'form.html'}
),
(
prefix + r'/api/calculator', ConcentrationModel
),
(
prefix + r'/static/(.*)',
StaticFileHandler,
{'path': static_dir}
),
]
return Application(
urls,
debug=debug,
)

View file

@ -0,0 +1,27 @@
import argparse
from tornado.ioloop import IOLoop
from tornado.options import define, options
from . import make_app
def configure_parser(parser):
parser.add_argument(
"--no-debug", help="Don't enable debug mode",
action="store_false",
)
return parser
def main():
parser = argparse.ArgumentParser()
args = configure_parser(parser)
args = parser.parse_args()
app = make_app(debug=args.no_debug)
app.listen(8080)
IOLoop.instance().start()
if __name__ == '__main__':
main()

View file

@ -0,0 +1,86 @@
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
</head>
<body>
<form id="covid-calculator">
<label for="room_name">Room name:</label>
<input name="room_name" type="text" value="" />
<input type="submit" value="Send" />
</form>
<div id="results">
The results will go here:
</div>
<script>
function objectifyForm(formArray) {
//serialize data function
var returnArray = {};
for (var i = 0; i < formArray.length; i++){
returnArray[formArray[i]['name']] = formArray[i]['value'];
}
return returnArray;
}
// Contents from https://stackoverflow.com/a/5004276/741316
// Variable to hold request
var request;
// Bind to the submit event of our form
$("#covid-calculator").submit(function(event){
// Prevent default posting of form - put here to work in case of errors
event.preventDefault();
// Abort any pending request
if (request) {
request.abort();
}
// setup some local variables
var $form = $(this);
// Let's select and cache all the fields
var $inputs = $form.find("input, select, button, textarea");
// Serialize the data in the form
var serializedData = objectifyForm($form.serializeArray());
console.log(['Sending over', JSON.stringify(serializedData)])
// Fire off the request to the calculator.
request = $.ajax({
url: "/calculator/api/calculator",
type: "post",
data: serializedData,
dataType: "json",
});
// Callback handler that will be called on success
request.done(function (response, textStatus, jqXHR){
build_report(response);
});
// Callback handler that will be called on failure
request.fail(function (jqXHR, textStatus, errorThrown){
// Log the error to the console
console.error(
"The following error occurred: "+
textStatus, errorThrown
);
});
});
function build_report(report_data) {
$("#results").html("Results are in: " + JSON.stringify(report_data));
}
</script>
</body>
</html>