Query API : Raw table query tutorial

This tutorial will guide you through the construction of a custom view based on the raw table query API. The view will show:

Creating the custom view

Let’s start by opening the Hurricanes demo file from the “File > Open Demo” menu using the Omniscope “Classic” interface if prompted.

Create a new blank tab, then click on the “Add View > View Designer” icon to start creating our new custom view. In the browser View Designer app, click on “Create new” and give it a name (e.g. raw data view).

Edit manifest.json

Select the newly created view and click on “edit view”. The first file we will edit is the manifest.json so we can customise our view capabilities and options.

We need to:

In the options -> items element:

Now we can add all these items to the view toolbar by editing the structure -> toolbar element

   "structure": {
      "toolbar": [
        "fields",
        "sorts",
        "sortsDirection"
      ],
      "x": [
        "paneX"
      ],
      "y": [
        "paneY"
      ]
    }

Edit index.html

Once we edited the manifest.json we can now edit the index.html file in the view designer.

Build the raw data query

The first step is to build the raw data query.

As we are providing sorts on selected fields, we need to ensure sorts are only configured on selected fields.

        // get hold of the view context
        var viewContext = omniscope.view.context();
        var sorts = [];
        if (viewContext.options.items.sorts) {
            viewContext.options.items.sorts.forEach(function(sortItem) {
                if (viewContext.options.items.fields.indexOf(sortItem) >= 0) {
                    sorts.push({ inputField: sortItem, direction: omniscope.view.context().options.items.sortsDirection });
                } else {
                    // show some warnings to user.
                    document.getElementById("warnings").textContent += "Cannot order by '"+sortItem+"' as it is not selected in the Fields menu";
                }
            });
        }

Then we can create the raw query

        var rawQuery = { 
                         "@visokiotype": "SimpleQuery",
                         "fields" : viewContext.options.items.fields,
                         "sorts" : sorts,
                         "filters" : viewContext.dataConfig.filter
                       };

Note that we need to add the @visokiotype element to specify the “SimpleQuery” value to avoid any ambiguity.

The query contains the fields and sorts specified by the user, and it also uses the filters provided by the view framework.

The following code snippet shows how to execute the query and create a html table with the result data.
We use the omniscope.view.queryBuilder() function that creates a query builder with pre-configured view’s filter state.
We insert it as function called on view load, update and resize (replace the existing one)

omniscope.view.on(["load", "update", "resize"], function() {

    // get hold of the view context
    var viewContext = omniscope.view.context();
    var sorts = [];
    if (viewContext.options.items.sorts) {
        viewContext.options.items.sorts.forEach(function(sortItem) {
            if (viewContext.options.items.fields.indexOf(sortItem) >= 0) {
                sorts.push({ inputField: sortItem, direction: omniscope.view.context().options.items.sortsDirection });
            } else {
                // show some warnings to user.
                document.getElementById("warnings").textContent += "Cannot order by '"+sortItem+"' as it is not selected in the Fields menu";
            }
        });
    }

    // create the query
    var rawQuery = { 
                     "@visokiotype": "SimpleQuery",
                     "fields" : viewContext.options.items.fields,
                     "sorts" : sorts,
                     "filters" : viewContext.dataConfig.filter
                   };
                   
    // execute the query
    omniscope.view.queryBuilder().table(rawQuery)
        .on("error", function(err) {
            if (event.data.error) console.log(event.data.error);
            omniscope.view.error(event.data.message, event.data.internal);
        })
        //on result
        .on("load", function(event) {
            document.getElementById("query").textContent = JSON.stringify(rawQuery, null, 2);
          
            if (event.data.records) {
              //create tabular view of result
              var fields = event.data.schema.fields;
              var records = event.data.records;

              var table = document.createElement("table");
              var header = table.insertRow(0);
              header.style.fontWeight = "bold";
              var col = 0;
              fields.forEach(function(field) {
                  var cell = header.insertCell(col++);
                  cell.innerHTML = field.name;
              });

              var recordId = 1;
              records.forEach(function(record) {
                   var col = 0;
                   var row = table.insertRow(recordId++);
                   record.forEach(function(column) {
                       var cell = row.insertCell(col++);
                       //truncate text
                       if (typeof column === "string" && column.length > 50) { 
                           column = column.substring(0, 50) + "...";
                       }
                       cell.innerHTML = column;
                   });
              });
              
              document.getElementById("result").appendChild(table);
            } else {
              document.getElementById("result").textContent = "No records";
            }
            
        })
        .execute();
});

View style

Here we adjust the view style to make it look prettier. In the html style element we add some CSS rules for our view:

        main {
            width: 99%;
            height: 99%;
            font-family: monospace;
            font-size: 11px;
            overflow: scroll;
        }
        #query {
          font-size: 11px;
          overflow: scroll;
          border: 1px dotted lightgrey;
          height: 200px;
          white-space: pre;
        }
        #result {
          font-size: 12px;
        }
        #warnings {
            color: red;
            white-space: pre;
        }
        td {
             border: 1px dotted lightgrey;
        }

And we complete the index.html editing by adding the view structure in the HTML body element:

<main>
 <div id="warnings"></div>
 <h3>Query:</h3>
 <div id="query"></div>
 <h3>Result:</h3>
 <div id="result"></div>
</main>

Finally, check the online demo for this tutorial Raw data custom view demo