mirror of
https://github.com/OpenBankProject/API-Explorer.git
synced 2026-02-06 10:47:23 +00:00
Refactoring live-docs
This commit is contained in:
parent
4d00adc7a9
commit
c9b80a708b
@ -5,8 +5,7 @@ import net.liftweb.json.JObject
|
||||
import net.liftweb.json.JsonDSL._
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.common.Full
|
||||
import net.liftweb.json.JsonAST.JValue
|
||||
import net.liftweb.json.JsonAST.JInt
|
||||
import net.liftweb.json.JsonAST.{JValue, JInt}
|
||||
import net.liftweb.json.JDouble
|
||||
import net.liftweb.common.Empty
|
||||
import java.net.URL
|
||||
@ -627,19 +626,36 @@ object ObpJson {
|
||||
case class PermissionsJson(permissions : Option[List[PermissionJson]])
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Copied from OBP-API JSONFactory1_4_0
|
||||
// TODO: Import these and others from API jar file?
|
||||
|
||||
// Import these from API jar file?
|
||||
// Matches OBP-API representation of Resource Docs etc. Used to describe where an API call is implemented
|
||||
case class ImplementedByJson (
|
||||
version : String, // Short hand for the version e.g. "1_4_0" means Implementations1_4_0
|
||||
function : String // The val / partial function that implements the call e.g. "getBranches"
|
||||
)
|
||||
|
||||
|
||||
// Used to describe the OBP API calls for documentation and API discovery purposes
|
||||
case class ResourceDocJson(id: Int,
|
||||
verb: String,
|
||||
url: String,
|
||||
description: String)
|
||||
request_verb: String,
|
||||
request_url: String,
|
||||
description: String,
|
||||
request_body: JValue,
|
||||
response_body: JValue,
|
||||
implemented_by: ImplementedByJson)
|
||||
|
||||
case class ResourceDocsJson (resource_docs : List[ResourceDocJson])
|
||||
///////////////////////////////////////////
|
||||
|
||||
|
||||
// Internal representation of the ResourceDoc (may differ from the OBP API representation)
|
||||
case class ResourceDoc(id: Int,
|
||||
verb: String,
|
||||
url: String,
|
||||
description: String)
|
||||
description: String,
|
||||
request_body: JValue)
|
||||
|
||||
|
||||
case class ResourceDocs (resourceDocs : List[ResourceDoc])
|
||||
|
||||
@ -3,14 +3,19 @@ package code.snippet
|
||||
import _root_.net.liftweb._
|
||||
import code.lib.ObpJson.ResourceDoc
|
||||
import code.lib.{ObpPost, ObpGet}
|
||||
//import code.snippet.CallUrlForm._
|
||||
import net.liftweb.http.S
|
||||
|
||||
import net.liftweb.json.{JsonParser, JsonAST}
|
||||
import net.liftweb.json.{Extraction, JsonParser, JsonAST}
|
||||
import net.liftweb.json.JsonAST.{JField, JObject, JValue}
|
||||
import _root_.scala.xml.{NodeSeq, Text}
|
||||
|
||||
|
||||
import net.liftweb._
|
||||
// for compact render
|
||||
import net.liftweb.json._
|
||||
|
||||
|
||||
import common._
|
||||
|
||||
import net.liftweb.util.Helpers._
|
||||
@ -28,32 +33,26 @@ Present a list of OBP resource URLs
|
||||
*/
|
||||
class LiveDocs extends Loggable {
|
||||
def showResources = {
|
||||
case class Resource(id: String,
|
||||
verb: String,
|
||||
url: String,
|
||||
description: String,
|
||||
representation: String)
|
||||
|
||||
// Get the requested version from the url parameter and default if none
|
||||
val apiVersion = S.param("api-version").getOrElse("1.4.0")
|
||||
val apiVersionRequested = S.param("api-version").getOrElse("1.4.0")
|
||||
|
||||
if (apiVersion != "1.4.0") S.notice("Note: Only 1.4.0 is currently supported")
|
||||
if (apiVersionRequested != "1.4.0") S.notice("Note: Only 1.4.0 is currently supported")
|
||||
|
||||
logger.info (s"API version requested is: $apiVersion")
|
||||
logger.info (s"API version requested is: $apiVersionRequested")
|
||||
|
||||
// Get a list of resource docs from the API server
|
||||
// This will throw exception if resource_docs key is not populated
|
||||
// Convert the json representation to ResourceDoc (pretty much a one to one mapping)
|
||||
|
||||
|
||||
val resources = for {
|
||||
r <- getResourceDocsJson.map(_.resource_docs).get
|
||||
} yield ResourceDoc(id = r.id, verb = r.verb, url = r.url, description = r.description)
|
||||
} yield ResourceDoc(id = r.id, verb = r.request_verb, url = r.request_url, description = r.description, request_body = r.request_body)
|
||||
|
||||
|
||||
// Render the resources into a (nested) table.
|
||||
// This could probably be improved.
|
||||
// So far we can't (why?) set value of input field at render time like this ".resource_id_input [value]" #> s"lslslsls${i.id}"
|
||||
// so have to work around and set the input fields via the try_me_button onclick javascript.
|
||||
// Notes on escaping strings
|
||||
// Notes on escaping strings:
|
||||
// To have a $ in the resulting string use two: $$
|
||||
// Can't escape " with \" or use triple quoted string in the string interpolation so use the replace hack
|
||||
|
||||
@ -66,9 +65,72 @@ class LiveDocs extends Loggable {
|
||||
}
|
||||
|
||||
|
||||
// Constant
|
||||
val apiVersion = "v1.4.0"
|
||||
|
||||
|
||||
|
||||
var resourceId = ""
|
||||
var requestVerb = ""
|
||||
var requestUrl = ""
|
||||
var requestBody = "{}"
|
||||
|
||||
|
||||
|
||||
def process(): JsCmd = {
|
||||
logger.info(s"requestUrl is $requestUrl")
|
||||
logger.info(s"resourceId is $resourceId")
|
||||
|
||||
// Create json object from input string
|
||||
val jsonObject = JsonParser.parse(requestBody).asInstanceOf[JObject]
|
||||
// Call the url with optional body and put the response into the appropriate result div
|
||||
SetHtml("result_" + resourceId, Text(getResponse(apiVersion, requestUrl, requestVerb, jsonObject))) &
|
||||
// This applies json highlighting to the json
|
||||
Run ("$('pre code').each(function(i, block) { hljs.highlightBlock(block);});")
|
||||
}
|
||||
|
||||
|
||||
def getResponse (apiVersion : String, url : String, resourceVerb: String, json : JValue) : String = {
|
||||
|
||||
implicit val formats = net.liftweb.json.DefaultFormats
|
||||
|
||||
val urlWithVersion = s"/$apiVersion$url"
|
||||
|
||||
// TODO: Handle POST requests
|
||||
val responseBodyBox = {
|
||||
resourceVerb match {
|
||||
case "GET" => ObpGet(urlWithVersion)
|
||||
case "POST" => ObpPost(urlWithVersion, json)
|
||||
case _ => {
|
||||
val failMsg = s"Live Docs says: Unsupported resourceVerb: $resourceVerb. Url requested was: $url"
|
||||
logger.warn(failMsg)
|
||||
Failure(failMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logger.info(s"responseBodyBox is ${responseBodyBox}")
|
||||
|
||||
// Handle the contents of the Box
|
||||
val responseBody =
|
||||
responseBodyBox match {
|
||||
case Full(json) => writePretty(json)
|
||||
case Empty => "Empty: API did not return anything"
|
||||
case Failure(message, _, _) => "Failure: " + message
|
||||
}
|
||||
|
||||
logger.info(s"responseBody is $responseBody")
|
||||
responseBody
|
||||
}
|
||||
|
||||
// In case we use Extraction.decompose
|
||||
implicit val formats = net.liftweb.json.DefaultFormats
|
||||
|
||||
|
||||
// Note! This is the return of the function.
|
||||
// All the replacements you want to do *must be chained here together at the end of the function*.
|
||||
// Also, you can't chain replaceWith (alias for #>)
|
||||
// Also, you can't use replaceWith (the alias for #>) to chain
|
||||
|
||||
// See the following for some examples.
|
||||
// http://blog.knoldus.com/2013/03/08/lift-web-basics-of-using-snippets-for-a-beginner/
|
||||
@ -84,86 +146,29 @@ class LiveDocs extends Loggable {
|
||||
".resource_url" #> i.url &
|
||||
".resource_description" #> i.description &
|
||||
".resource_representation" #> "JSON" &
|
||||
".resource_url_td [id]" #> s"resource_url_td_${i.id}" &
|
||||
".resource_verb_td [id]" #> s"resource_verb_td_${i.id}" &
|
||||
".resource_url_td [id]" #> s"resource_url_td_${i.id}" & // Probably don't need this now
|
||||
".resource_verb_td [id]" #> s"resource_verb_td_${i.id}" & // Probably don't need this now
|
||||
".url_caller [id]" #> s"url_caller_${i.id}" &
|
||||
"@request_url_input [id]" #> s"request_url_input_${i.id}" &
|
||||
"@request_url_input [value]" #> s"${i.url}" &
|
||||
".try_me_button [onclick]" #> s"$$(DOUBLE-QUOTE#url_caller_${i.id}DOUBLE-QUOTE).fadeToggle(); $$(DOUBLE-QUOTE#request_url_input_${i.id}DOUBLE-QUOTE).val($$(DOUBLE-QUOTE#resource_url_td_${i.id}DOUBLE-QUOTE)[0].innerHTML); $$(DOUBLE-QUOTE#resource_id_input_${i.id}DOUBLE-QUOTE).val(DOUBLE-QUOTE${i.id}DOUBLE-QUOTE); $$(DOUBLE-QUOTE#request_verb_input_${i.id}DOUBLE-QUOTE).val($$(DOUBLE-QUOTE#resource_verb_td_${i.id}DOUBLE-QUOTE)[0].innerHTML);".replaceAll("DOUBLE-QUOTE",""""""") &
|
||||
".try_me_button [onclick]" #> s"$$(DOUBLE-QUOTE#url_caller_${i.id}DOUBLE-QUOTE).fadeToggle();".replaceAll("DOUBLE-QUOTE",""""""") &
|
||||
".result [id]" #> s"result_${i.id}" &
|
||||
"@resource_id_input [id]" #> s"resource_id_input_${i.id}" &
|
||||
"@request_verb_input [id]" #> s"request_verb_input_${i.id}" &
|
||||
"@request_body [id]" #> s"request_body_${i.id}" &
|
||||
"@request_body [style]" #> s"display: ${displayBody(i.verb)};"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Call an OBP URL and return the response to the browser in JSON form.
|
||||
*/
|
||||
object CallUrlForm extends Loggable {
|
||||
|
||||
|
||||
def getResponse (apiVersion : String, url : String, resourceVerb: String, json : JValue) : String = {
|
||||
|
||||
implicit val formats = net.liftweb.json.DefaultFormats
|
||||
|
||||
// TODO: Handle POST requests
|
||||
val responseBodyBox = {
|
||||
resourceVerb match {
|
||||
case "GET" => ObpGet(url)
|
||||
case "POST" => ObpPost(url, json)
|
||||
case _ => {
|
||||
val failMsg = s"Live Docs says: Unsupported resourceVerb: $resourceVerb."
|
||||
logger.warn(failMsg)
|
||||
Failure(failMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logger.info(s"responseBodyBox is ${responseBodyBox}")
|
||||
|
||||
// Handle the contents of the Box
|
||||
val responseBody =
|
||||
responseBodyBox match {
|
||||
case Full(json) => writePretty(json)
|
||||
case Empty => "Empty: API did not return anything"
|
||||
case Failure(message, _, _) => "Failure: " + message
|
||||
}
|
||||
|
||||
logger.info(s"responseBody is $responseBody")
|
||||
responseBody
|
||||
}
|
||||
|
||||
|
||||
def render = {
|
||||
|
||||
var apiVersion = "/obp/v1.4.0/"
|
||||
var resourceId = ""
|
||||
var requestVerb = ""
|
||||
var requestUrl = ""
|
||||
var requestBody = "{}"
|
||||
|
||||
def process(): JsCmd = {
|
||||
// Create json object from input string
|
||||
val jsonObject = JsonParser.parse(requestBody).asInstanceOf[JObject]
|
||||
// Call the url with optional body and put the response into the appropriate result div
|
||||
SetHtml("result_" + resourceId, Text(getResponse(apiVersion, requestUrl, requestVerb, jsonObject))) &
|
||||
// This applies json highlighting to the json
|
||||
Run ("$('pre code').each(function(i, block) { hljs.highlightBlock(block);});")
|
||||
}
|
||||
|
||||
"@request_body [style]" #> s"display: ${displayBody(i.verb)};" &
|
||||
//////
|
||||
// The form field (on the left) is bound to the variable (urlToCall)
|
||||
// (However, updating the var here does not seem to update the form field value)
|
||||
"@resource_id_input" #> text(resourceId, s => resourceId = s, "type" -> "hidden") &
|
||||
"@request_verb_input" #> text(requestVerb, s => requestVerb = s, "type" -> "hidden") &
|
||||
"@request_url_input" #> text(requestUrl, s => requestUrl = s, "maxlength" -> "255", "size" -> "100") &
|
||||
"@request_body_input" #> text(requestBody, s => requestBody = s, "type" -> "text") &
|
||||
// TODO use this approach.
|
||||
// We provide a default value (i.url) and bind the user input to requestUrl. requestURL is available in the function process
|
||||
"@request_url_input" #> text(i.url, s => requestUrl = s, "maxlength" -> "255", "size" -> "100", "id" -> s"request_url_input_${i.id}") &
|
||||
// Extraction.decompose creates json representation of JObject.
|
||||
"@request_body_input" #> text(pretty(render(i.request_body)), s => requestBody = s, "type" -> "text") &
|
||||
// We're not using the id at the moment
|
||||
"@request_verb_input" #> text(i.verb, s => requestVerb = s, "type" -> "text", "id" -> s"request_verb_input_${i.id}") &
|
||||
"@resource_id_input" #> text(i.id.toString, s => resourceId = s, "type" -> "text", "id" -> s"resource_id_input_${i.id}") &
|
||||
// Replace the type=submit with Javascript that makes the ajax call.
|
||||
"type=submit" #> ajaxSubmit("Call", process)
|
||||
|
||||
// ".call_button" #> ajaxSubmit("Call", process(i.id, apiVersion, i.url, i.verb,"{}"))
|
||||
//".call_button" #> ajaxSubmit("Call", process(123, "apiVersion", "i.url", "i.verb","{}"))
|
||||
".call_button" #> ajaxSubmit("Call", process)
|
||||
// def process(resourceId: String, apiVersion : String, requestUrl: String, requestVerb: String, requestBody: String = "{}"): JsCmd = {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,21 +30,24 @@
|
||||
</tr>
|
||||
|
||||
<!-- This section starts hidden and is shown with the Try Me button -->
|
||||
<tr class="url_caller" style="display: none;">
|
||||
<tr class="url_caller" style="display: block;">
|
||||
<td colspan="5">
|
||||
<form class="lift:form.ajax">
|
||||
<div class="lift:CallUrlForm">
|
||||
<div class="xxxlift:LiveDocs">
|
||||
<!-- Attributes for these fields are replaced -->
|
||||
<input name="resource_id_input">
|
||||
<input name="request_verb_input">
|
||||
<!-- The url_to_call is populated with the Try Me button (but it can be edited manually) -->
|
||||
<input name="request_verb_input" placeholder="GET or POST etc.">
|
||||
<!-- The url_to_call is populated at render (but it can be edited manually) -->
|
||||
<input name="request_url_input" placeholder="OBP URL to call">
|
||||
|
||||
<div name="request_body" style="display: block;">
|
||||
<input name="request_body_input" placeholder="JSON body to POST">
|
||||
</div>
|
||||
|
||||
<input name="test_input" placeholder="Test input">
|
||||
|
||||
<!-- This submit button is also modified by LiveDocs.scala -->
|
||||
<input type="submit">
|
||||
<input class="call_button" type="submit">
|
||||
</div>
|
||||
</form>
|
||||
<!-- API call result goes here It is highlighted by javascript called from the submit button -->
|
||||
|
||||
Loading…
Reference in New Issue
Block a user