Build beautiful and interactive API documentation for ORDS

Image
In this blog post, I will show you how to quickly build beautiful and interactive API documentation for your Oracle APEX REST data sources using  swagger hub . Using APEX v23.1. I downloaded the  titanic data set  and loaded them into tables in my APEX instance, created some authorized restful services and published them using swagger hub. You can create a free account on swagger hub.   Check out my titanic swagger hub here ; Press Authorize. Username REST, password Glasgow123! I won't go through creating RESTful services and just show you the four I created that sit on top of the titanic data set; The GET is a very simple SQL query;      select * from TITANIC_DATA_SET_NEW A handy tip is to add comments, as there will appear on swagger hub, making your API self documenting; Once you have created your modules, press the Generate Swagger Doc button; This will generate an open API for you.  Copy the API and paste it into swagger hub This will generate the documentation; As mentioned b

Add calculated tooltips to your Interactive Grid

In this post, I will show you how to add a tooltip that calculates column values displayed as tooltips on your Interactive grid or report.  It's a nice value add, giving your users some context to the values in the grid.


The tooltip displays the following calculated values from the selected value's column;


Create the Interactive Region with static ID IR_STATIC_ID using the following SQL source;

select 'Product 1' as PRODUCT, 100 as VALUE_1, 200 as VALUE_2, 
'121' as VALUE_3, 'text' as VALUE_4 from DUAL
UNION
select 'Product 2' as PRODUCT, 103 as VALUE_1, 140 as VALUE_2, 
'99' as VALUE_3, 'text' as VALUE_4 from DUAL
UNION
select 'Product 3' as PRODUCT, 1 as VALUE_1, 2 as VALUE_2, 
'1,200' as VALUE_3, 'text' as VALUE_4 from DUAL
UNION
select 'Product 4' as PRODUCT, 10 as VALUE_1, 7 as VALUE_2, 
'124' as VALUE_3, 'text' as VALUE_4 from DUAL
UNION
select 'Product 5' as PRODUCT, 432 as VALUE_1, 632 as VALUE_2, 
'134' as VALUE_3, 'text' as VALUE_4 from DUAL
UNION
select 'Product 6' as PRODUCT, 34 as VALUE_1, 333 as VALUE_2, 
'non number' as VALUE_3, 'text' as VALUE_4 from DUAL

Add the following code to execute when page loads;

// Interactive report static ID
const IG_NAME = '#IR_STATIC_ID';

// This function expects the first column to be a string and the rest of the columns to be numbers.
// It will ignore any columns that have text.
$(function(){
  // Get column values for all rows and place it in the cols array
  var cols = []
  var trs = $(IG_NAME + ' tr')
  var data =$.each(trs , function(indextr){
    $.each($(tr).find("td").not(":first"), function(indextd){
      cols[index] = cols[index] || [];

      if(!isNaN($(td).text().replace(',',''))){
        cols[index].push(parseInt($(td).text().replace(',',''), 10)) 
      }
    })
  });

  cols.forEach(function(colindex)
  {
    let columnData = new ColumnData(col);

    $(IG_NAME + ' tr').find('td:eq('+(index+1)+')').each(function(itd)
    {       
        if(!isNaN($(td).text().replace(',','')))
        {
         columnData.createTooltip($(td));
        }        
    })
  })
})

