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 generat...

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 style an Interactive Grid cell conditionally based on the value of another cell using JavaScript and CSS

Oracle APEX Color Interactive Grid (IG) group header using CSS