From c36589f1de932b5d91e6a658db53cc2f331609f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 15 Nov 2021 14:23:02 +0100 Subject: [PATCH 01/14] feature/Enhance function getDisplayNameOfUser in case of Azure as Identity Provider --- src/main/scala/code/snippet/Login.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/code/snippet/Login.scala b/src/main/scala/code/snippet/Login.scala index 8e539d6a..19c3d838 100644 --- a/src/main/scala/code/snippet/Login.scala +++ b/src/main/scala/code/snippet/Login.scala @@ -46,8 +46,9 @@ class Login { ObpAPI.currentUser.map { u => u.provider.toLowerCase() match { - case provider if provider.contains("google") => u.email - case provider if provider.contains("yahoo") => u.email + case provider if provider.contains("google") && !u.email.isEmpty => u.email + case provider if provider.contains("yahoo") && !u.email.isEmpty => u.email + case provider if provider.contains("microsoft") && !u.email.isEmpty => u.email case _ => u.username } } From db1ab02c185b18007a74ebb1b9fc56b7dde2a02f Mon Sep 17 00:00:00 2001 From: Hongwei Date: Tue, 16 Nov 2021 15:36:42 +0100 Subject: [PATCH 02/14] feature/added the json for the webui_index_dynamic_url_text_pairs props --- .../resources/props/sample.props.template | 16 +++-- src/main/scala/code/lib/ObpAPI.scala | 63 +++++++++++-------- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/src/main/resources/props/sample.props.template b/src/main/resources/props/sample.props.template index 0dc8f6b0..dc8260e6 100644 --- a/src/main/resources/props/sample.props.template +++ b/src/main/resources/props/sample.props.template @@ -149,11 +149,17 @@ dev.port=8082 # need to set it manually here. #api_manager_url= -# API explorer menu structure (temporary layout - for first workshops) -webui_index_dynamic_1_link_url=/?tags=Dynamic-Endpoint -webui_index_dynamic_1_link_text=Third Party -webui_index_dynamic_2_link_url=/?tags=Dynamic-Endpoint -webui_index_dynamic_2_link_text=Third Party 2 +# API explorer menu structure, the value should be validate json format. +#webui_index_dynamic_url_text_pairs=[\ +# {\ +# "url": "/?api-collection-id=feb47896-6a18-4a96-b8e9-ed6db05dbd401",\ +# "text": "Third Party 1"\ +# },\ +# {\ +# "url": "/?api-collection-id=feb47896-6a18-4a96-b8e9-ed6db05dbd401",\ +# "text": "Third Party 2"\ +# }\ +# ] # Sngle Sign On diff --git a/src/main/scala/code/lib/ObpAPI.scala b/src/main/scala/code/lib/ObpAPI.scala index a4e1c6ba..dd28053a 100644 --- a/src/main/scala/code/lib/ObpAPI.scala +++ b/src/main/scala/code/lib/ObpAPI.scala @@ -21,6 +21,7 @@ import scala.concurrent.duration._ import scala.language.postfixOps import java.util.UUID.randomUUID import net.liftweb.common._ +import net.liftweb.json case class Header(key: String, value: String) @@ -235,35 +236,44 @@ object ObpAPI extends Loggable { ObpDelete(s"$obpPrefix/v4.0.0/my/api-collections/$apiCollectionName/api-collection-endpoints/$operationId") } - //NOTE: there is no parameters for the method, the cache is not working well. need to fix later -// private val sharableApiCollectionsTTL: FiniteDuration = Helper.getPropsAsIntValue("sharable_api_collections.cache.ttl.seconds", 0) seconds - def sharableApiCollections: Box[List[(String, String)]] = { -// var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) -// CacheKeyFromArguments.buildCacheKey { -// Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(sharableApiCollectionsTTL) { - val apiCollectionsResponse = ObpGet(s"$obpPrefix/v4.0.0/api-collections/featured").flatMap(_.extractOpt[ApiCollectionsJson400]) - apiCollectionsResponse.map(_.api_collections.map(apiCollection => (apiCollection.api_collection_name, apiCollection.api_collection_id))) -// } -// } - } + @deprecated("16-11-2021","this is the Legacy props, now we introduce `webui_index_dynamic_url_text_pairs` ") + def getApiCollectionsFromPropsLegacy: List[(String, String)] = { + val webuiIndexDynamic1LinkUrl = Helper.getPropsValue("webui_index_dynamic_1_link_url", "") + val webuiIndexDynamic1LinkText = Helper.getPropsValue("webui_index_dynamic_1_link_text", "") - val webuiIndexDynamic1LinkUrl = Helper.getPropsValue("webui_index_dynamic_1_link_url", "") - val webuiIndexDynamic1LinkText = Helper.getPropsValue("webui_index_dynamic_1_link_text", "") - - val webuiIndexDynamic2LinkUrl = Helper.getPropsValue("webui_index_dynamic_2_link_url", "") - val webuiIndexDynamic2LinkText = Helper.getPropsValue("webui_index_dynamic_2_link_text", "") + val webuiIndexDynamic2LinkUrl = Helper.getPropsValue("webui_index_dynamic_2_link_url", "") + val webuiIndexDynamic2LinkText = Helper.getPropsValue("webui_index_dynamic_2_link_text", "") + + if (webuiIndexDynamic1LinkUrl.nonEmpty && webuiIndexDynamic1LinkText.nonEmpty && webuiIndexDynamic2LinkText.nonEmpty && webuiIndexDynamic2LinkUrl.nonEmpty){ + List( + (webuiIndexDynamic1LinkText,webuiIndexDynamic1LinkUrl), (webuiIndexDynamic2LinkText,webuiIndexDynamic2LinkUrl) + ) + } else if (webuiIndexDynamic1LinkText.nonEmpty && webuiIndexDynamic1LinkText.nonEmpty ) + List( + (webuiIndexDynamic1LinkText,webuiIndexDynamic1LinkUrl) + ) + else + Nil + } + + val dynamicUrlTextPairsJson: List[DynamicUrlTextPairsJson] = { + def extractor(str: String) = try { + val dynamicUrlTextPairs = json.parse(str).extract[List[DynamicUrlTextPairsJson]] + //The props value can be parse to JNothing. + if(str.nonEmpty && dynamicUrlTextPairs == Nil) + throw new RuntimeException(s"props [webui_index_dynamic_url_text_pairs] parse -> extract to Nil! it should be the valid class($DynamicUrlTextPairsJson) json format, current value is $str .") + else + dynamicUrlTextPairs + } catch { + case e: Throwable => // error handling, found wrong props value as early as possible. + this.logger.error(s"props [webui_index_dynamic_url_text_pairs] value is invalid, it should be the class($DynamicUrlTextPairsJson) json format, current value is $str ." ); + throw e; + } + Helper.getPropsValue("webui_index_dynamic_url_text_pairs").map(extractor).getOrElse(Nil) + } def getApiCollectionsFromProps: Box[List[(String, String)]] = { - if (webuiIndexDynamic1LinkUrl.nonEmpty && webuiIndexDynamic1LinkText.nonEmpty && webuiIndexDynamic2LinkText.nonEmpty && webuiIndexDynamic2LinkUrl.nonEmpty){ - Full(List( - (webuiIndexDynamic1LinkText,webuiIndexDynamic1LinkUrl), (webuiIndexDynamic2LinkText,webuiIndexDynamic2LinkUrl) - )) - } else if (webuiIndexDynamic1LinkText.nonEmpty && webuiIndexDynamic1LinkText.nonEmpty ) - Full(List( - (webuiIndexDynamic1LinkText,webuiIndexDynamic1LinkUrl) - )) - else - Full(Nil) + Full(getApiCollectionsFromPropsLegacy ++ dynamicUrlTextPairsJson.map(dynamicUrlTextPair => List((dynamicUrlTextPair.text, dynamicUrlTextPair.url))).flatten) } /** @@ -1232,6 +1242,7 @@ object ObpJson { ) case class ResourceDocsJson (resource_docs : List[ResourceDocJson]) + case class DynamicUrlTextPairsJson (url:String, text:String) /////////////////////////////////////////// From be05dd7dc32a5d0d4f5ef5013de6426a5695faff Mon Sep 17 00:00:00 2001 From: Hongwei Date: Tue, 23 Nov 2021 21:27:52 +0100 Subject: [PATCH 03/14] bugfix/fixed the operationId mapping issue --- src/main/scala/code/lib/ObpAPI.scala | 16 ++--- src/main/scala/code/snippet/ApiExplorer.scala | 59 +++++++++++-------- src/main/scala/code/util/Helper.scala | 18 ++++++ src/main/webapp/index.html | 2 +- 4 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/main/scala/code/lib/ObpAPI.scala b/src/main/scala/code/lib/ObpAPI.scala index dd28053a..16afa9d6 100644 --- a/src/main/scala/code/lib/ObpAPI.scala +++ b/src/main/scala/code/lib/ObpAPI.scala @@ -5,7 +5,7 @@ import java.text.SimpleDateFormat import java.util.{Date, UUID} import code.lib.ObpJson._ import code.util.Helper -import code.util.Helper.MdcLoggable +import code.util.Helper.{MdcLoggable, covertWebpageIdToObpOperationId} import code.util.cache.Caching import net.liftweb.common.{Box, Failure, Full, _} import net.liftweb.http.{RequestVar, S, SessionVar} @@ -227,13 +227,15 @@ object ObpAPI extends Loggable { ObpPost(s"$obpPrefix/v4.0.0/my/api-collections", Extraction.decompose(postSelectionEndpointJson)) } - def createMyApiCollectionEndpoint (apiCollectionName: String, operationId: String) = { - val postSelectionEndpointJson = PostSelectionEndpointJson400(operationId) + def createMyApiCollectionEndpoint (apiCollectionName: String, webPageOperationId: String) = { + val obpOperationId = covertWebpageIdToObpOperationId(webPageOperationId) + val postSelectionEndpointJson = PostSelectionEndpointJson400(obpOperationId) ObpPost(s"$obpPrefix/v4.0.0/my/api-collections/$apiCollectionName/api-collection-endpoints", Extraction.decompose(postSelectionEndpointJson)) } - def deleteMyApiCollectionEndpoint (apiCollectionName: String, operationId: String) = { - ObpDelete(s"$obpPrefix/v4.0.0/my/api-collections/$apiCollectionName/api-collection-endpoints/$operationId") + def deleteMyApiCollectionEndpoint (apiCollectionName: String, webPageOperationId: String) = { + val obpOperationId = covertWebpageIdToObpOperationId(webPageOperationId) + ObpDelete(s"$obpPrefix/v4.0.0/my/api-collections/$apiCollectionName/api-collection-endpoints/$obpOperationId") } @deprecated("16-11-2021","this is the Legacy props, now we introduce `webui_index_dynamic_url_text_pairs` ") @@ -667,7 +669,7 @@ object ObpDeleteBoolean { object ObpDelete { def apply(apiPath: String): Box[JValue] = { OBPRequest(apiPath, None, "DELETE", Nil) match { - case Full((status, result, _)) => Full(APIUtils.apiResponseWorked(status, result)) + case Full((status, result, _)) => APIUtils.getAPIResponseBody(status, result) case Failure(msg, exception, chain) => Failure(msg) case _ => Failure("Unknown Error!") } @@ -676,7 +678,7 @@ object ObpDelete { object ObpDeleteWithHeader { def apply(apiPath: String, headers : List[Header] = Nil): (Box[JValue], List[String]) = { OBPRequest(apiPath, None, "DELETE", headers) match { - case Full(value) => (APIUtils.deleteApiResponse(value._1, value._2), value._3) + case Full(value) => (APIUtils.getAPIResponseBody(value._1, value._2), value._3) } } } diff --git a/src/main/scala/code/snippet/ApiExplorer.scala b/src/main/scala/code/snippet/ApiExplorer.scala index d8f5a829..bc9f86ea 100644 --- a/src/main/scala/code/snippet/ApiExplorer.scala +++ b/src/main/scala/code/snippet/ApiExplorer.scala @@ -4,7 +4,7 @@ import code.lib.ObpAPI.{getAuthenticationTypeValidations, getJsonSchemaValidatio import code.lib.ObpJson._ import code.lib.{ObpAPI, ObpGet, _} import code.util.Helper -import code.util.Helper.MdcLoggable +import code.util.Helper.{MdcLoggable, covertObpOperationIdToWebpageId} import net.liftweb.json import net.liftweb.util.{CssSel, Html5} import java.net.URL @@ -590,7 +590,10 @@ WIP to add comments on resource docs. This code copied from Sofit. var errorResponseBodies = List("") var isFavourites = "false" - var favouritesOperationId = "" + //Note: OperationIdFromWebpage = OBPv4_0_0-getBanks + //But operationIdForOBP => OBPv4.0.0-getBanks (Javascript do not support '.' there.) + //We must do the converting properly for this two ids. + var favouritesOperationIdFromWebpage = "" var favouritesApiCollectionId = "" @@ -665,9 +668,7 @@ WIP to add comments on resource docs. This code copied from Sofit. val allResources = for { r <- allResourcesList } yield ResourceDocPlus( - //in OBP-API, before it returned v3_1_0, but now, only return v3.1.0 - //But this field will be used in JavaScript, so need clean the field. - id = r.operation_id.replace(".","_").replaceAll(" ","_"), + id = covertObpOperationIdToWebpageId(r.operation_id), operationId = r.operation_id, verb = r.request_verb, url = modifiedRequestUrl( @@ -773,8 +774,8 @@ WIP to add comments on resource docs. This code copied from Sofit. //this can be empty list, if there is no operationIds there. - val getOperationIdsByApiCollectionId = ObpAPI.getApiCollectionEndpointsById(apiCollectionId).map(_.api_collection_endpoints.map(_.operation_id)).openOr(List()) - val getMyOperationIds = ObpAPI.getApiCollectionEndpoints("Favourites").map(_.api_collection_endpoints.map(_.operation_id)).openOr(List()) + def webpageOperationIds = ObpAPI.getApiCollectionEndpointsById(apiCollectionId).map(_.api_collection_endpoints.map(_.operation_id)).openOr(List()).map(covertObpOperationIdToWebpageId) + def myWebpageOperationIds = ObpAPI.getApiCollectionEndpoints("Favourites").map(_.api_collection_endpoints.map(_.operation_id)).openOr(List()).map(covertObpOperationIdToWebpageId) // Group resources by the first tag val unsortedGroupedResources: Map[String, List[ResourceDocPlus]] = resources.groupBy(_.tags.headOr("ToTag")) @@ -1001,32 +1002,41 @@ WIP to add comments on resource docs. This code copied from Sofit. def processFavourites(name: String): JsCmd = { // enable button val jsEnabledBtn = s"jQuery('input[name=$name]').removeAttr('disabled')" - //We call the getApiCollectionsForCurrentUser endpoint again, to make sure we already created or delelet the record there. + //We call the getApiCollectionsForCurrentUser endpoint again, to make sure we already created or delete the record there. val apiFavouriteCollection = ObpAPI.getApiCollection("Favourites") val errorMessage = if(apiFavouriteCollection.isInstanceOf[Failure]) apiFavouriteCollection.asInstanceOf[Failure].messageChain else "" if(apiFavouriteCollection.isInstanceOf[Failure]){ // If the user is not logged in, we do not need call any apis calls. (performance enhancement) - SetHtml(s"favourites_error_message_${favouritesOperationId}", Text(errorMessage))& + SetHtml(s"favourites_error_message_${favouritesOperationIdFromWebpage}", Text(errorMessage))& Run (jsEnabledBtn) } else { if(errorMessage.equals("")){ //If there is no error, we changed the button if(favouritesApiCollectionId.nonEmpty && !apiFavouriteCollection.map(_.api_collection_id).contains(favouritesApiCollectionId)){ - SetHtml(s"favourites_error_message_${favouritesOperationId}", Text("You only have read access for the Favourites. You can only edit your own Favourites."))& + SetHtml(s"favourites_error_message_${favouritesOperationIdFromWebpage}", Text("You only have read access for the Favourites. You can only edit your own Favourites."))& Run (jsEnabledBtn) }else{ - //prepare the js for the button color changing. - val favouritesBtnColour = if (getMyOperationIds.contains(favouritesOperationId)) { - ObpAPI.deleteMyApiCollectionEndpoint("Favourites",favouritesOperationId) - s"jQuery('#favourites_button_${favouritesOperationId}').css('color','#767676')" - } else { - ObpAPI.createMyApiCollectionEndpoint("Favourites",favouritesOperationId) - s"jQuery('#favourites_button_${favouritesOperationId}').css('color','#53C4EF')" + if (myWebpageOperationIds.contains(favouritesOperationIdFromWebpage)) { //If we already have this operationId, we need to delete it + val deletedBox = ObpAPI.deleteMyApiCollectionEndpoint("Favourites",favouritesOperationIdFromWebpage) + val deleteErrorMessage = if(deletedBox.isInstanceOf[Failure]) deletedBox.asInstanceOf[Failure].messageChain else "" + if (deletedBox.isInstanceOf[Failure]){ + SetHtml(s"favourites_error_message_${favouritesOperationIdFromWebpage}", Text(deleteErrorMessage)) & + Run(jsEnabledBtn) + }else{ + Run (jsEnabledBtn) & Run(s"jQuery('#favourites_button_${favouritesOperationIdFromWebpage}').css('color','#767676')") + } + } else {//If we do not have this operationId, we need to create it. + val createdBox = ObpAPI.createMyApiCollectionEndpoint("Favourites",favouritesOperationIdFromWebpage) + val createdErrorMessage = if(createdBox.isInstanceOf[Failure]) createdBox.asInstanceOf[Failure].messageChain else "" + if (createdBox.isInstanceOf[Failure]){ + SetHtml(s"favourites_error_message_${favouritesOperationIdFromWebpage}", Text(createdErrorMessage)) & + Run(jsEnabledBtn) + }else{ + Run (jsEnabledBtn) & Run(s"jQuery('#favourites_button_${favouritesOperationIdFromWebpage}').css('color','#53C4EF')") + } } - Run (jsEnabledBtn) & - Run (favouritesBtnColour)} - } else { //if there is error, we show the OBP-API error there. - SetHtml(s"favourites_error_message_${favouritesOperationId}", Text(errorMessage)) & + }} else { //if there is error, we show the OBP-API error there. + SetHtml(s"favourites_error_message_${favouritesOperationIdFromWebpage}", Text(errorMessage)) & Run(jsEnabledBtn) } } @@ -1644,11 +1654,11 @@ WIP to add comments on resource docs. This code copied from Sofit. "@success_response_body [id]" #> s"success_response_body_${i.id}" & // The button. First argument is the text of the button (GET, POST etc). Second argument is function to call. Arguments to the func could be sent in third argument "@call_button" #> Helper.ajaxSubmit(i.verb, disabledBtn, process) & - ".favourites_operatino_id" #> text(i.id.toString, s => favouritesOperationId = s, "type" -> "hidden","class" -> "favourites_operatino_id") & + ".favourites_operation_id" #> text(i.id.toString, s => favouritesOperationIdFromWebpage = s, "type" -> "hidden","class" -> "favourites_operation_id") & ".favourites_api_collection_id" #> text(apiCollectionId, s => favouritesApiCollectionId = s, "type" -> "hidden","class" -> "favourites_api_collection_id") & ".favourites_button" #> Helper.ajaxSubmit("★", disabledBtn, processFavourites, "id" -> s"favourites_button_${i.id.toString}", - if(apiCollectionIdParam.isDefined && getOperationIdsByApiCollectionId.nonEmpty) {"style" -> "color:#53C4EF"} - else if(getMyOperationIds.contains(i.id.toString)) {"style" -> "color:#53C4EF"} + if(apiCollectionIdParam.isDefined && webpageOperationIds.nonEmpty) {"style" -> "color:#53C4EF"} + else if(myWebpageOperationIds.contains(i.id.toString)) {"style" -> "color:#53C4EF"} else {"style" -> "color:#767676"} ) & ".favourites_error_message [id]" #> s"favourites_error_message_${i.id}" & @@ -1675,7 +1685,6 @@ WIP to add comments on resource docs. This code copied from Sofit. logger.debug("before showResources:") def resourceDocsRequiresRole = ObpAPI.getRoot.flatMap(_.extractOpt[APIInfoJson400].map(_.resource_docs_requires_role)).openOr(false) - // Get a list of resource docs from the API server // This will throw an exception if resource_docs key is not populated // Convert the json representation to ResourceDoc (pretty much a one to one mapping) diff --git a/src/main/scala/code/util/Helper.scala b/src/main/scala/code/util/Helper.scala index 5b25dd66..fdf74c86 100644 --- a/src/main/scala/code/util/Helper.scala +++ b/src/main/scala/code/util/Helper.scala @@ -156,4 +156,22 @@ Returns a string which can be used for the title of the account case JNothing => "" case v => pretty(render(v)) } + + //in OBP-API, before it returned v3_1_0, but now, only return v3.1.0 + //But this field will be used in JavaScript/Webpage html id attribute, so need clean the field. + //To use any of the meta-characters (such as !"#$%&'()*+,./:;<=>?@[\]^`{|}~) as a literal part of a name, + //it must be escaped with with two backslashes: \\. For example, an element with id="foo.bar", + //can use the selector $("#foo\\.bar"). + //So in Leftweb: + // eg: SetHtml(s"OBPv4.0.0_getBank", Text("Wrong OperationId")) --> not working + // eg: SetHtml(s"OBPv4_0_0_getBank", Text("Wrong OperationId")) --> working, + def covertObpOperationIdToWebpageId(operation_id: String) = { + operation_id.replace(".", "_").replaceAll(" ", "_") + } + + + def covertWebpageIdToObpOperationId(web_page_operation_id: String) = { + web_page_operation_id.replace("_", ".") + } + } diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index c98614c9..877aee1b 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -335,7 +335,7 @@

The root of the API
- +
From 37466da6251a7398ad8cc87236b8270f3682a67c Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 24 Nov 2021 15:22:17 +0100 Subject: [PATCH 04/14] bugfix/show the new bankIds in the dropdown menu --- src/main/scala/code/snippet/ApiExplorer.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/scala/code/snippet/ApiExplorer.scala b/src/main/scala/code/snippet/ApiExplorer.scala index bc9f86ea..ef5b7506 100644 --- a/src/main/scala/code/snippet/ApiExplorer.scala +++ b/src/main/scala/code/snippet/ApiExplorer.scala @@ -1093,12 +1093,15 @@ WIP to add comments on resource docs. This code copied from Sofit. featuredBankIds.contains(b.id.get) // Add a flag to say if this bank is featured. ) + // Banks where a user has accounts + My Spaces + Featured Banks. + val userCanShowBankIds= (myBankIds++featuredBankIds.map(BankId(_))++ getMySpaces.map(_.bank_ids.map(BankId(_))).getOrElse(List.empty[BankId])).toSet + val banksForUser = if (listAllBanks) // Url param says show all. banks else - if(!myBankIds.isEmpty) // User has accounts so show those banks - banks.filter(b => myBankIds.contains(BankId(b.id))) + if(!userCanShowBankIds.isEmpty) // User has accounts so show those banks + banks.filter(b => userCanShowBankIds.contains(BankId(b.id))) else // If we have a featured list of banks show those, else all. banks.filter(b => b.isFeatured || featuredBankIds.length == 0) From d039a10cf6a2253cbb77eda2e5a422776e0a9cbb Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 24 Nov 2021 15:25:26 +0100 Subject: [PATCH 05/14] refactor/tweaked the .option-box length --- src/main/webapp/media/js/website.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/webapp/media/js/website.js b/src/main/webapp/media/js/website.js index 179bfaa8..6f5b6da7 100644 --- a/src/main/webapp/media/js/website.js +++ b/src/main/webapp/media/js/website.js @@ -122,6 +122,11 @@ $(document).ready(function() { $("#right_side .resource:nth-child(5) .content-box__headline").css("padding","332px 0 0 0").css("margin","0 0 32px 0"); $("#right_side .resource:nth-child(5) .content-box .end-point-anchor form").css("padding","332px 0 0 0").css("margin","0 0 32px 0");; } + + $(".option-box").click(function(){ + $(".select2-dropdown--below").css('width','187px'); + }); + }); From 11d354cac88fca2b704b19c8521aa776b234c536 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Nov 2021 10:54:34 +0100 Subject: [PATCH 06/14] feature/move the description to the div --- src/main/scala/code/snippet/ApiExplorer.scala | 9 ++++++++- src/main/webapp/index.html | 4 +++- src/main/webapp/media/css/style.css | 12 ++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/scala/code/snippet/ApiExplorer.scala b/src/main/scala/code/snippet/ApiExplorer.scala index ef5b7506..d05c4f48 100644 --- a/src/main/scala/code/snippet/ApiExplorer.scala +++ b/src/main/scala/code/snippet/ApiExplorer.scala @@ -1428,7 +1428,14 @@ WIP to add comments on resource docs. This code copied from Sofit. "@api_glossary_item_link * " #>{ val description = glossaryItems.find(_.title == i._1.replaceAll("-"," ")).map(_.description.markdown).getOrElse("") if (description.length > 100) - description.substring(0,100).trim() +" ..." + "More..." + else + "" //If there is no description, we will show empty here. + } & + "@api_glossary_item_text * " #>{ + val description = glossaryItems.find(_.title == i._1.replaceAll("-"," ")).map(_.description.markdown).getOrElse("") + if (description.length > 100) + description.substring(0,100).trim() else "" //If there is no description, we will show empty here. } & diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index 877aee1b..9ddfb926 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -59,7 +59,9 @@ API group
  • - Read More... +
    +
    +
  • API call title diff --git a/src/main/webapp/media/css/style.css b/src/main/webapp/media/css/style.css index 4b5ba3d3..23cd59f2 100644 --- a/src/main/webapp/media/css/style.css +++ b/src/main/webapp/media/css/style.css @@ -1800,4 +1800,16 @@ details > summary.api_group_item_details_summary{ content: ""; clear: both; display: table; +} + +.api_glossary_item_text{ + text-decoration: none; + font-size: 10px; + color: #333333; + line-height: 15px; + word-wrap: break-word; + white-space: pre-wrap; + width: 240px; + margin-top: 10px; + overflow: hidden; } \ No newline at end of file From dc49c03db9e16df04c714a43a81fa36701995350 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Nov 2021 12:21:05 +0100 Subject: [PATCH 07/14] refacot/tweaked the hyperlink underline --- src/main/webapp/media/css/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/media/css/style.css b/src/main/webapp/media/css/style.css index 23cd59f2..53a97208 100644 --- a/src/main/webapp/media/css/style.css +++ b/src/main/webapp/media/css/style.css @@ -739,7 +739,7 @@ a img { color: #333333; } .api_glossary_item a { - text-decoration: none; + text-decoration: underline; font-family: Roboto-Regular; font-size: 10px; color: #333333; From 724d60af33566cc0847d998dc8831dcc6b0163fb Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Nov 2021 14:17:39 +0100 Subject: [PATCH 08/14] bugfix/Unexpected missing generic font family --- src/main/webapp/media/css/fonts.css | 6 +- src/main/webapp/media/css/normalize.css | 2 +- src/main/webapp/media/css/screen.css | 18 +++--- src/main/webapp/media/css/style.css | 74 ++++++++++++------------- 4 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/main/webapp/media/css/fonts.css b/src/main/webapp/media/css/fonts.css index 688dd8b9..973e9c95 100644 --- a/src/main/webapp/media/css/fonts.css +++ b/src/main/webapp/media/css/fonts.css @@ -1,14 +1,14 @@ @font-face { - font-family: Roboto-Light; + font-family: Roboto-Light, sans-serif; src: url(../font/Roboto-Light.ttf); } @font-face { - font-family: Roboto-Medium; + font-family: Roboto-Medium, sans-serif; src: url(../font/Roboto-Medium.ttf); } @font-face { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; src: url(../font/Roboto-Regular.ttf); } \ No newline at end of file diff --git a/src/main/webapp/media/css/normalize.css b/src/main/webapp/media/css/normalize.css index fb3067ec..73cceb35 100644 --- a/src/main/webapp/media/css/normalize.css +++ b/src/main/webapp/media/css/normalize.css @@ -208,7 +208,7 @@ code, kbd, pre, samp { - font-family: monospace, monospace; + font-family: monospace, monospace ,sans-serif; font-size: 1em; } diff --git a/src/main/webapp/media/css/screen.css b/src/main/webapp/media/css/screen.css index c2976a4f..479e2c33 100644 --- a/src/main/webapp/media/css/screen.css +++ b/src/main/webapp/media/css/screen.css @@ -8,12 +8,12 @@ pre{ border: 0; background-color: #333333; - font-family: 'Courier New', monospace; + font-family: 'Courier New', monospace ,sans-serif; } pre code{ border: 0; background-color: #333333; - font-family: 'Courier New', monospace; + font-family: 'Courier New', monospace ,sans-serif; color: #FFFFFF; } hr { @@ -80,7 +80,7 @@ hr { #left_side_small_screen .logout-link{ margin-right: 28px; margin-left: 28px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; text-align: center; @@ -128,13 +128,13 @@ hr { } .sidebar a { text-decoration: none; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; } .sidebar #sideba-api-key-div a { - font-family: Roboto-Medium; + font-family: Roboto-Medium, sans-serif; } #small-screen-navbar{ text-align: center; @@ -264,7 +264,7 @@ hr { #left_side_small_screen .logout-link{ margin-right: 28px; margin-left: 28px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; text-align: center; @@ -312,13 +312,13 @@ hr { } .sidebar a { text-decoration: none; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; } .sidebar #sideba-api-key-div a { - font-family: Roboto-Medium; + font-family: Roboto-Medium, sans-serif; } #small-screen-navbar{ text-align: center; @@ -409,7 +409,7 @@ hr { padding: 5px 12px 7px; margin: 0; background-color: #53C4EF; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 12px; color: #FFFFFF; letter-spacing: 0; diff --git a/src/main/webapp/media/css/style.css b/src/main/webapp/media/css/style.css index 53a97208..eea84c8b 100644 --- a/src/main/webapp/media/css/style.css +++ b/src/main/webapp/media/css/style.css @@ -1,7 +1,7 @@ @import url(/media/css/fonts.css); @font-face { - font-family: Roboto-Light; + font-family: Roboto-Light, sans-serif; src: url(/media/font/Roboto-Light.ttf); } body { @@ -69,7 +69,7 @@ a img { .header .site-title-box__text { display: inline-block; margin: 0; - font-family: Roboto-Light; + font-family: Roboto-Light, sans-serif; font-size:18px; color: #333333; letter-spacing: 0; @@ -106,7 +106,7 @@ a img { } .sign-box__text { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; text-align: center; @@ -192,7 +192,7 @@ a img { padding: 10px 0 10px 25px; margin: 0; float: left; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #FFFFFF; letter-spacing: 0; @@ -206,7 +206,7 @@ a img { padding: 0; margin: 26px 25px 22px 0; letter-spacing: 0; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #FFFFFF; letter-spacing: 0; @@ -242,7 +242,7 @@ a img { display: inline-block; margin: 0 0 0 0; text-decoration: none; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #FFFFFF; letter-spacing: 0; @@ -282,7 +282,7 @@ a img { color: white; background: #767676; height: 52px; - font-family: Roboto-Medium; + font-family: Roboto-Medium, sans-serif; font-size: 18px; color: #FFFFFF; line-height: 28px; @@ -305,7 +305,7 @@ a img { .info-box__headline { margin: 0 0 0 0; padding: 16px 0 16px 25px; - font-family: Roboto-Light; + font-family: Roboto-Light, sans-serif; font-size: 28px; color: #FFFFFF; letter-spacing: 0; @@ -313,7 +313,7 @@ a img { } .info-box__about_selected { - font-family: Roboto-Light; + font-family: Roboto-Light, sans-serif; font-size: 18px; color: #FFFFFF; line-height: 28px; @@ -361,14 +361,14 @@ a img { .option-section .option-box__headline { padding-top: 0; padding-bottom: 8px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; letter-spacing: 0; line-height: 24px; } .option-section select { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; /*font-size: 16px;*/ /*color: #333333;*/ /*line-height: 24px;*/ @@ -482,7 +482,7 @@ a img { margin: -240px 0 32px 0; font-weight: 400; padding: 240px 0 0 0; - font-family: Roboto-Light; + font-family: Roboto-Light, sans-serif; font-size: 28px; color: #333333; letter-spacing: 0; @@ -530,7 +530,7 @@ a img { margin: -222px 0 32px 0; font-weight: 400; padding: 222px 0 0 0; - font-family: Roboto-Light; + font-family: Roboto-Light, sans-serif; font-size: 28px; color: #333333; letter-spacing: 0; @@ -553,7 +553,7 @@ a img { width: 100%; /*padding: 5px;*/ max-width: 1000px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px;[ color: #333333;] line-height: 24px; @@ -620,7 +620,7 @@ a img { margin-right: 20px; margin-top: 0; margin-bottom: 13px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -631,7 +631,7 @@ a img { margin-right: 20px; margin-top: 0; margin-bottom: 13px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -643,7 +643,7 @@ a img { margin-right: 20px; margin-top: 0; margin-bottom: 13px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -659,7 +659,7 @@ a img { font-size: 8px; margin-left: 25px; margin-top: 13px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; color: #333333; line-height: 24px; } @@ -703,7 +703,7 @@ a img { } .api_group_item a { text-decoration: none; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -730,7 +730,7 @@ a img { } .api_list_item a { text-decoration: none; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 12px; color: #333333; line-height: 4px; @@ -740,7 +740,7 @@ a img { } .api_glossary_item a { text-decoration: underline; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 10px; color: #333333; line-height: 4px; @@ -771,7 +771,7 @@ a img { -webkit-appearance: none; margin-top: 0px; width: 100%; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -787,7 +787,7 @@ a img { margin-left: 0 ; float: left; border: 1px solid #333333; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; text-align: center; @@ -840,7 +840,7 @@ a img { margin-top: 13px; padding: 14px 19px 44px 19px; overflow-x: auto; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; line-height: 24px; @@ -851,7 +851,7 @@ a img { float: left; margin-right: 20px; margin-top: 5px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -1126,7 +1126,7 @@ code, kbd, pre, samp { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; line-height: 24px; @@ -1136,7 +1136,7 @@ samp { .glossary kbd, .glossary pre, .glossary samp { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; line-height: 24px; @@ -1387,7 +1387,7 @@ a.end-point-anchor { letter-spacing: 0; margin: 0 0 0 5px; clear: both; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 12px; line-height: 24px; } @@ -1418,7 +1418,7 @@ a.end-point-anchor { .username { color: #000; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -1489,7 +1489,7 @@ a.end-point-anchor { } .select2-results__option { padding: 6px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -1500,7 +1500,7 @@ a.end-point-anchor { } .select2-container--default .select2-selection--single .select2-selection__rendered { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -1528,7 +1528,7 @@ a.end-point-anchor { #resouce-footer .container p{ margin-left: 25px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -1584,7 +1584,7 @@ footer .footer-links-box { } footer .footer-link-box__link { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #FFFFFF; letter-spacing: 0; @@ -1630,7 +1630,7 @@ footer .footer-box__paragraph { } footer .footer-box__paragraph2 { margin-bottom: 0px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #FFFFFF; letter-spacing: 0; @@ -1643,7 +1643,7 @@ footer .footer-box__paragraph2 a:hover { } footer a,span, footer a:hover{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #FFFFFF; letter-spacing: 0; @@ -1663,7 +1663,7 @@ footer a:hover{ } .api_group_item_small_screen a { text-decoration: none; - font-family: Roboto-Light; + font-family: Roboto-Light, sans-serif; font-size: 19px; color: #333333; line-height: 27px; @@ -1765,7 +1765,7 @@ p{ .content-box__available-since span{ color: #000000; font-size: 8px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; } #dropdownMenuButton{ From 1712d5bd78c4b9f8cfac8599a63bd8dffb5f5efc Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Nov 2021 14:31:21 +0100 Subject: [PATCH 09/14] bugfix/fixed the blocker issues of sonarcloud --- src/main/webapp/media/js/views.js | 8 ++++---- src/main/webapp/media/js/website.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/webapp/media/js/views.js b/src/main/webapp/media/js/views.js index 24800c3a..31f1ce84 100644 --- a/src/main/webapp/media/js/views.js +++ b/src/main/webapp/media/js/views.js @@ -54,7 +54,7 @@ $(document).ready(function(){ /* make Save / Cancel / Delete unclickable for not selected columns */ var $actionButtons = $(".action"); - for(i=0; i<$actionButtons.length; i++){ + for(let i=0; i<$actionButtons.length; i++){ var $action = $($actionButtons[i]); if($action.attr("data-id") !== viewId) $action.attr("disabled", "disabled"); @@ -97,7 +97,7 @@ $(document).ready(function(){ function getOptions () { var aliasOptions = new Array("public", "private", "none (display real names only)") var option = "" - for(a in aliasOptions){ + for(let a in aliasOptions){ var alias = aliasOptions[a] option += "" } @@ -152,7 +152,7 @@ $(document).ready(function(){ /* make Save / Cancel / Delete clickable for not selected columns */ var $actionButtons = $(".action"); - for(i=0; i<$actionButtons.length; i++){ + for(let i=0; i<$actionButtons.length; i++){ var $action = $($actionButtons[i]); $action.removeAttr("disabled"); } @@ -174,7 +174,7 @@ $(document).ready(function(){ var $permissions = $("input.permission_value_cb"); var allowedActions = new Array(); - for(i=0; i < $permissions.length; i++){ + for(let i=0; i < $permissions.length; i++){ var $permission = $($permissions[i]) if($permission.attr("data-viewid") == viewId && $permission.is(':checked')){ allowedActions.push($permission.attr("name")); diff --git a/src/main/webapp/media/js/website.js b/src/main/webapp/media/js/website.js index 6f5b6da7..0d5f97fd 100644 --- a/src/main/webapp/media/js/website.js +++ b/src/main/webapp/media/js/website.js @@ -34,7 +34,7 @@ function openNav() { $(".api-info-section").css("display","none"); $("#right_side").css("display","none"); $("#small-nav-collapse").attr("onclick","closeNav()"); - logOnButton = $("#start-login").text().indexOf("Log on"); + let logOnButton = $("#start-login").text().indexOf("Log on"); if (logOnButton >= 0){ $("#left_side_small_screen .settings-box").css("display","none") } @@ -110,7 +110,7 @@ $(document).ready(function() { //and update the value for .version class var versions =$(".breadcrumbs .breadcrumbs__row .breadcrumbs__list .version") if(urlParameterFilteredVersionAndTagsAndContent !== ""){ - for (i = 0; i < versions.length; i++) { + for (let i = 0; i < versions.length; i++) { $(".breadcrumbs .breadcrumbs__row .breadcrumbs__list .version")[i].href=versions[i].href+"&"+urlParameterFilteredVersionAndTagsAndContent } } From c0e5042cae4df8377f5b353ca9881ee04254aab3 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Nov 2021 15:31:07 +0100 Subject: [PATCH 10/14] feature/fix the bugs of sonarcloud --- src/main/scala/code/lib/ObpAPI.scala | 59 ++++++++++++++++------------ 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/main/scala/code/lib/ObpAPI.scala b/src/main/scala/code/lib/ObpAPI.scala index 16afa9d6..8ee38415 100644 --- a/src/main/scala/code/lib/ObpAPI.scala +++ b/src/main/scala/code/lib/ObpAPI.scala @@ -40,6 +40,12 @@ object ObpAPI extends Loggable { val defaultProvider = Helper.getPropsValue("defaultAuthProvider").getOrElse("") val userNotFoundError = "user (\\S+) at provider (\\S+) not found".r + + private val AccountUrlPath = "/accounts/" + private val ApiCollectionId = "api-collection-id" + private val CacheModifier = "cache-modifier" + private val ContentEqualStatic = "content=static" + private val ContentEqualDynamic = "content=dynamic" /** * The request vars ensure that for one page load, the same API call isn't @@ -84,7 +90,7 @@ object ObpAPI extends Loggable { fromDate.map(f => Header("obp_from_date", dateFormat.format(f))).toList ::: toDate.map(t => Header("obp_to_date", dateFormat.format(t))).toList ::: sortDirection.map(s => Header("obp_sort_direction", s.value)).toList ::: Nil - ObpGet(s"$obpPrefix/v3.0.0/banks/" + urlEncode(bankId) + "/accounts/" + urlEncode(accountId) + "/" + urlEncode(viewId) + + ObpGet(s"$obpPrefix/v3.0.0/banks/" + urlEncode(bankId) + AccountUrlPath + urlEncode(accountId) + "/" + urlEncode(viewId) + "/transactions", headers).flatMap(x => x.extractOpt[TransactionsJsonV300]) } @@ -95,19 +101,19 @@ object ObpAPI extends Loggable { def publicAccounts(bankId : String) : Box[BarebonesAccountsJson] = { - ObpGet(s"$obpPrefix/v3.1.0/banks/" + urlEncode(bankId) + "/accounts/public").flatMap(_.extractOpt[BarebonesAccountsJson]) + ObpGet(s"$obpPrefix/v3.1.0/banks/" + urlEncode(bankId) + AccountUrlPath + "public").flatMap(_.extractOpt[BarebonesAccountsJson]) } def publicAccounts : Box[BarebonesAccountsJson] = { - ObpGet(s"$obpPrefix/v3.1.0/accounts/public").flatMap(_.extractOpt[BarebonesAccountsJson]) + ObpGet(s"$obpPrefix/v3.1.0${AccountUrlPath}public").flatMap(_.extractOpt[BarebonesAccountsJson]) } def privateAccounts(bankId : String) : Box[BarebonesAccountsJson] = { - ObpGet(s"$obpPrefix/v3.1.0/banks/" + urlEncode(bankId) + "/accounts/private").flatMap(_.extractOpt[BarebonesAccountsJson]) + ObpGet(s"$obpPrefix/v3.1.0/banks/" + urlEncode(bankId) + AccountUrlPath + "private").flatMap(_.extractOpt[BarebonesAccountsJson]) } def privateAccounts : Box[BarebonesAccountsJson] = { - ObpGet(s"$obpPrefix/v1.2.1/accounts/private").flatMap(_.extractOpt[BarebonesAccountsJson]) + ObpGet(s"$obpPrefix/v1.2.1${AccountUrlPath}private").flatMap(_.extractOpt[BarebonesAccountsJson]) } @deprecated("This method will mix public and private, not clear for Apps.","2018-02-18") @@ -117,20 +123,20 @@ object ObpAPI extends Loggable { // Similar to getViews below def getViewsForBankAccount(bankId: String, accountId: String) = { - ObpGet(s"$obpPrefix/v3.1.0/banks/" + bankId + "/accounts/" + accountId + "/views").flatMap(_.extractOpt[ViewsJson]) + ObpGet(s"$obpPrefix/v3.1.0/banks/" + bankId + AccountUrlPath + accountId + "/views").flatMap(_.extractOpt[ViewsJson]) } def getAccount(bankId: String, accountId: String, viewId: String) : Box[AccountJson] = { - ObpGet(s"$obpPrefix/v3.1.0/banks/" + urlEncode(bankId) + "/accounts/" + urlEncode(accountId) + "/" + urlEncode(viewId) + "/account").flatMap(x => x.extractOpt[AccountJson]) + ObpGet(s"$obpPrefix/v3.1.0/banks/" + urlEncode(bankId) + AccountUrlPath + urlEncode(accountId) + "/" + urlEncode(viewId) + "/account").flatMap(x => x.extractOpt[AccountJson]) } def getCounterparties(bankId: String, accountId: String, viewId: String): Box[DirectOtherAccountsJson] = { - val counterparties = ObpGet(s"$obpPrefix/v3.1.0/banks/" + urlEncode(bankId) + "/accounts/" + urlEncode(accountId) + "/" + urlEncode(viewId) + "/other_accounts").flatMap(x => x.extractOpt[DirectOtherAccountsJson]) + val counterparties = ObpGet(s"$obpPrefix/v3.1.0/banks/" + urlEncode(bankId) + AccountUrlPath + urlEncode(accountId) + "/" + urlEncode(viewId) + "/other_accounts").flatMap(x => x.extractOpt[DirectOtherAccountsJson]) counterparties } def getExplictCounterparties(bankId: String, accountId: String, viewId: String): Box[ExplictCounterpartiesJson] = { - ObpGet(s"$obpPrefix/v2.2.0/banks/" + urlEncode(bankId) + "/accounts/" + urlEncode(accountId) + "/" + urlEncode(viewId) + "/counterparties").flatMap(x => x.extractOpt[ExplictCounterpartiesJson]) + ObpGet(s"$obpPrefix/v2.2.0/banks/" + urlEncode(bankId) + AccountUrlPath + urlEncode(accountId) + "/" + urlEncode(viewId) + "/counterparties").flatMap(x => x.extractOpt[ExplictCounterpartiesJson]) } def getEntitlementsV300 : Box[EntitlementsJson] = { @@ -287,17 +293,18 @@ object ObpAPI extends Loggable { // Returns both system and dynamic resource docs: def getAllResourceDocsJson(apiVersion : String): Box[List[ResourceDocJson]] = { - val apiCollectionIdParam = List("api-collection-id") + val apiCollectionIdParam = List(ApiCollectionId) .map(paramName => (paramName, S.param(paramName))) .collect{ - case (paramName, Full(paramValue)) if(paramValue.trim.size > 0) => s"$paramName=$paramValue" + case (paramName, Full(paramValue)) if(paramValue.trim.size > 0 + ) => s"$paramName=$paramValue" } .mkString("?", "&", "") //Note: ?content=static&content=dynamic // if there are two content parameters there, only the first one is valid for the api call. // so requestParams have the high priority - val requestParams = List("tags", "language", "functions", "content", "cache-modifier") + val requestParams = List("tags", "language", "functions", "content", CacheModifier) .map(paramName => (paramName, S.param(paramName))) .collect{ case (paramName, Full(paramValue)) if(paramValue.trim.size > 0) => s"$paramName=$paramValue" @@ -314,11 +321,11 @@ object ObpAPI extends Loggable { lazy val dynamicResourcesDocs = getDynamicResourceDocs(apiVersion,requestParams, canReadResourceDocRole, OAuthClient.loggedIn) //If the api-collection-id in the URL, it will ignore all other parameters, so here we first check it: - if(apiCollectionIdParam.contains("api-collection-id=")) { + if(apiCollectionIdParam.contains(ApiCollectionId + "=")) { getResourceDocsByApiCollectionId(apiVersion, apiCollectionIdParam) - }else if(requestParams.contains("content=static")) { + }else if(requestParams.contains(ContentEqualStatic)) { staticResourcesDocs - } else if (requestParams.contains("content=dynamic")){ + } else if (requestParams.contains(ContentEqualDynamic)){ dynamicResourcesDocs } else{ for{ @@ -333,7 +340,7 @@ object ObpAPI extends Loggable { // Returns all bank level dynamic resources def getStaticAndAllBankLevelDynamicResourceDocs(apiVersion : String) = { - val apiCollectionIdParam = List("api-collection-id") + val apiCollectionIdParam = List(ApiCollectionId) .map(paramName => (paramName, S.param(paramName))) .collect{ case (paramName, Full(paramValue)) if(paramValue.trim.size > 0) => s"$paramName=$paramValue" @@ -343,7 +350,7 @@ object ObpAPI extends Loggable { //Note: ?content=static&content=dynamic // if there are two content parameters there, only the first one is valid for the api call. // so requestParams have the high priority - val requestParams = List("tags", "language", "functions", "cache-modifier") + val requestParams = List("tags", "language", "functions", CacheModifier) .map(paramName => (paramName, S.param(paramName))) .collect{ case (paramName, Full(paramValue)) if(paramValue.trim.size > 0) => s"$paramName=$paramValue" @@ -363,11 +370,11 @@ object ObpAPI extends Loggable { bankId => getBankLevelDynamicResourceDocs(apiVersion,bankId,requestParams)).flatten.flatten) //If the api-collection-id in the URL, it will ignore all other parameters, so here we first check it: - if(apiCollectionIdParam.contains("api-collection-id=")) { + if(apiCollectionIdParam.contains(ApiCollectionId + "=")) { getResourceDocsByApiCollectionId(apiVersion, apiCollectionIdParam) - }else if(requestParams.contains("content=static")) { + }else if(requestParams.contains(ContentEqualStatic)) { staticResourcesDocs - } else if (requestParams.contains("content=dynamic")){ + } else if (requestParams.contains(ContentEqualDynamic)){ dynamicResourcesDocs } else{ for{ @@ -381,7 +388,7 @@ object ObpAPI extends Loggable { // Returns only the bank level resource docs def getOneBankLevelResourceDocsJson(apiVersion : String, bankId:String) = { - val apiCollectionIdParam = List("api-collection-id") + val apiCollectionIdParam = List(ApiCollectionId) .map(paramName => (paramName, S.param(paramName))) .collect{ case (paramName, Full(paramValue)) if(paramValue.trim.size > 0) => s"$paramName=$paramValue" @@ -391,7 +398,7 @@ object ObpAPI extends Loggable { //Note: ?content=static&content=dynamic // if there are two content parameters there, only the first one is valid for the api call. // so requestParams have the high priority - val requestParams = List("tags", "language", "functions", "content", "cache-modifier") + val requestParams = List("tags", "language", "functions", "content", CacheModifier) .map(paramName => (paramName, S.param(paramName))) .collect{ case (paramName, Full(paramValue)) if(paramValue.trim.size > 0) => s"$paramName=$paramValue" @@ -408,7 +415,7 @@ object ObpAPI extends Loggable { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(getStaticResourceDocsJsonTTL) { - val requestParamsRemovedContent = requestParams.replace("content=static","") + val requestParamsRemovedContent = requestParams.replace(ContentEqualStatic,"") getResourceDocs(apiVersion, requestParamsRemovedContent, "static") } } @@ -421,7 +428,7 @@ object ObpAPI extends Loggable { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(getDynamicResourceDocsJsonTTL) { - val requestParamsRemovedContent = requestParams.replace("content=dynamic","") + val requestParamsRemovedContent = requestParams.replace(ContentEqualDynamic,"") getResourceDocs(apiVersion, requestParamsRemovedContent, "dynamic") } } @@ -451,7 +458,7 @@ object ObpAPI extends Loggable { def getBankLevelDynamicResourceDocsJValueResponse(apiVersion : String, bankId:String, requestParams: String) = { logger.debug("getBankLevelResourceDocsJValueResponse says Hello") - val result = ObpGet(s"$obpPrefix/v4.0.0/banks/$bankId/resource-docs/$apiVersion/obp$requestParams&cache-modifier=${UUID.randomUUID().toString}") + val result = ObpGet(s"$obpPrefix/v4.0.0/banks/$bankId/resource-docs/$apiVersion/obp$requestParams&$CacheModifier=${UUID.randomUUID().toString}") logger.debug("getBankLevelResourceDocsJValueResponse says result is: " + result) result } @@ -460,7 +467,7 @@ object ObpAPI extends Loggable { ObpGet(s"$obpPrefix/v4.0.0/resource-docs/$apiVersion/obp$requestParams").map(extractResourceDocsJson).map(_.resource_docs) def getApiCollectionByIdJValueResponse(apiVersion : String) = { - val apiCollectionIdParam = List("api-collection-id") + val apiCollectionIdParam = List(ApiCollectionId) .map(paramName => (paramName, S.param(paramName))) .collect{ case (paramName, Full(paramValue)) if(paramValue.trim.size > 0) => s"$paramName=$paramValue" From f7ad4af11365b4240ac12e24af49f5f3caaf6e39 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Nov 2021 15:54:23 +0100 Subject: [PATCH 11/14] bugfix/Unexpected shorthand "font" after "font-size" --- src/main/webapp/media/css/reset.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/media/css/reset.css b/src/main/webapp/media/css/reset.css index af944401..3116b224 100644 --- a/src/main/webapp/media/css/reset.css +++ b/src/main/webapp/media/css/reset.css @@ -19,8 +19,8 @@ time, mark, audio, video { margin: 0; padding: 0; border: 0; - font-size: 100%; font: inherit; + font-size: 100%; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ From 969ffb2c649a7495af0e13cfaccd9ee6497eb23a Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Nov 2021 16:14:07 +0100 Subject: [PATCH 12/14] bugfix/fixed the bugs of sonarcloud --- src/main/scala/code/lib/ObpAPI.scala | 2 +- src/main/webapp/media/css/website.css | 2 - .../webapp/templates-hidden/_AdminLogin.html | 54 ++++++++--------- .../webapp/templates-hidden/_UserLogin.html | 60 +++++++++---------- .../webapp/templates-hidden/_comment.html | 14 ++--- src/main/webapp/templates-hidden/default.html | 4 +- 6 files changed, 67 insertions(+), 69 deletions(-) diff --git a/src/main/scala/code/lib/ObpAPI.scala b/src/main/scala/code/lib/ObpAPI.scala index 8ee38415..7cff448a 100644 --- a/src/main/scala/code/lib/ObpAPI.scala +++ b/src/main/scala/code/lib/ObpAPI.scala @@ -256,7 +256,7 @@ object ObpAPI extends Loggable { List( (webuiIndexDynamic1LinkText,webuiIndexDynamic1LinkUrl), (webuiIndexDynamic2LinkText,webuiIndexDynamic2LinkUrl) ) - } else if (webuiIndexDynamic1LinkText.nonEmpty && webuiIndexDynamic1LinkText.nonEmpty ) + } else if (webuiIndexDynamic1LinkUrl.nonEmpty && webuiIndexDynamic1LinkText.nonEmpty ) List( (webuiIndexDynamic1LinkText,webuiIndexDynamic1LinkUrl) ) diff --git a/src/main/webapp/media/css/website.css b/src/main/webapp/media/css/website.css index 09b9f484..2b46af74 100644 --- a/src/main/webapp/media/css/website.css +++ b/src/main/webapp/media/css/website.css @@ -638,7 +638,6 @@ span#accountsMsg .tagID{ padding: 5px 10px; background: #F3F9F8; - display: inline-block; margin-right: 10px; display: inline-block; border: 2px solid #CBCBCB; @@ -688,7 +687,6 @@ span#accountsMsg .image-holder { padding: 5px 10px; background: #F3F9F8; - display: inline-block; margin-right: 10px; display: inline-block; border: 2px solid #CBCBCB; diff --git a/src/main/webapp/templates-hidden/_AdminLogin.html b/src/main/webapp/templates-hidden/_AdminLogin.html index 6bc00ae2..37c11d54 100644 --- a/src/main/webapp/templates-hidden/_AdminLogin.html +++ b/src/main/webapp/templates-hidden/_AdminLogin.html @@ -1,27 +1,27 @@ -
    -
    - - - - - - - - - - - - - - - - - - -
    login
    email address
    password
    - -
    -
    -
    \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/templates-hidden/_UserLogin.html b/src/main/webapp/templates-hidden/_UserLogin.html index 230b921e..c6d239eb 100644 --- a/src/main/webapp/templates-hidden/_UserLogin.html +++ b/src/main/webapp/templates-hidden/_UserLogin.html @@ -1,30 +1,30 @@ -
    -
    - - - - - - - - - - - - - - - - - - - -
    login
    email address
    password
    - -
    -
    -
    \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/templates-hidden/_comment.html b/src/main/webapp/templates-hidden/_comment.html index 577f19d3..b81be965 100644 --- a/src/main/webapp/templates-hidden/_comment.html +++ b/src/main/webapp/templates-hidden/_comment.html @@ -1,7 +1,7 @@ -
  • - #0 - The comment goes here -
    - 2012/10/12 13:23 - Commenter's email address goes here -
  • + + + + + + + diff --git a/src/main/webapp/templates-hidden/default.html b/src/main/webapp/templates-hidden/default.html index 9ab4bb87..89ac879b 100755 --- a/src/main/webapp/templates-hidden/default.html +++ b/src/main/webapp/templates-hidden/default.html @@ -28,8 +28,8 @@ along with this program. If not, see www.gnu.org/licenses/ - - + + API Explorer From 55128ae7c1a82a326d98d2fd0ae74b7cc6960ced Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Nov 2021 17:25:58 +0100 Subject: [PATCH 13/14] bugfix/fixed the sonarcloud bugs --- src/main/scala/code/lib/ObpAPI.scala | 29 ++++++---- src/main/scala/code/snippet/ApiExplorer.scala | 55 ++++++++++--------- src/main/webapp/media/js/website.js | 2 +- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/main/scala/code/lib/ObpAPI.scala b/src/main/scala/code/lib/ObpAPI.scala index 7cff448a..44cc4f42 100644 --- a/src/main/scala/code/lib/ObpAPI.scala +++ b/src/main/scala/code/lib/ObpAPI.scala @@ -1,5 +1,6 @@ package code.lib +import code.lib.ObpAPI.UnknownErrorMessage import java.io._ import java.text.SimpleDateFormat import java.util.{Date, UUID} @@ -41,11 +42,19 @@ object ObpAPI extends Loggable { val userNotFoundError = "user (\\S+) at provider (\\S+) not found".r - private val AccountUrlPath = "/accounts/" - private val ApiCollectionId = "api-collection-id" - private val CacheModifier = "cache-modifier" - private val ContentEqualStatic = "content=static" - private val ContentEqualDynamic = "content=dynamic" + final val AccountUrlPath = "/accounts/" + final val ApiCollectionId = "api-collection-id" + final val CacheModifier = "cache-modifier" + final val ContentEqualStatic = "content=static" + final val ContentEqualDynamic = "content=dynamic" + final val UnknownErrorMessage = "Unknown Error!" + final val OBPVersionV400 = "OBPv4.0.0" + final val UKVersionV31 = "UKv3.1" + final val UKVersionV20 = "UKv2.0" + final val BGVersionV13 = "BGv1.3" + final val PAPIVersionV2111 = "PAPIv2.1.1.1" + final val BGVersionV133 = "BGv1.3.3" + final val VersionV133 = "v1.3.3" /** * The request vars ensure that for one page load, the same API call isn't @@ -624,7 +633,7 @@ object ObpPut { OBPRequest(apiPath, Some(json), "PUT", Nil) match { case Full((status, result, _)) => APIUtils.getAPIResponseBody(status, result) case Failure(msg, exception, chain) => Failure(msg) - case _ => Failure("Unknown Error!") + case _ =>Failure(UnknownErrorMessage) } } } @@ -641,7 +650,7 @@ object ObpPost { OBPRequest(apiPath, Some(json), "POST", Nil) match { case Full((status, result, _)) => APIUtils.getAPIResponseBody(status, result) case Failure(msg, exception, chain) => Failure(msg) - case _ => Failure("Unknown Error!") + case _ => Failure(UnknownErrorMessage) } } } @@ -678,7 +687,7 @@ object ObpDelete { OBPRequest(apiPath, None, "DELETE", Nil) match { case Full((status, result, _)) => APIUtils.getAPIResponseBody(status, result) case Failure(msg, exception, chain) => Failure(msg) - case _ => Failure("Unknown Error!") + case _ => Failure(UnknownErrorMessage) } } } @@ -701,7 +710,7 @@ object ObpGet { OBPRequest(apiPath, None, "GET", headers) match { case Full((status, result, _)) => APIUtils.getAPIResponseBody(status, result) case Failure(msg, exception, chain) => Failure(msg) - case _ => Failure("Unknown Error!") + case _ => Failure(UnknownErrorMessage) } } } @@ -715,7 +724,7 @@ object ObpHead { OBPRequest(apiPath, None, "HEAD", headers) match { case Full((status, result, _)) => APIUtils.getAPIResponseBody(status, result) case Failure(msg, exception, chain) => Failure(msg) - case _ => Failure("Unknown Error!") + case _ => Failure(UnknownErrorMessage) } } } diff --git a/src/main/scala/code/snippet/ApiExplorer.scala b/src/main/scala/code/snippet/ApiExplorer.scala index d05c4f48..cee13b71 100644 --- a/src/main/scala/code/snippet/ApiExplorer.scala +++ b/src/main/scala/code/snippet/ApiExplorer.scala @@ -1,6 +1,6 @@ package code.snippet -import code.lib.ObpAPI.{getAuthenticationTypeValidations, getJsonSchemaValidations, getMySpaces, obpPrefix} +import code.lib.ObpAPI._ import code.lib.ObpJson._ import code.lib.{ObpAPI, ObpGet, _} import code.util.Helper @@ -180,7 +180,7 @@ WIP to add comments on resource docs. This code copied from Sofit. logger.info(s"nativeParam is $nativeParam") - def apiCollectionIdParam = S.param("api-collection-id") + def apiCollectionIdParam = S.param(ApiCollectionId) logger.info(s"apiCollectionIdParam is $apiCollectionIdParam") @@ -343,7 +343,7 @@ WIP to add comments on resource docs. This code copied from Sofit. val defaultVersion: String = Helper.getPropsValue("default.version") match { case Full(v) => v - case _ => "OBPv4.0.0" + case _ => OBPVersionV400 } // Get the requested version from the url parameter and default if none @@ -352,9 +352,10 @@ WIP to add comments on resource docs. This code copied from Sofit. // Possible OBP Versions - val obpVersionsSupported = List("OBPv3.1.0", "OBPv4.0.0") + val obpVersionsSupported = List("OBPv3.1.0", OBPVersionV400) - val otherVersionsSupported = List("BGv1.3", "UKv3.1") + + val otherVersionsSupported = List(BGVersionV13, UKVersionV31) // This is basically all versions supported val allSupportedVersionsInDropdownMenu = List( @@ -366,11 +367,11 @@ WIP to add comments on resource docs. This code copied from Sofit. "OBPv2.2.0", "OBPv3.0.0", "OBPv3.1.0", - "OBPv4.0.0", - "UKv3.1", + OBPVersionV400, + UKVersionV31, "BGv1.3", "STETv1.4", - "PAPIv2.1.1.1", + PAPIVersionV2111, "AUv1.0.0", "0.6v1", "MXOFv1.0.0", @@ -674,12 +675,12 @@ WIP to add comments on resource docs. This code copied from Sofit. url = modifiedRequestUrl( r.specified_url, // We used to use the request_url - but we want to use the specified url i.e. the later version. apiVersion - .replaceAll("UKv2.0", "v2.0") - .replaceAll("UKv3.1", "v3.1") - .replaceAll("BGv1.3.3", "v1.3.3") + .replaceAll(UKVersionV20, "v2.0") + .replaceAll(UKVersionV31, "v3.1") + .replaceAll(BGVersionV133, VersionV133) .replaceAll("BGv1", "v1") - .replaceAll("BGv1.3", "v1.3") - .replaceAll("PAPIv2.1.1.1", "v2.1.1.1") + .replaceAll(BGVersionV13, "v1.3") + .replaceAll(PAPIVersionV2111, "v2.1.1.1") .replaceAll("OBPv", ""), presetBankId, presetAccountId @@ -964,20 +965,20 @@ WIP to add comments on resource docs. This code copied from Sofit. s"$requestUrl" } logger.info(s"urlWithVersion is: " + urlWithVersion - .replaceAll("UKv2.0", "v2.0") - .replaceAll("UKv3.1", "v3.1") - .replaceAll("BGv1.3.3", "v1.3.3") + .replaceAll(UKVersionV20, "v2.0") + .replaceAll(UKVersionV31, "v3.1") + .replaceAll(BGVersionV133, VersionV133) .replaceAll("BGv1", "v1") - .replaceAll("BGv1.3", "v1.3") + .replaceAll(BGVersionV13, "v1.3") .replaceAll("(? (i .replace("b1", "API Builder") - .replace("BGv1.3.3", "Berlin Group 1.3.3") - .replace("BGv1.3", "Berlin Group 1.3") + .replace(BGVersionV133, "Berlin Group 1.3.3") + .replace(BGVersionV13, "Berlin Group 1.3") .replace("BGv1", "Berlin Group") - .replace("UKv2.0", "UK 2.0") - .replace("UKv3.1", "UK 3.1") + .replace(UKVersionV20, "UK 2.0") + .replace(UKVersionV31, "UK 3.1") .replace("STETv1.4", "STET 1.4") - .replace("PAPIv2.1.1.1", "Polish API 2.1.1.1") + .replace(PAPIVersionV2111, "Polish API 2.1.1.1") .replace("AUv1.0.0", "AU CDR v1.0.0"), s"${CurrentReq.value.uri}?version=${i}&list-all-banks=${listAllBanks}")) @@ -1322,7 +1323,7 @@ WIP to add comments on resource docs. This code copied from Sofit. * we need to skip the case: &api-collection-id=& */ def isCollectionOfResourceDocs_? = { - S.param("api-collection-id").isDefined && S.param("api-collection-id").getOrElse("").nonEmpty + S.param(ApiCollectionId).isDefined && S.param(ApiCollectionId).getOrElse("").nonEmpty } val glossaryItems = getGlossaryItemsJson.map(_.glossary_items).getOrElse(List()) diff --git a/src/main/webapp/media/js/website.js b/src/main/webapp/media/js/website.js index 0d5f97fd..40e62035 100644 --- a/src/main/webapp/media/js/website.js +++ b/src/main/webapp/media/js/website.js @@ -101,7 +101,7 @@ $(document).ready(function() { var urlParameterFilteredVersionAndTagsAndContent = urlParameters.filter(function(item) { return !item.includes("version") && (!item.includes("tags")) - && (!item.includes("api-collection-id")) + && (!item.includes(ApiCollectionId)) && (!item.includes("content")) && (!item.includes("functions")) && (!item.includes("space_bank_id")) From f2136ad22ee8366b99e5943991a998383b1ec886 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 26 Nov 2021 11:49:44 +0100 Subject: [PATCH 14/14] refactor/Define a constant instead of duplicating this literal --- src/main/scala/code/lib/ObpAPI.scala | 21 +++ src/main/scala/code/snippet/ApiExplorer.scala | 140 +++++++++--------- 2 files changed, 91 insertions(+), 70 deletions(-) diff --git a/src/main/scala/code/lib/ObpAPI.scala b/src/main/scala/code/lib/ObpAPI.scala index 44cc4f42..f3b22199 100644 --- a/src/main/scala/code/lib/ObpAPI.scala +++ b/src/main/scala/code/lib/ObpAPI.scala @@ -55,6 +55,27 @@ object ObpAPI extends Loggable { final val PAPIVersionV2111 = "PAPIv2.1.1.1" final val BGVersionV133 = "BGv1.3.3" final val VersionV133 = "v1.3.3" + final val DisplayEqualNone = "display: none" + final val ResourceStyleCss = ".resource [style]" + final val ResourceErrorStyleCss = ".resource-error [style]" + final val DisplayEqualBlock = "display: block" + final val ContentBoxHeadline = ".content-box__headline *" + final val RolesBoxId = "@roles_box [id]" + final val RolesBoxStyle = "@roles_box [style]" + final val RoleItemClassCss = ".role_item" + final val RolesRoleNameCss = "@roles__role_name" + final val RoleStatusNameCss = "@roles__status" + final val RolesBankIdInput = "@roles__bank_id_input" + final val RolesRoleInput = "@roles__role_input" + final val RolesEntitlementRequestId = "@roles__entitlement_request_response [id]" + final val RolesRequestEntitlementButton = "@roles__request_entitlement_button" + final val PleaseLoginToRequestThisRole = " - Please login to request this Role" + final val YouHaveThisRole = s" - You have this Role." + final val ContactOBPTeam = s" - You have requested this Role. Please contact Open Bank Project team to grant your this role." + final val YouCanRequestThisRole = s" - You can request this Role." + final val RolesEntitlementRequestButtonBox = "@roles__entitlement_request_button_box [style]" + final val EndPointAnchorHref = ".end-point-anchor [href]" + final val ContentBoxHeadlineId = ".content-box__headline [id]" /** * The request vars ensure that for one page load, the same API call isn't diff --git a/src/main/scala/code/snippet/ApiExplorer.scala b/src/main/scala/code/snippet/ApiExplorer.scala index cee13b71..7d0972b5 100644 --- a/src/main/scala/code/snippet/ApiExplorer.scala +++ b/src/main/scala/code/snippet/ApiExplorer.scala @@ -1504,51 +1504,51 @@ WIP to add comments on resource docs. This code copied from Sofit. // This creates the list of resources in the DOM { if(allResourcesBox.isInstanceOf[Failure]) { - ".resource [style]" #> s"display: none" & - ".resource-error [style]" #> s"display: block" & - ".content-box__headline *" #> { + ResourceStyleCss #> s"${DisplayEqualNone}" & + ResourceErrorStyleCss #> s"${DisplayEqualBlock}" & + ContentBoxHeadline #> { allResourcesBox.asInstanceOf[Failure].msg }& { if(allResourcesBox.asInstanceOf[Failure].msg.contains("CanReadResourceDoc")){ //required roles and related user information - "@roles_box [id]" #> s"roles_box_canReadResourceDocRoleInfo" & - "@roles_box [style]" #> {s"display: block"} & + RolesBoxId #> s"roles_box_canReadResourceDocRoleInfo" & + RolesBoxStyle #> {s"${DisplayEqualBlock}"} & // We generate mulutiple .role_items from roleInfos (including the form defined in index.html) - ".role_item" #> canReadResourceDocRoleInfo.map { r => - "@roles__status" #> {if (! isLoggedIn) - s" - Please login to request this Role" + RoleItemClassCss #> canReadResourceDocRoleInfo.map { r => + RoleStatusNameCss #> {if (! isLoggedIn) + PleaseLoginToRequestThisRole else if (r.userHasEntitlement) - s" - You have this Role." + YouHaveThisRole else if (r.userHasEntitlementRequest) - s" - You have requested this Role. Please contact Open Bank Project team to grant your this role." + ContactOBPTeam else - s" - You can request this Role."} & - "@roles__role_name" #> s"${r.role}" & + YouCanRequestThisRole} & + RolesRoleNameCss #> s"${r.role}" & // ajaxSubmit will submit the form. // The value of rolesBankId is given to bank_id_input field and the value of bank_id_input entered by user is given back to rolesBankId - "@roles__bank_id_input" #> SHtml.text({if (r.requiresBankId) rolesBankId else ""}, rolesBankId = _, if (r.requiresBankId) "type" -> "text" else "type" -> "hidden") & - "@roles__role_input" #> SHtml.text(s"${r.role}", entitlementRequestRoleName = _, "type" -> "hidden" ) & + RolesBankIdInput #> SHtml.text({if (r.requiresBankId) rolesBankId else ""}, rolesBankId = _, if (r.requiresBankId) "type" -> "text" else "type" -> "hidden") & + RolesRoleInput #> SHtml.text(s"${r.role}", entitlementRequestRoleName = _, "type" -> "hidden" ) & "@roles__resource_id_input" #> text("canReadResourceDocRoleInfo", s => RolesResourceId = s, "type" -> "hidden", "id" -> s"roles__resource_id_input_${canReadResourceDocRoleInfo}") & - "@roles__request_entitlement_button" #> Helper.ajaxSubmit("Request", disabledBtn, processEntitlementRequest) & - "@roles__entitlement_request_response [id]" #> s"roles__entitlement_request_response_${canReadResourceDocRoleInfo}_${r.role}" & - "@roles__entitlement_request_button_box [style]" #> { if (! isLoggedIn || r.userHasEntitlement || r.userHasEntitlementRequest) - s"display: none" + RolesRequestEntitlementButton #> Helper.ajaxSubmit("Request", disabledBtn, processEntitlementRequest) & + RolesEntitlementRequestId #> s"roles__entitlement_request_response_${canReadResourceDocRoleInfo}_${r.role}" & + RolesEntitlementRequestButtonBox #> { if (! isLoggedIn || r.userHasEntitlement || r.userHasEntitlementRequest) + s"${DisplayEqualNone}" else - s"display: block" + s"${DisplayEqualBlock}" } } } else{ - "@roles_box [style]" #> s"display: none" + RolesBoxStyle #> s"${DisplayEqualNone}" } } }else if(allResourcesBox.isEmpty || allResourcesBox.openOr(Nil).length ==0){ - ".resource [style]" #> s"display: none" & - ".resource-error [style]" #> s"display: block" & - ".content-box__headline *" #> { + ResourceStyleCss #> s"${DisplayEqualNone}" & + ResourceErrorStyleCss #> s"${DisplayEqualBlock}" & + ContentBoxHeadline #> { "Sorry, we could not return any Resource Docs." }& - ".content-box__info-box [style]" #> s"display: none" + ".content-box__info-box [style]" #> s"${DisplayEqualNone}" } else { //The default tag is the first tag of the resource, if it is empty, we use the API Tag. @@ -1563,9 +1563,9 @@ WIP to add comments on resource docs. This code copied from Sofit. resourcesShowedInPage }).map { i => // append the anchor to the current url. Maybe need to set the catalogue to all etc else another user might not find if the link is sent to them. - ".end-point-anchor [href]" #> s"#${i.id}" & - ".content-box__headline *" #> i.summary & - ".content-box__headline [id]" #> i.id & // id for the anchor to find + EndPointAnchorHref #> s"#${i.id}" & + ContentBoxHeadline #> i.summary & + ContentBoxHeadlineId #> i.id & // id for the anchor to find // Replace attribute named overview_text with the value (whole div/span element is replaced leaving just the text) "@description *" #> i.description & "@special_instructions *" #> i.specialInstructions & @@ -1628,34 +1628,34 @@ WIP to add comments on resource docs. This code copied from Sofit. ".connector_method_item_link *" #> i } & //required roles and related user information - "@roles_box [id]" #> s"roles_box_${i.id}" & - "@roles_box [style]" #> { if (i.roleInfos.isEmpty) - s"display: none" + RolesBoxId #> s"roles_box_${i.id}" & + RolesBoxStyle #> { if (i.roleInfos.isEmpty) + s"${DisplayEqualNone}" else - s"display: block" + s"${DisplayEqualBlock}" } & // We generate multiple .role_items from roleInfos (including the form defined in index.html) - ".role_item" #> i.roleInfos.map { r => - "@roles__status" #> {if (! isLoggedIn) - s" - Please login to request this Role" + RoleItemClassCss #> i.roleInfos.map { r => + RoleStatusNameCss #> {if (! isLoggedIn) + PleaseLoginToRequestThisRole else if (r.userHasEntitlement) - s" - You have this Role." + YouHaveThisRole else if (r.userHasEntitlementRequest) - s" - You have requested this Role. Please contact Open Bank Project team to grant your this role." + ContactOBPTeam else - s" - You can request this Role."} & - "@roles__role_name" #> s"${r.role}" & + YouCanRequestThisRole} & + RolesRoleNameCss #> s"${r.role}" & // ajaxSubmit will submit the form. // The value of rolesBankId is given to bank_id_input field and the value of bank_id_input entered by user is given back to rolesBankId - "@roles__bank_id_input" #> SHtml.text({if (r.requiresBankId) rolesBankId else ""}, rolesBankId = _, if (r.requiresBankId) "type" -> "text" else "type" -> "hidden") & - "@roles__role_input" #> SHtml.text(s"${r.role}", entitlementRequestRoleName = _, "type" -> "hidden" ) & + RolesBankIdInput #> SHtml.text({if (r.requiresBankId) rolesBankId else ""}, rolesBankId = _, if (r.requiresBankId) "type" -> "text" else "type" -> "hidden") & + RolesRoleInput #> SHtml.text(s"${r.role}", entitlementRequestRoleName = _, "type" -> "hidden" ) & "@roles__resource_id_input" #> text(i.id.toString, s => RolesResourceId = s, "type" -> "hidden", "id" -> s"roles__resource_id_input_${i.id}_${r.role}") & - "@roles__request_entitlement_button" #> Helper.ajaxSubmit("Request", disabledBtn, processEntitlementRequest) & - "@roles__entitlement_request_response [id]" #> s"roles__entitlement_request_response_${i.id}_${r.role}" & - "@roles__entitlement_request_button_box [style]" #> { if (! isLoggedIn || r.userHasEntitlement || r.userHasEntitlementRequest) - s"display: none" + RolesRequestEntitlementButton #> Helper.ajaxSubmit("Request", disabledBtn, processEntitlementRequest) & + RolesEntitlementRequestId #> s"roles__entitlement_request_response_${i.id}_${r.role}" & + RolesEntitlementRequestButtonBox #> { if (! isLoggedIn || r.userHasEntitlement || r.userHasEntitlementRequest) + s"${DisplayEqualNone}" else - s"display: block" + s"${DisplayEqualBlock}" } } & // @@ -1711,9 +1711,9 @@ WIP to add comments on resource docs. This code copied from Sofit. val glossaryItems = getGlossaryItemsJson.map(_.glossary_items).getOrElse(List()) if(glossaryItems.length==0) { - ".resource [style]" #> s"display: none" & - ".resource-error [style]" #> s"display: block" & - ".content-box__headline *" #> { + ResourceStyleCss #> s"${DisplayEqualNone}" & + ResourceErrorStyleCss #> s"${DisplayEqualBlock}" & + ContentBoxHeadline #> { if(!isLoggedIn)//If no resources, first check the login, "Sorry, we could not return any Glossary Items. Note: OBP-20001: User not logged in." else if(isLoggedIn && canReadGlossaryRole.isEmpty) //Then check the missing role @@ -1723,33 +1723,33 @@ WIP to add comments on resource docs. This code copied from Sofit. }&{ if(isLoggedIn && canReadGlossaryRole.isEmpty){ //required roles and related user information - "@roles_box [id]" #> s"roles_box_CanReadGlossaryRoleInfo" & - "@roles_box [style]" #> {s"display: block"} & + RolesBoxId #> s"roles_box_CanReadGlossaryRoleInfo" & + RolesBoxStyle #> {s"${DisplayEqualBlock}"} & // We generate multiple .role_items from roleInfos (including the form defined in index.html) - ".role_item" #> canReadGlossaryRoleInfo.map { r => - "@roles__status" #> {if (! isLoggedIn) - s" - Please login to request this Role" + RoleItemClassCss #> canReadGlossaryRoleInfo.map { r => + RoleStatusNameCss #> {if (! isLoggedIn) + PleaseLoginToRequestThisRole else if (r.userHasEntitlement) - s" - You have this Role." + YouHaveThisRole else if (r.userHasEntitlementRequest) s" - You have requested this Role. Please contact the administrators to grant you this role." else - s" - You can request this Role."} & - "@roles__role_name" #> s"${r.role}" & + YouCanRequestThisRole} & + RolesRoleNameCss #> s"${r.role}" & // ajaxSubmit will submit the form. // The value of rolesBankId is given to bank_id_input field and the value of bank_id_input entered by user is given back to rolesBankId - "@roles__bank_id_input" #> SHtml.text({if (r.requiresBankId) rolesBankId else ""}, rolesBankId = _, if (r.requiresBankId) "type" -> "text" else "type" -> "hidden") & - "@roles__role_input" #> SHtml.text(s"${r.role}", entitlementRequestRoleName = _, "type" -> "hidden" ) & - "@roles__request_entitlement_button" #> Helper.ajaxSubmit("Request", disabledBtn, processEntitlementRequest) & - "@roles__entitlement_request_response [id]" #> s"roles__entitlement_request_response_${canReadGlossaryRoleInfo}_${r.role}" & - "@roles__entitlement_request_button_box [style]" #> { if (! isLoggedIn || r.userHasEntitlement || r.userHasEntitlementRequest) - s"display: none" + RolesBankIdInput #> SHtml.text({if (r.requiresBankId) rolesBankId else ""}, rolesBankId = _, if (r.requiresBankId) "type" -> "text" else "type" -> "hidden") & + RolesRoleInput #> SHtml.text(s"${r.role}", entitlementRequestRoleName = _, "type" -> "hidden" ) & + RolesRequestEntitlementButton #> Helper.ajaxSubmit("Request", disabledBtn, processEntitlementRequest) & + RolesEntitlementRequestId #> s"roles__entitlement_request_response_${canReadGlossaryRoleInfo}_${r.role}" & + RolesEntitlementRequestButtonBox #> { if (! isLoggedIn || r.userHasEntitlement || r.userHasEntitlementRequest) + s"${DisplayEqualNone}" else - s"display: block" + s"${DisplayEqualBlock}" } } }else{ - "@roles_box [style]" #> s"display: none" + RolesBoxStyle #> s"${DisplayEqualNone}" } } }else{ @@ -1758,9 +1758,9 @@ WIP to add comments on resource docs. This code copied from Sofit. val tag = i.title.replaceAll(" ", "-") val operationId = allResourcesList.find(_.tags.head == tag).map(_.operation_id).getOrElse("") // append the anchor to the current url. Maybe need to set the catalogue to all etc else another user might not find if the link is sent to them. - ".end-point-anchor [href]" #> s"#${urlEncode(i.title.replaceAll(" ", "-"))}" & - ".content-box__headline *" #> i.title & - ".content-box__headline [id]" #> i.title.replaceAll(" ", "-") & // id for the anchor to find + EndPointAnchorHref #> s"#${urlEncode(i.title.replaceAll(" ", "-"))}" & + ContentBoxHeadline #> i.title & + ContentBoxHeadlineId #> i.title.replaceAll(" ", "-") & // id for the anchor to find //i.title must be a proper tag, and will prepare the URL for it ... ".glossary_item_apis [href]" #> { s"./?operation_id=${operationId.replace(".","_").replaceAll(" ","_")}#group-${tag}" @@ -1803,9 +1803,9 @@ WIP to add comments on resource docs. This code copied from Sofit. } } & ".message-doc" #> messageDocs.map { i => - ".end-point-anchor [href]" #> s"#${urlEncode(i.process.replaceAll(" ", "-"))}" & - ".content-box__headline *" #> i.process & - ".content-box__headline [id]" #> i.process.replaceAll(" ", "-") & // id for the anchor to find + EndPointAnchorHref #> s"#${urlEncode(i.process.replaceAll(" ", "-"))}" & + ContentBoxHeadline #> i.process & + ContentBoxHeadlineId #> i.process.replaceAll(" ", "-") & // id for the anchor to find ".outbound-topic *" #> stringToNodeSeq(i.outbound_topic.getOrElse("")) & ".inbound-topic *" #> stringToNodeSeq(i.inbound_topic.getOrElse("")) & ".outbound-message *" #> stringToNodeSeq(Helper.renderJson(i.example_outbound_message)) &