class ColumnData {
    constructor(col) {
        this.max = Math.max.apply(nullcol);
        this.min = Math.min.apply(nullcol);
        this.total = col.reduce((ab=> a + b0);
        this.avg = (this.totalcol.length).toFixed(0);
        this.col = col;
        this.col.sort(function(ab){return (b-a)});
    }

    valueAsNumber(cell) {
        return parseInt((cell.text()).replace(',',''), 10);
    }

    ranking(cell)
    {
        return this.col.findIndex(rank => rank === this.valueAsNumber(cell)) +1;
    }

    maxDifference(cell)
    {
        return this.max - this.valueAsNumber(cell);
    }

    minDifference(cell)
    {
        return this.valueAsNumber(cell) - this.min;
    }   

    percent(cell)
    {
        return ((this.valueAsNumber(cell)/this.total)*100).toFixed(0);
    }
    
    percentColour(cell)
    {
        if (this.valueAsNumber(cell) < this.avg)
        {
            return "red";
        }
        return  "green"
    }

    createTooltip(cell)
    {
        cell.attr('title''');

        cell.tooltip({
        content: "<table border='1'><tr>"+
        //////////////////////////////////////////////
        // HEADER row
        //////////////////////////////////////////////
"<th class='celldata'>Value</th>"+
        "<th class='celldata'>Rank</th>"+
        "<th class='celldata'>% of total</th>"+
        "<th class='celldata'>Avg</th>"+
        "<th>Overal total</th>"+
        "<th>Min value</th><th>> Min</th>"+
        "<th>Max value</th><th>< Max</th></tr>"+
        //////////////////////////////////////////////
        // DATA row
        //////////////////////////////////////////////
        "<tr><td style='font-size: 150%;'><b>"+this.valueAsNumber(cell)+"</b></td>"+
        "<td>"+this.ranking(cell)+"</td>"+
        "<td>"+this.percent(cell)+"%</td>"+
        "<td style='font-size: 100%;' class='"+this.percentColour(cell)+"'</td>"+this.avg+"</td>"
        "<td>"+this.total+"</td>"+
        "<td>"+this.min+"</td><td>"+this.minDifference(cell)+"</td>"+
        "<td>"+this.max+"</td><td>"+this.maxDifference(cell)+"</<td>"+
        "</tr></table>"
    });  
}}


If you don't want values to appear in the tooltip, comment them out here.  In this case, we don't want min and max value displayed in the tooltip;

 //////////////////////////////////////////////
        // HEADER row
        //////////////////////////////////////////////
        "<th class='celldata'>Rank</th>"+
        "<th class='celldata'>% of total</th>"+
        "<th class='celldata'>Avg</th>"+
        "<th>Overal total</th>"+
        //"<th>Min value</th><th>> Min</th>"+
        //"<th>Max value</th><th>< Max</th></tr>"+
        //////////////////////////////////////////////
        // DATA rows
        //////////////////////////////////////////////
        "<tr><td style='font-size: 150%;'><b>"+this.valueAsNumber(cell)+"</b></td>"+
        "<td>"+this.ranking(cell)+"</td>"+
        "<td>"+this.percent(cell)+"%</td>"+
        "<td style='font-size: 100%;' class='"+this.percentColour(cell)+"'</td>"+this.avg+"</td>"
        "<td>"+this.total+"</td>"+
        //"<td>"+this.min+"</td><td>"+this.minDifference(cell)+"</td>"+
        //"<td>"+this.max+"</td><td>"+this.maxDifference(cell)+"</<td>"+
        "</tr></table>"

Conversely, you could add other values to the tooltip here like the column name.  Style the tooltip by placing this code in inline CSS;

div.ui-tooltip {
    max-width: 600px !Important;
}

table {
  border-collapsecollapse;border: 2px solid rgba(0000.075);
}

.celldata {
  padding: 15px;
  colorwhite;
  background-colorrgb(19824140);
  text-aligncenter;
}

th {
  padding: 15px;
  colorwhite;
  background-colordodgerblue;
  text-aligncenter;
}

td {
  padding: 15px
  background-color:white;
  text-aligncenter;
}

.red{
    color:red;
}

.green{
    color:green;
}

Any questions, post a comment and I will try and answer it.


Comments

Popular posts from this blog

Oracle APEX Interactive Grid colour cells based on a condition using JavaScript and CSS

Oracle APEX pretty checkbox item plugin

Build beautiful and interactive API documentation for ORDS