From f8ad310c665cee78ea20c90e6bdfa6373be72062 Mon Sep 17 00:00:00 2001 From: Coos Baakman Date: Thu, 6 Sep 2018 17:57:10 +0200 Subject: [PATCH 1/2] send the input data for get_metadomain_annotation as a post request --- metadome/presentation/api/routes.py | 51 ++++++++--------- .../web/templates/js/dashboard.js | 32 +++++------ tests/unit/presentation/test_api.py | 56 +++++++++++++++++++ 3 files changed, 95 insertions(+), 44 deletions(-) create mode 100644 tests/unit/presentation/test_api.py diff --git a/metadome/presentation/api/routes.py b/metadome/presentation/api/routes.py index 76395f7..674243a 100755 --- a/metadome/presentation/api/routes.py +++ b/metadome/presentation/api/routes.py @@ -1,7 +1,7 @@ from metadome.domain.repositories import GeneRepository from metadome.domain.services.metadome import process_visualization_request -from flask import Blueprint, jsonify, render_template +from flask import Blueprint, jsonify, render_template, request from builtins import Exception import traceback @@ -43,35 +43,30 @@ def get_transcript_ids_for_gene(gene_name): return jsonify(trancript_ids=transcript_results, message=message) -@bp.route('/get_metadomain_annotation', methods=['GET']) -def get_metadomain_annotation_stub(): - """This endpoint is a stub, to ensure deeper endpoints may be used""" - pass +@bp.route('/get_metadomain_annotation/', methods=['POST']) +def get_metadomain_annotation(): + data = request.get_json() + + _log.debug("data is {}".format(data)) + + if not 'transcript_id' in data: + return jsonify({"error: no transcript id"}), 400 + elif not 'protein_position' in data: + return jsonify({"error: no protein position"}), 400 + elif not 'requested_domains' in data: + return jsonify({"error: no requested domains"}), 400 + + transcript_id = data['transcript_id'] + protein_pos = data['protein_position'] + requested_domains = data['requested_domains'] + + _log.debug("get_metadomain_annotation with transcript: {}, protein position: {}, requested_domains: {}" + .format(transcript_id, protein_pos, requested_domains)) -@bp.route('/get_metadomain_annotation///') -def get_metadomain_annotation(transcript_id, protein_pos, domain_request): - _log.debug('get_metadomain_annotation with: transcript_id: '+str(transcript_id)+', protein_pos: '+str(protein_pos)+', domain_request: '+str(domain_request)) - - # Try to tokenize the domain request - try: - tokens = domain_request.split(':') - - domain_request_as_json = "{" - for token in tokens: - if token.startswith('PF'): - domain_request_as_json+= '"'+token+'":' - else: - domain_request_as_json+=token - domain_request_as_json+="}" - _log.debug(domain_request_as_json) - domain_positions = json.loads(domain_request_as_json) - except Exception as e: - return jsonify({"error:"+str(e)}) - # attempt to retrieve the response for a metadomain position from metadome.tasks import retrieve_metadomain_annotation as rma - response = rma(transcript_id, protein_pos, domain_positions) - + response = rma(transcript_id, protein_pos, requested_domains) + return jsonify(response) @bp.route('/submit_gene_analysis', methods=['GET']) @@ -139,4 +134,4 @@ def conditional_jsonify(_value, _jsonify=True): """Conditianally jsonifies a given value""" if _jsonify: return jsonify(_value) - return _value \ No newline at end of file + return _value diff --git a/metadome/presentation/web/templates/js/dashboard.js b/metadome/presentation/web/templates/js/dashboard.js index c2cf2b1..3945b93 100644 --- a/metadome/presentation/web/templates/js/dashboard.js +++ b/metadome/presentation/web/templates/js/dashboard.js @@ -557,39 +557,39 @@ function createPositionalInformation(domain_metadomain_coverage, transcript_id, protein_position = position_json.values[0].protein_pos; // Construct the request for this domain and the aligned positions - domain_request = ""; + var requested_domains = {}; domain_ids = Object.keys(position_json.values[0].domains); for (i = 0; i < domain_ids.length; i++){ domain_id = domain_ids[i]; // Check if this position is meta domain suitable if (!(position_json.values[0].domains[domain_id] == null)){ - domain_request += domain_id + ":["; + requested_domains[domain_id] = []; // append the consensus positions for (j = 0; j < position_json.values[0].domains[domain_id].consensus_pos.length; j ++) { - domain_request += position_json.values[0].domains[domain_id].consensus_pos[j]; - if (j+1 < position_json.values[0].domains[domain_id].consensus_pos.length) { - domain_request += ","; - } - } - domain_request += "]"; - if (i+1 < domain_ids.length) { - domain_request += ","; + requested_domains[domain_id].push(position_json.values[0].domains[domain_id].consensus_pos[j]) } } } - - if (domain_request != ""){ + + if (Object.keys(requested_domains).length > 0) { // Activate the loading overlay $("#loading_overlay").addClass('is-active'); - + + var input = {"requested_domains": requested_domains, + "transcript_id": transcript_id, + "protein_position": protein_position}; + // Execute the GET request - $.get("{{ url_for('api.get_metadomain_annotation_stub') }}" + "/" + transcript_id + "/" + protein_position + "/" + domain_request, function(data){ + $.post("{{ url_for('api.get_metadomain_annotation') }}", JSON.stringify(input), + contentType: "application/json", + function(data){ $("#loading_overlay").removeClass('is-active'); FillPositionalInformation(domain_metadomain_coverage, position_json, data); $("#positional_information_overlay").addClass('is-active'); - }); + } + ); } else{ // No domain request, so we can fill in the information without performing a GET request @@ -861,4 +861,4 @@ function sortTable(){ $.each(rows, function(index, row) { $('#position_information_tbody').append(row); }); -} \ No newline at end of file +} diff --git a/tests/unit/presentation/test_api.py b/tests/unit/presentation/test_api.py new file mode 100644 index 0000000..900c622 --- /dev/null +++ b/tests/unit/presentation/test_api.py @@ -0,0 +1,56 @@ +import json +import logging + +from nose.tools import with_setup, eq_ +from mock import patch +from flask import url_for + +from metadome.factory import create_app + + +_log = logging.getLogger(__name__) + + +@patch("metadome.database.db") +def setup(mock_db): + global server + global client + + class FakeDB: + def init_app(self, app): + pass + + def create_all(self): + pass + mock_db.return_value = FakeDB() + + server = create_app({'SERVER_NAME': "test-server", + 'TESTING': True, + 'SECRET_KEY': 'testing'}) + client = server.test_client() + + +def teardown(): + pass + + +@with_setup(setup, teardown) +@patch("metadome.tasks.retrieve_metadomain_annotation") +def test_get_metadomain_annotation(mock_retrieve): + global server + global client + + mock_retrieve.return_value = {} + + input_ = { + 'transcript_id': 'test', + 'protein_position': 1, + 'requested_domains': {} + } + + with server.app_context(): + r = client.post(url_for('api.get_metadomain_annotation'), + data=json.dumps(input_), + content_type="application/json") + + eq_(r.status_code, 200) From 1a419daf3bcd43f9a60572697dbcd9d42442d937 Mon Sep 17 00:00:00 2001 From: Coos Baakman Date: Fri, 7 Sep 2018 14:05:52 +0200 Subject: [PATCH 2/2] after testing: fixed the javascript so that its sent data is interpreted as actual json --- .../web/templates/js/dashboard.js | 74 ++++++++++--------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/metadome/presentation/web/templates/js/dashboard.js b/metadome/presentation/web/templates/js/dashboard.js index 3945b93..93b5bfb 100644 --- a/metadome/presentation/web/templates/js/dashboard.js +++ b/metadome/presentation/web/templates/js/dashboard.js @@ -552,50 +552,56 @@ function loadDoc() { } // annotates meta domain information for a position -function createPositionalInformation(domain_metadomain_coverage, transcript_id, position_json){ - // Retrieve the needed information for the GET request - protein_position = position_json.values[0].protein_pos; - - // Construct the request for this domain and the aligned positions +function createPositionalInformation(domain_metadomain_coverage, transcript_id, position_json) { + // Retrieve the needed information for the GET request + protein_position = position_json.values[0].protein_pos; + + // Construct the request for this domain and the aligned positions var requested_domains = {}; - domain_ids = Object.keys(position_json.values[0].domains); - for (i = 0; i < domain_ids.length; i++){ - domain_id = domain_ids[i]; - - // Check if this position is meta domain suitable - if (!(position_json.values[0].domains[domain_id] == null)){ + domain_ids = Object.keys(position_json.values[0].domains); + for (i = 0; i < domain_ids.length; i++){ + domain_id = domain_ids[i]; + + // Check if this position is meta domain suitable + if (!(position_json.values[0].domains[domain_id] == null)){ requested_domains[domain_id] = []; - - // append the consensus positions - for (j = 0; j < position_json.values[0].domains[domain_id].consensus_pos.length; j ++) { + + // append the consensus positions + for (j = 0; j < position_json.values[0].domains[domain_id].consensus_pos.length; j ++) { requested_domains[domain_id].push(position_json.values[0].domains[domain_id].consensus_pos[j]) - } - } - } + } + } + } - if (Object.keys(requested_domains).length > 0) { - // Activate the loading overlay - $("#loading_overlay").addClass('is-active'); + if (Object.keys(requested_domains).length > 0) { + // Activate the loading overlay + $("#loading_overlay").addClass('is-active'); var input = {"requested_domains": requested_domains, "transcript_id": transcript_id, "protein_position": protein_position}; - // Execute the GET request - $.post("{{ url_for('api.get_metadomain_annotation') }}", JSON.stringify(input), - contentType: "application/json", - function(data){ - $("#loading_overlay").removeClass('is-active'); - FillPositionalInformation(domain_metadomain_coverage, position_json, data); - $("#positional_information_overlay").addClass('is-active'); - } + // Execute the GET request + $.ajax( + { + type: 'POST', + url: "{{ url_for('api.get_metadomain_annotation') }}", + data: JSON.stringify(input), + success:function(data) { + $("#loading_overlay").removeClass('is-active'); + FillPositionalInformation(domain_metadomain_coverage, position_json, data); + $("#positional_information_overlay").addClass('is-active'); + }, + contentType: "application/json", + dataType: 'json' + } ); - } - else{ - // No domain request, so we can fill in the information without performing a GET request - FillPositionalInformation(domain_metadomain_coverage, position_json, {}); - $("#positional_information_overlay").addClass('is-active'); - } + } + else { + // No domains requested, so we can fill in the information without performing a GET request + FillPositionalInformation(domain_metadomain_coverage, position_json, {}); + $("#positional_information_overlay").addClass('is-active'); + } } //Adds positional information for a selected position