0

Integration of the ICD-11 Coding Tool into a Ninox database

Hi,

I use a Ninox database to keep electronic medical records of my patients. I am writing here looking for help to integrate the ICD-11 Coding Tool into my Ninox database.

You can see live the kind of functionality that I would like to implement here: 

The World Health Organization (WHO) provides detailed instructions here: 

I have tried the following code (full example) within an HTML function, but it doesn't work.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://icdcdn.who.int/embeddedct/icd11ect-1.6.1.css">
<title>Embedded Coding Tool v1.6</title>
</head>
<body>
Type for starting search:
<!-- input element used for typing the search -->
<input type="text" class="ctw-input" autocomplete="off" data-ctw-ino="1">
<!-- div element used for showing the search results -->
<div class="ctw-window" data-ctw-ino="1"></div>
<!-- example of an extra input element for testing the Embedded Coding Tool select entity function -->
The selected code: <input type="text" id="paste-selectedEntity" value="">
<script src="https://icdcdn.who.int/embeddedct/icd11ect-1.6.1.js"></script>
<script>
// Embedded Coding Tool settings object
// please note that only the property "apiServerUrl" is required
// the other properties are optional
const mySettings = {
// The API located at the URL below should be used only for software
// development and testing. ICD content at this location might not
// be up to date or complete. For production, use the API located at
// id.who.int with proper OAUTH authentication
apiServerUrl: "https://icd11restapi-developer-test.azurewebsites.net" };
// example of an Embedded Coding Tool using the callback selectedEntityFunction
// for copying the code selected in an <input> element and clear the search results
const myCallbacks = {
selectedEntityFunction: (selectedEntity) => {
// paste the code into the <input>
document.getElementById('paste-selectedEntity').value = selectedEntity.code;
// clear the searchbox and delete the search results
ECT.Handler.clear("1") } }; // configure the ECT Handler with mySettings and myCallbacks ECT.Handler.configure(mySettings, myCallbacks);
</script>
</body>

Integrating this tool could benefit all users who keep medical records in Ninox.

Any help is welcome.

24 replies

null
    • Ninox partner
    • RoSoft_Steven.1
    • 1 yr ago
    • Reported - view

    Seems like it works on codepen and in my Visual Studio but not in Ninox, seems like the input field is blocked...

    Any specialists around?

      • Ninox developper
      • Jacques_TUR
      • 1 yr ago
      • Reported - view

        

      <script src="https://icdcdn.who.int/embeddedct/icd11ect-1.6.1.js"></script>

      I believe that the loading of external libraries is intentionally blocked by Ninox for security reasons. You need to load the JS sources using the http() function and include them within the rest of the JS, CSS, and HTML code.

    • Mconneen
    • 1 yr ago
    • Reported - view

    I do not do much with embedding HTML in Ninox.. tho it seems like something really good to learn.

    That said.. See the ninox documentation on using the HTTP function.
    https://docs.ninox.com/en/api/http-function

    Provided it is simple RestAPI.. it "should" work.  If you need to do something tricky with the response object.. then your mileage may vary.

    This seems to discuss the RestAPI.. I will see what I can find out.
    https://icd.who.int/docs/icd-api/APIDoc-Version2/

    • Mconneen
    • 1 yr ago
    • Reported - view

    OK.. so the basic API works.. But I do not know what the embedded tool kit is doing.. This screen shot shows the basic call to an ICD entity.   Open "Table1" .. drill into a row.. and then manipulate the "API Endpoint" to the way you want it..  Click 'Call API' and GOOD LUCK! ;)
     

    • Mconneen
    • 1 yr ago
    • Reported - view

      ... Using the above provided ninox database.. put this into the API Endpoint.. It will return a json block items that have 'hypertension' in it..    You will have to write some Ninox code to parse the response.result .. which will be in a json string.

    https://icd11restapi-developer-test.azurewebsites.net/icd/entity/search?q=hypertension&useFlexisearch=false&flatResults=true&highlightingEnabled=true

    • Mconneen
    • 1 yr ago
    • Reported - view

    .. OK.. I am NOT an ICD-xx expert.. but it looks like you will want this API
    /icd/release/11/{releaseId}/{linearizationname}/search

    In the above supplied ninox db.. put this in the API Endpoint
    https://icd11restapi-developer-test.azurewebsites.net/icd/release/11/2023-01/mms/search?q=hypertension%25&subtreeFilterUsesFoundationDescendants=false&includeKeywordResult=false&useFlexisearch=false&flatResults=true&highlightingEnabled=true&medicalCodingMode=true

    Again.. you will have to write some code to parse the information ..   So.. like the embedded tool kit example, you will want to pull the destinationEntities[x].title and .theCode
    "title": "Essential <em class='found'>hypertension</em><em class='nonwbe'></em>, unspecified"
    "theCode": "BA00.Z",

    To use the "production" API.. you will have to register at https://icd.who.int/icdapi which will generate you a client id / secret .. You use these to first request your OAuth / Bearer token which is then put in the header of all the API requests.

    Happy Coding!

    • szormpas
    • 1 yr ago
    • Reported - view

    Hi, Thanks for all your reflections!

    The International Classification of Diseases (ICD) is the predominant classification of human diseases, syndromes, and conditions worldwide. The ICD-11 database is the latest taxonomy comprising about 85,000 entities, called classes or nodes. An entity can be anything relevant to health care. It usually represents a disease or a pathogen, but it can also be an isolated symptom or (developmental) body anomaly.

    In practice, no one can remember all these codes, so the WHO developed the ICD-11 Coding Tool software. A very advanced search engine written in javascript. It has features such as word completion and word suggestion and an intuitive way to help someone find the correct entity.

    When I want to assign a new diagnosis to a patient, I go to the above online version of the ICD-11 Coding tool, type in one or more keywords (e.g., hypertension), select and copy to the clipboard the desired code. Finally, paste the selected code back into my Ninox database.

    you got the point! It seems that yours last API endpoint suggestion search the ICD database and give back relevant results according to the keyword (e.g. hypertension). Now, what I need is to be able to select only one of the suggested entities. Do you think that it is feasible to pull only one of the "destinationEntities[x].title and .theCode" using ninox scripting?

    So, what I understand from your replies untill now is that one approach is to directly make calls to ICD-11 API and then try to manage the results local in Ninox. The alternative is to use the Embedded Coding Tool that allows the integration of a complete ICD-11 Coding Tool into your web application by  loading the external javascript library.   do you believe that the latter is feasible without breaking down Ninox security?

    In summary, which of the above approaches is the more efficient and feasible?

    • Mconneen
    • 1 yr ago
    • Reported - view

    .. Yes.. it is possible.. I started looking at a way to do a dynamic choice selection .. Then it took me over two hours to remember that https posts only seem to work from the Ninox Cloud .. at least that has been my experience...  I was playing around with the logic to POST / request an OAuth token.

    So.. Yes.. it should be possible to do from your Ninox Database.. Assuming that database is hosted within a Team on the Ninox Cloud. 

    The others will have to comment about how to pull it into an HTML window within Ninox.. That would be really interesting to see the code behind that and if it would continue to work as Ninox upgrades.

    • Ninox developper
    • Jacques_TUR
    • 1 yr ago
    • Reported - view
     said:
     Jacques TUR  do you believe that the latter is feasible without breaking down Ninox security?

    What do you mean by "challenging Ninox's security"?

    I believe you should be able to do this without much difficulty. You simply need to include the JS code directly instead of using <script> tags. To do this, open the link "https://icdcdn.who.int/embeddedct/icd11ect-1.6.1.js" in a browser, then copy the JavaScript code that appears and paste it into your code. The same applies to the .CSS files. 

    It's a good idea to start with a trial on CodePen as it's easier for debugging.

    For retrieving data from your code, you can either use Ninox's REST API or utilize Ninext, which enables you to directly modify the value of a field.

    Note : that while Ninext is recognized by Ninox, there isn't an official agreement in place yet to guarantee that Ninox updates won't disrupt the proper functioning of Ninext. Therefore, relying solely on Ninext for a commercial application is not recommended.

    • Mconneen
    • 1 yr ago
    • Reported - view
     said:
    For retrieving data from your code, you can either use Ninox's REST API or utilize Ninext, which enables you to directly modify the value of a field.

     I will have to go back and check out you Ninext again..   I don't follow the bit about retrieving data from your code using Ninox REST API..   Would the REST API access the html code block or are you referring to the base IDC API?

      • Ninox developper
      • Jacques_TUR
      • 1 yr ago
      • Reported - view

       I just meant that once the value is selected in the HTML/JavaScript code, you still need to retrieve it to place it in a field of a Ninox table. And for this purpose, you can use either the Ninox REST API or Ninext. The latter allows you to modify the value of a field in Ninox using JavaScript.

      But maybe I misunderstood what you're trying to achieve?

    • Mconneen
    • 1 yr ago
    • Reported - view
     said:
     I just meant that once the value is selected in the HTML/JavaScript code, you still need to retrieve it to place it in a field of a Ninox table. And for this purpose, you can use either the Ninox REST API or Ninext.

      .. I think it is I that does not understand.. In the above quote, are you saying that once the HTML/JavaScript has selected a value, the Ninox REST API can reach into that HTML code block and pull the selected value?

    Or.. that you can use the Ninox REST API to call out to the ICD API and list the values?   

    Sorry if I am confused.

    • szormpas
    • 1 yr ago
    • Reported - view

    Hello,

    although the option of integrating the ICD coding tool into Ninox in the way     suggests seems the most functional option, it is far from my capabilities and furthermore makes me worry about the possibility that in the future the Ninext project will not be compatible with Ninox.

    I decided to follow   's advice and tried to customize his database based on my needs. 

    1. I modified the endpoint API to accept a different keyword each time from the 'Type in a keyword' field.
    2. I created a table "TempResults" to store the 'theCode' and 'title' from the API response results each time.
    3. I added a dynamic choice field 'Select a code' which takes its values from the "TempResults" table.

    See the code below:

    'Select a code' := null;
    delete (select TempResults);
    let urlAPI := "https://icd11restapi-developer-test.azurewebsites.net/icd/release/11/2023-01/mms/search?q=" +
        'Type in a keyword' +
        "%25&subtreeFilterUsesFoundationDescendants=false&includeKeywordResult=false&useFlexisearch=false&flatResults=true&highlightingEnabled=false&medicalCodingMode=true";
    let headers := {
            Accept: "application/json",
            'API-Version': "v2",
            'Accept-Language': "en"
        };
    let response := do as server
            http("GET", urlAPI, headers, null)
        end;
    if response.error then
        'API Error Response' := text(response.error)
    else
        do as server
            for item in response.result.destinationEntities do
                let newRec := (create TempResults);
                newRec.(Code := text(item.theCode));
                newRec.(Title := text(item.title))
            end
        end
    end

     

    This way I can select the desired ICD code+title which is then copied to the corresponding patient fields.

    It works (see the screenshot) but the whole process is a bit slow.

    Do you have any suggestions for something more efficient and fast?

    In other words, is there a better way to select the desired ICD code+title and copy it to the corresponding database fields?

    Best wishes
     

      • Ninox developper
      • Jacques_TUR
      • 1 yr ago
      • Reported - view

       Good job !!!

      You can easily optimize your code like this:

      1 - Create the maximum number of records that you're willing to display in your list. For example, 100, as this is the maximum number of lines that Ninox accepts for a dynamic choice field.

      2 - Configure the "Binding" option of the Code and Title fields to "Per record in memory." This way, when you make changes, Ninox won't send the modifications to the cloud. This saves a lot of time.

      3 - Instead of deleting the records every time, you clear the values of Code and Title:

      (select TempResults).(Code := null; Title := null);

      4 - You update the first records with the items from destinationEntities:

      var i := 0;
      for item in response.result.destinationEntities do
         record(TempResults, i).(Code := text(item.theCode); Title := text(item.title));
      end;
      

      5 - In the dynamic choice field, you input the following formula:

      select TempsResults where Code;

       

      I tested updating 100 records with different values. It takes about 50ms.

      • Ninox developper
      • Jacques_TUR
      • 1 yr ago
      • Reported - view

      I've created a sample application that works quite well. I'm currently trying to get the embedded ICC code to work. It works sometimes, but it's not yet stable. I hope to achieve it soon.

      • szormpas
      • 1 yr ago
      • Reported - view

        I followed the optimizations you suggest and the improvement is spectacular. In fact the time to refresh the search data is less than the time it takes to drop down the combobox!  (I wish there was an auto focus feature!)

      • szormpas
      • 1 yr ago
      • Reported - view

        you have added some useful extra elements like the language option and the field that shows the number of results, great!!

    • Mconneen
    • 1 yr ago
    • Reported - view

    .. I also have a framework for accessing the "production" API version.. If I get time, I will roll the above into that DB and then share..

      • szormpas
      • 1 yr ago
      • Reported - view

       this is the last piece of the puzzle to mark the post as "ANSWERED". I look forward to seeing how OAUTH 2.0 token identification is done in the Ninox environment. I really appreciate what you have done already! 💪

    • Ninox developper
    • Jacques_TUR
    • 1 yr ago
    • Reported - view

    I managed to make the embedded code work by loading the CSS and JS, and then integrating it within an html() function:

    var _style := http("GET", "https://icdcdn.who.int/embeddedct/icd11ect-1.4.1.css");
    var _code := http("GET", "https://icdcdn.who.int/embeddedct/icd11ect-1.4.1.js");
    var _localScript := "
        // configure the ECT Handler
        ECT.Handler.configure({
            // The API located at the URL below should be used only
            // for software development and testing.
            // ICD content at this location might not
            // be up to date or complete.
            // For production, use the API located at
            // id.who.int with proper OAUTH authentication
            apiServerUrl: 'https://icd11restapi-developer-test.azurewebsites.net',
            language: '" +
        'Country code' +
        "' // set the language to Spanish
        });
        ECT.Handler.bindEmbeddedBrowser(1)
    ";
    var _html := ---
    <style>{ _style.result }
    </style>
    <script>{ _code.result } { _localScript }
    </script>
    <!-- div element used for building the Embedded Browser -->
    <div class="ctw-eb-window" style="width:100%; height:100%" data-ctw-ino="1"></div>
        ---;
    html(_html)
    

    I also had to call the bindEmbeddedBrowser function (line 17) to refresh the page upon display.

    And there you have the result :

      • szormpas
      • 1 yr ago
      • Reported - view

        this is impressive! speechless 😮! Actually these are two ICD-11 tools the embedded coding tool and the embedded browser!

    • szormpas
    • 1 yr ago
    • Reported - view

    Hi,
    I spent the past two days studying OAUTH2 authentication and how to use Ninox to request a token from the ICD server.
    After dozens of failed attempts, I found a way that worked (see screenshot). 
    See the code below:

    let token_endpoint := "https://icdaccessmanagement.who.int/connect/token";
    let header := {
            'Content-Type': "application/x-www-form-urlencoded"
        };
    let data := "client_id=*******&client_secret=********&scope=icdapi_access&grant_type=client_credentials";
    let response := do as server
            http("POST", token_endpoint, header, data)
        end;
    if response.error then
        'API Response' := text(response.error)
    else
        'API Response' := text(response.result)
    end
    

     

      is the above code optimal? Have you use a different 'Content-Type' in your database?

    Have a good time

    Sotirios

    • Mconneen
    • 1 yr ago
    • Reported - view

      Sorry.. I have been crazy busy.   Here is a WORK IN PROGRESS.  See the "HowTo" table for some help.   It only works to get the access token for now.  Have not had time to roll it into the rest of calling the API.     I have used this framework on many other OAuth APIs with great success.

    If I get more time.. I will clean it up.. but for now.. Have fun.
     

    • Mconneen
    • 1 yr ago
    • Reported - view

Content aside

  • Status Answered
  • 1 yr agoLast active
  • 24Replies
  • 532Views
  • 4 Following