Creating a Simple Linux Dashboard with Oracle Jet


 
Thread Tools Search this Thread
Top Forums Web Development Creating a Simple Linux Dashboard with Oracle Jet
# 1  
Old 10-22-2018
Creating a Simple Linux Dashboard with Oracle Jet

Creating a Simple Linux Dashboard with Oracle Jet - Part 1 the Server Side PHP Code

Creating a simple Linux dashboard with Oracle Jet is easy and fun. It's simple to create a dashboard to monitor your Linux server using Oracle JET. The sky is the limit with indicators and gauges.

Here is some very basic server side PHP code to build an Oracle JET dashboard. The code is not fully optimized, but should help anyone who wants to build a dashboard.

Code:
<?php

// anyway to start you request is fine.  In this script the $_GET request is not required.
// basically we build a JSON string from a number of simple Linux indicators:

if ($_GET['loadavg'] == '1') {
    $out = '{';
    $out .= getLoads();
    $out .= getLEDIndicator('mysqldump');
    $out .= getLEDIndicator('gzip');
    $out .= getLEDIndicator('find');
    $out .= getLEDIndicator('rsync');
    $out .= getdiskPercent('md2');
    $out .= getMem('MemFree');
    $out .= getMem('Cached');
    $out .= getprocessCPU('all');
    $out .= getprocessCPU('apache2');
    $out .= getprocessCPU('mysqld');
    $out .= getprocessCounts('apache2');
    $out .= getprocessCounts('rsync');
    $out .= '}';

    // on our server we have a  can_moderate() function that controls access to the JSON file
    // however, you can use any access control method you like:

    if (can_moderate()) {
        header('Access-Control-Allow-Origin: *');
        echo $out;
    }

}

// the functions are simple, and self explanatory and could be further combined
// but you get this idea:

function getprocessCounts($get = 'rsync')
{
    $target = 'ps aux | grep ' . $get . ' | grep -v grep | wc -l';
    $target_results = shell_exec($target);
    $output = ',"' . $get . 'count":"' . trim($target_results) . '"';

    return $output;
}

function getLoads()
{
    $string = file_get_contents('/proc/loadavg');
    $loadavg = explode(' ', $string);

    $n = 0;
    for ($n = 0; $n < count($loadavg); $n++) {
        $key = 'load' . $n;
        if ($n < count($loadavg) - 1) {
            $output .= '"' . $key . '":"' . trim($loadavg[$n]) . '",';
        } else {
            $output .= '"' . $key . '":"' . trim($loadavg[$n]) . '"';
        }

    }

    return $output;
}

function getLEDIndicator($get = 'apache2')
{
    $cmd = 'ps aux | grep ' . $get . ' | grep -v grep | wc -l';
    $cmd_results = shell_exec($cmd);
    $output = ',"' . $get . '":"' . trim($cmd_results) . '"';
    return $output;
}

function getdiskPercent($get = 'md2')
{
    $df = 'df | grep ' . $get . ' | grep -v grep';
    $df_results = shell_exec($df);
    $usage = preg_split('/\s+/', $df_results);
    $percent = explode('%', $usage[4]);
    $output = ',"' . $get . '":"' . trim($percent[0]) . '"';
    return $output;
}

function getMem($get = 'MemFree')
{
    $getMem = 'cat /proc/meminfo | grep ' . $get;
    $getMem_results = shell_exec($getMem);
    $mem = preg_split('/\s+/', $getMem_results);
    $output = ',"' . strtolower($get) . '":"' . trim($mem[1]) . '"';
    return $output;
}

function getprocessCPU($get = 'mysqld')
{
    $sum = 0;
    if ($get == 'all') {
        $doit = 'ps -eopcpu,comm';
    } else {
        $doit = 'ps -eopcpu,comm | grep ' . $get;
    }

    $results = shell_exec($doit);
    if ($get == 'all') {
        $clean = explode(' ', $results);
    } else {
        $clean = explode($get, $results);
    }

    foreach ($clean as $line) {

        if (s_has_letters(trim($line)) or trim($line) == '') {
            continue;}
        {
            if (strlen($line) > 0) {
                $sum += trim($line);
            }

        }
    }
    $output = ',"' . strtolower($get) . '":"' . trim($sum) . '"';
    return $output;
}

function s_has_letters($string)
{
    return preg_match('/[a-zA-Z]/', $string);
}

Here is some sample JSON output. Please note in a future update to this code I will update the loadavg names in the JSON to more accurately describe the indicators:

Code:
{
  "load0": "0.69",
  "load1": "0.57",
  "load2": "0.56",
  "load3": "1/291",
  "load4": "29704",
  "mysqldump": "0",
  "gzip": "0",
  "find": "0",
  "rsync": "0",
  "md2": "18",
  "memfree": "54970768",
  "cached": "5185620",
  "all": "39.5",
  "apache2": "35.8",
  "mysqld": "3.6",
  "apache2count": "93",
  "rsynccount": "0"
}

In the next post; I'll post the Oracle JET module, including the Javascript and HTML files.
# 2  
Old 10-22-2018
Here is a screen shot of the dashboard. Will post the Oracle JET code in the next posts:

Image
# 3  
Old 10-22-2018
Oracle JET - loadavg.html module

Creating a Simple Linux Dashboard with Oracle Jet - Part 2 the Oracle Jet HTML Module Code

Here is the loadavg.html module which is situated in the views folder of my Oracle JET simple Linux dashboard project:

Code:
<style>
    .neo-netdown {
        color: black;
    }

    .circular-status-meter-common {
        text-align: center;
        margin-top: 5px;
        margin-bottom: 5px;
        width: auto;
    }

    .circular-status-meter-large {
        height: 100px;
    }

    .circular-status-meter-small {
        height: 50px;
    }

    .neo-gauge {
        display: inline-block;
    }

    .neo-oj-gauge {
        background-color: white;
    }
</style>


<div class="neo-netdown  oj-flex">
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="load1" color="green" step="1" outer-radius="0.5" label="[[lable1]]"
            min="0" max="5" value="[[load1]]" orientation="circular" class="circular-status-meter-common circular-status-meter-large neo-oj-gauge">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Load Avg 1m</h5>
    </div>
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="load5" color="green" label="[[lable5]]" min="0" max="5" value="[[load5]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Load Avg 5m</h5>
    </div>
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="load15" color="green" label="[[lable15]]" min="0" max="5" value="[[load15]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Load Avg 15m</h5>
    </div>
    <div class="neo-gauge mysqldump oj-flex-item">
        <oj-status-meter-gauge readonly="true" inner-radius="0" id="mysqldump" color="red" min="0" max="1" value="[[mysqldump]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">mysqldump</h5>
    </div>
</div>

<div class="neo-netdown oj-flex">

    <div class="neo-gauge oj-flex-item" style="display:none">
        <oj-status-meter-gauge readonly="true" id="activeprocs" label="[[processes]]" color="green" min="0" max="10"
            value="[[activeprocs]]" orientation="circular" class="circular-status-meter-common circular-status-meter-large"
            converter='{value:{
                "type":"text", 
                "options": {"style": "text"}'>
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Active Processes</h5>
    </div>
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="alltheprocs" label="[[processes]]" color="green" min="0" max="600"
            value="[[alltheprocs]]" orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Server</h5>
    </div>

    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="apache2count" label="[[processes]]" color="green" min="0" max="150"
            value="[[apache2count]]" orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Apache</h5>
    </div>

    <div class="neo-gauge oj-flex-item" style="display:none;">
        <oj-status-meter-gauge readonly="true" id="lastpid" color="green" min="7000" max="30000" value="[[lastpid]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Last PID</h5>
    </div>

    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="wolval" label="[[users]]" color="green" min="0" max="5000" value="[[wolval]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">WOL Total</h5>
    </div>
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" inner-radius="0" id="gzip" color="red" min="0" max="1" value="[[gzip]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">gzip</h5>
    </div>
</div>
<div class="neo-netdown oj-flex">
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" d="allcpus" label="[[cpu]]" metric-label="[[customMetricLabel]]" color="green"
            min="0" max="100" value="[[all]]" orientation="circular" class="circular-status-meter-common circular-status-meter-large"
            readonly="true">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Server</h5>
    </div>
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="apache2" label="[[cpu]]" metric-label="[[customMetricLabel]]" color="green"
            min="0" max="100" value="[[apache2]]" orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Apache</h5>
    </div>

    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="mysqld" readonly=true label="[[cpu]]" metric-label="[[customMetricLabel]]"
            color="green" min="0" max="100" value="[[mysqld]]" orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">MySQL</h5>
    </div>

    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" inner-radius="0" id="rsync" color="red" min="0" max="1" value="[[rsync]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">rsync</h5>
    </div>
</div>

<div class="neo-netdown oj-flex">
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="diskusage" label="[[diskname]]" metric-label="[[customMetricLabel]]"
            color="green" min="0" max="100" value="[[diskusage]]" orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Disk Usage</h5>
    </div>
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="freemem" label="[[kb]]" color="green" min="0" max="65842320" value="[[freemem]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Free Mem</h5>
    </div>
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" id="cachedmem" label="[[kb]]" color="green" min="0" max="65842320" value="[[cachedmem]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">Cached Mem</h5>
    </div>
    <div class="neo-gauge oj-flex-item">
        <oj-status-meter-gauge readonly="true" inner-radius="0" id="find" color="red" min="0" max="1" value="[[find]]"
            orientation="circular" class="circular-status-meter-common circular-status-meter-large">
        </oj-status-meter-gauge>
        <h5 class="circular-status-meter-common neo-netdown">find</h5>
    </div>

</div>

# 4  
Old 10-22-2018
Creating a Simple Linux Dashboard with Oracle Jet - Part 2 the Oracle Jet JS Module Code


Here is the loadavg.js part of my simple Linux dashboard module, situated in the Oracle JET viewModels folder of my project:

Code:
/*
 * loadavg.js
 */
$(function() {
  //$(".neo-box").hide();
});
define([
  "ojs/ojcore",
  "knockout",
  "jquery",
  "text!data/data.json",
  "ojs/ojknockout",
  "ojs/ojvalidation-number",
  "ojs/ojgauge",
  "ojs/ojchart"
], function(oj, ko, $, file) {
  function UnixViewModel() {
    var self = this;
    var release = true;

   // the following code is an quick and easy way to play around with the $.getJSON timers:

    if (localStorage.getItem("loadTimer") !== null) {
      if (localStorage.getItem("loadTimer") < 1000)
        localStorage.setItem("loadTimer", "1000");
      loadTimer = localStorage.getItem("loadTimer");
    } else {
      if (release == false) {
        var loadTimer = 1000;
      } else {
        var loadTimer = 5000;
      }
      localStorage.setItem("loadTimer", loadTimer);
    }
    if (localStorage.getItem("wolTimer") !== null) {
      if (localStorage.getItem("wolTimer") < 1000)
        localStorage.setItem("wolTimer", "1000");
      wolTimer = localStorage.getItem("wolTimer");
    } else {
      if (release == false) {
        var wolTimer = 5000;
      } else {
        var wolTimer = 10000;
      }
      localStorage.setItem("wolTimer", wolTimer);
    }

    // TODO:  setup vars should be moved to a JSON config file 

    var serverForum = "https://www.yourserver.com/forumvars.php";
    var serverMain = "https://www.yourserver.com/ojetcallback.php";

    // in no particular order

    self.wolval = ko.observable(0);
    self.load1 = ko.observable(0);
    self.load5 = ko.observable(0);
    self.load15 = ko.observable(0);
    self.diskusage = ko.observable(0);
    self.cachedmem = ko.observable(0);
    self.all = ko.observable(0);
    self.apache2 = ko.observable(0);
    self.mysqld = ko.observable(0);
    self.rsync = ko.observable(0);
    self.apache2count = ko.observable(0);
    self.alltheprocs = ko.observable(0);
    self.activeprocs = ko.observable(0);
    self.mysqldump = ko.observable(0);
    self.gzip = ko.observable(0);
    self.find = ko.observable(0);
    self.lastpid = ko.observable(0);
    self.freemem = ko.observable(0);
    self.allprocs = ko.observable(0);

    self.customMetricLabel = ko.observable({
      rendered: "on",
      textType: "percent",
      style: { fontWeight: "bold", color: "black" }
    });

    self.lable1 = { text: "1min" };
    self.lable5 = { text: "5min" };
    self.lable15 = { text: "15min" };
    self.percent = { text: "percent" };
    self.kb = { text: "kB" };
    self.cpu = { text: "cpu" };
    self.processes = { text: "processes" };
    self.users = { text: "users" };
    self.diskname = { text: "/dev/md2" };
    self.customSvgStyle = { fill: "url(" + document.URL + "#pattern)" };

    // this code is used to get the specific number of online users from the forum
    // and is specific to our forum application (PHP code not provided for the serverForum
    // URL in the next few lines, but post back in this thread if you want me to post it.

    setInterval(function() {
      $.getJSON(serverForum, function(wol) {
        $.each(wol, function(wolkey, wolval) {
          self.wolval(parseFloat(wolval));
          if (parseFloat(wolval) < 400) {
            $("#wolval").attr({ color: "orange" });
          } else if (parseFloat(wolval) > 3000) {
            $("#wolval").attr({ color: "red" });
          } else {
            $("#wolval").attr({ color: "green" });
          }
        });
        // console.log(JSON.stringify(wol));
      });
    }, wolTimer);

    // here is the main part of the module that refreshes most of the indicators in the dash:

    setInterval(function() {
      $.getJSON(serverMain, function(json) {
        // console.log(JSON.stringify(json));

        $.each(json, function(key, val) {
          switch (key) {
            case "load0":
              self.load1(parseFloat(val));
              if (parseFloat(val) > 0.99) {
                $("#load1").attr({ color: "red" });
              } else {
                $("#load1").attr({ color: "green" });
              }
              break;
            case "load1":
              self.load5(parseFloat(val));
              if (parseFloat(val) > 0.75) {
                $("#load5").attr({ color: "red" });
              } else {
                $("#load5").attr({ color: "green" });
              }
              break;
            case "load2":
              self.load15(parseFloat(val));
              if (parseFloat(val) > 0.65) {
                $("#load15").attr({ color: "red" });
              } else {
                $("#load15").attr({ color: "green" });
              }
              break;
            case "load3":
              var vals = val.split("/");
              var active = Math.round(parseInt(vals[0]));
              var all = Math.round(parseInt(vals[1]));
              self.allprocs(val);
              self.activeprocs(active);
              self.alltheprocs(all);
              if (active > 6) {
                $("#activeprocs").attr({ color: "red" });
              } else {
                $("#activeprocs").attr({ color: "green" });
              }
              if (all > 400) {
                $("#alltheprocs").attr({ color: "red" });
              } else {
                $("#alltheprocs").attr({ color: "green" });
              }
              break;
            case "load4":
              self.lastpid(parseInt(val));
              break;
            case "apache2count":
              self.apache2count(parseInt(val));
              if (val > 100) {
                $("#apache2count").attr({ color: "red" });
              } else {
                $("#apache2count").attr({ color: "green" });
              }
              break;
            case "mysqldump":
              self.mysqldump(parseInt(val));
              if (val == 0) $("#mysqldump").attr({ color: "green" });
              else $("#mysqldump").attr({ color: "red" });
              break;
            case "gzip":
              self.gzip(parseInt(val));
              if (val == 0) $("#gzip").attr({ color: "green" });
              else $("#gzip").attr({ color: "red" });
              break;
            case "find":
              self.find(parseInt(val));
              if (val == 0) $("#find").attr({ color: "green" });
              else $("#find").attr({ color: "red" });
              break;
            case "md2":
              self.diskusage(parseInt(val));
              if (val > 60) {
                $("#diskusage").attr({ color: "red" });
                self.customMetricLabel = {
                  rendered: "on",
                  textType: "percent",
                  style: { fontWeight: "bold", color: "red" }
                };
              } else {
                $("#diskusage").attr({ color: "green" });
              }

              break;
            case "memfree":
              self.freemem(parseInt(val));
              if (parseInt(val) < 10000000) {
                $("#freemem").attr({ color: "red" });
              } else {
                $("#freemem").attr({ color: "green" });
              }
              break;
            case "cached":
              self.cachedmem(parseFloat(val));
              if (parseInt(val) > 50000000) {
                $("#cachedmem").attr({ color: "red" });
              } else {
                $("#cachedmem").attr({ color: "green" });
              }
              break;
            case "all":
              self.all(parseFloat(val));
              if (parseFloat(val) > 75) {
                $("#allcpus").attr({ color: "red" });
              } else {
                $("#allcpus").attr({ color: "green" });
              }
              break;
            case "apache2":
              self.apache2(parseInt(val));
              if (parseFloat(val) > 75) {
                $("#apache2").attr({ color: "red" });
              } else {
                $("#apache2").attr({ color: "green" });
              }
              break;
            case "mysqld":
              self.mysqld(parseFloat(val));
              if (parseFloat(val) > 75) {
                $("#mysqld").attr({ color: "red" });
              } else {
                $("#mysqld").attr({ color: "green" });
              }
              break;
            case "rsynccount":
              self.rsync(parseInt(val));
              if (val == 0) $("#rsync").attr({ color: "green" });
              else $("#rsync").attr({ color: "red" });
              break;
            default:
          }
          $(".neo-netdown").css({ color: "black" });
          // console.log("success items " + items.length + " " + val);
        });
      })

        //  self.datasource = ko.observableArray(items);
        .done(function() {
          //console.log("second success");
        })
        .fail(function() {

         // this code simply turns the indicators all red when the network is down or there is some
         // other connectivity or server issue which caused the call to the server to fail:

          var netFail = true;
          $(".neo-netdown").css({ color: "red" });
          $(
            "#load1,#load5,#load15, #activeprocs, #alltheprocs, #lastpid, #wolval,#allcpus, #apache2,#mysqld, #apache2count, #rsync, #diskusage, #cachedmem, #freemem"
          ).attr({
            color: "red"
          });
          console.log("error");
        })
        .always(function() {
          //console.log("complete");
        });
    }, loadTimer);

    // Below are a set of the ViewModel methods invoked by the oj-module component.
    // Please reference the oj-module jsDoc for additional information.

    /**
     * Optional ViewModel method invoked after the View is inserted into the
     * document DOM.  The application can put logic that requires the DOM being
     * attached here.
     * This method might be called multiple times - after the View is created
     * and inserted into the DOM and after the View is reconnected
     * after being disconnected.
     */
    self.connected = function() {
      // Implement if needed
    };

    /**
     * Optional ViewModel method invoked after the View is disconnected from the DOM.
     */
    self.disconnected = function() {
      //console.log(" self.disconnected = function()");
      // Implement if needed
    };

    /**
     * Optional ViewModel method invoked after transition to the new View is complete.
     * That includes any possible animation between the old and the new View.
     */
    self.transitionCompleted = function() {
      // Implement if needed
    };
  }

  /*
       * Returns a constructor for the ViewModel so that the ViewModel is constructed
       * each time the view is displayed.  Return an instance of the ViewModel if
       * only one instance of the ViewModel is needed.
       */

  return new UnixViewModel();
});

# 5  
Old 10-22-2018
appController.js

Creating a Simple Linux Dashboard with Oracle Jet - Part 4 the Oracle Jet JS appController.js Code

For completeness. appDontroller.js

Code:
/**
 * @license
 * Copyright (c) 2014, 2018, Oracle and/or its affiliates.
 * The Universal Permissive License (UPL), Version 1.0
 */
/*
 * Your application specific code will go here
 */
define([
  "ojs/ojcore",
  "knockout",
  "ojs/ojmodule-element-utils",
  "ojs/ojmodule-element",
  "ojs/ojrouter",
  "ojs/ojknockout",
  "ojs/ojarraytabledatasource",
  "ojs/ojoffcanvas"
], function(oj, ko, moduleUtils) {
  function ControllerViewModel() {
    var self = this;

    // Media queries for repsonsive layouts
    var smQuery = oj.ResponsiveUtils.getFrameworkQuery(
      oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.SM_ONLY
    );
    self.smScreen = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(
      smQuery
    );
    var mdQuery = oj.ResponsiveUtils.getFrameworkQuery(
      oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.MD_UP
    );
    self.mdScreen = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(
      mdQuery
    );

    // Router setup
    self.router = oj.Router.rootInstance;
    self.router.configure({
      loadavg: { label: "UNIX.COM", isDefault: true }
      // dashboard: { label: "Warm StandBy" }
      // incidents: { label: "Incidents" },
      //customers: { label: "Customers" },
      // about: { label: "About" }
    });
    oj.Router.defaults["urlAdapter"] = new oj.Router.urlParamAdapter();

    self.moduleConfig = ko.observable({ view: [], viewModel: null });

    self.loadModule = function() {
      ko.computed(function() {
        var name = self.router.moduleConfig.name();
        var viewPath = "views/" + name + ".html";
        var modelPath = "viewModels/" + name;
        var masterPromise = Promise.all([
          moduleUtils.createView({ viewPath: viewPath }),
          moduleUtils.createViewModel({ viewModelPath: modelPath })
        ]);
        masterPromise.then(function(values) {
          self.moduleConfig({ view: values[0], viewModel: values[1] });
        });
      });
    };

    // Navigation setup
    var navData = [
      {
        name: "UNIX.COM",
        id: "loadavg",
        iconClass:
          "oj-navigationlist-item-icon demo-icon-font-24 demo-chart-icon-24 neo-color"
      }
    ];
    self.navDataSource = new oj.ArrayTableDataSource(navData, {
      idAttribute: "id"
    });

    // Drawer
    // Close offcanvas on medium and larger screens
    self.mdScreen.subscribe(function() {
      oj.OffcanvasUtils.close(self.drawerParams);
    });
    self.drawerParams = {
      displayMode: "push",
      selector: "#navDrawer",
      content: "#pageContent"
    };
    // Called by navigation drawer toggle button and after selection of nav drawer item
    self.toggleDrawer = function() {
      return oj.OffcanvasUtils.toggle(self.drawerParams);
    };
    // Add a close listener so we can move focus back to the toggle button when the drawer closes
    $("#navDrawer").on("ojclose", function() {
      $("#drawerToggleButton").focus();
    });

    // Header
    // Application Name used in Branding Area
    self.appName = ko.observable("UNIX.COM Dashboard");
    // User Info used in Global Navigation area
    self.userLogin = ko.observable("neo@unix.com");
    self.neoVersion = ko.observable("v0.28");

    // Footer
    function footerLink(name, id, linkTarget) {
      this.name = name;
      this.linkId = id;
      this.linkTarget = linkTarget;
    }
    self.footerLinks = ko.observableArray([
      new footerLink("Home", "visitUNIX", "https://www.unix.com/"),
      new footerLink("WOL", "wol", "https://www.unix.com/online.php")
    ]);
  }

  return new ControllerViewModel();
});

# 6  
Old 10-22-2018
Creating a Simple Linux Dashboard with Oracle Jet - Part 5 the Oracle Jet index.html Code

Also for completeness and for reference: index.html

Code:
<!DOCTYPE html>
<html lang="en-us">

<head>
  <title>UNIX.COM Dashboard</title>

  <meta charset="UTF-8">
  <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1">
  <link rel="icon" href="css/images/favicon.ico" type="image/x-icon" />

  <!-- This is the main css file for the default Alta theme -->
  <!-- injector:theme -->
  <link rel="stylesheet" href="css/libs/oj/v6.0.0/alta/oj-alta-min.css" type="text/css" />
  <!-- endinjector -->

  <!-- This contains icon fonts used by the starter template -->
  <link rel="stylesheet" href="css/demo-alta-site-min.css" type="text/css" />

  <!-- This is where you would add any app specific styling -->
  <link rel="stylesheet" href="css/app.css" type="text/css" />
  <style>
    .neo-color{
  color:rgba(1, 8, 94,0.9) !important;
}
</style>
</head>

<body class="oj-web-applayout-body">
  <!-- Template for rendering navigation items shared between nav bar and nav list -->
  <script type="text/html" id="navTemplate">
      <li><a href="#">
        <span :class="[[$data['iconClass']]]"></span>
        <oj-bind-text value="[[$data['name']]]"></oj-bind-text>
      </a></li>
    </script>

  <div id="globalBody" class="oj-offcanvas-outer-wrapper oj-offcanvas-page">
    <!--
         ** Oracle JET V6.0.0 web application navigation drawer pattern.
         ** Please see the demos under Cookbook/Patterns/App Shell: Web
         ** and the CSS documentation under Support/API Docs/Non-Component Styling
         ** on the JET website for more information on how to use this pattern. 
         ** The off-canvas section is used when the browser is resized to a smaller media
         ** query size for a phone format and hidden until a user clicks on
         ** the header hamburger icon.
      -->
    <div id="navDrawer" role="navigation" class="oj-contrast-marker oj-web-applayout-offcanvas oj-offcanvas-start neo-color">
      <oj-navigation-list data="[[navDataSource]]" edge="start" item.renderer="[[oj.KnockoutTemplateUtils.getRenderer('navTemplate', true)]]"
        on-click="[[toggleDrawer]]" selection="{{router.stateId}}">
      </oj-navigation-list>
    </div>
    <div id="
        pageContent" class="oj-web-applayout-page">
      <!--
           ** Oracle JET V6.0.0 web application header pattern.
           ** Please see the demos under Cookbook/Patterns/App Shell: Web
           ** and the CSS documentation under Support/API Docs/Non-Component Styling
           ** on the JET website for more information on how to use this pattern.
        -->
      <header role="banner" class="oj-web-applayout-header">
        <div class="oj-web-applayout-max-width oj-flex-bar oj-sm-align-items-center">
          <!-- Offcanvas toggle button -->
          <div class="oj-flex-bar-start oj-md-hide">
            <oj-button id="drawerToggleButton" class="oj-button-lg" on-oj-action="[[toggleDrawer]]" chroming="half"
              display="icons">
              <span slot="startIcon" class="oj-web-applayout-offcanvas-icon"></span>
              <span>Application Navigation</span>
            </oj-button>
          </div>
          <div class="oj-flex-bar-middle oj-sm-align-items-baseline ">
            <span style="display:none" role="img" class="oj-icon demo-oracle-icon" title="Oracle Logo" alt="Oracle Logo"></span>
            <h1 class="oj-sm-only-hide oj-web-applayout-header-title neo-color" title="Application Name" style="font-weight: bold;margin:50px 0px 0px 20px;font-size:1.5em">
              <oj-bind-text value="[[appName]]"></oj-bind-text>
            </h1>
          </div>

       <!--
         ** the code below was "display:none;" 'd out of the app
         ** because did not yet fully integrate the user session functions yet
      -->

          <div class="oj-flex-bar-end" style="display:none;">
            <!-- Responsive Toolbar -->
            <oj-toolbar>
              <oj-menu-button id="userMenu" display="[[smScreen() ? 'icons' : 'all']]" chroming="half">
                <span>
                  <oj-bind-text value="[[userLogin]]"></oj-bind-text>
                </span>
                <span slot="endIcon" :class="[[{'oj-icon demo-appheader-avatar': smScreen(), 'oj-component-icon oj-button-menu-dropdown-icon': !smScreen()}]]"></span>
                <oj-menu id="menu1" slot="menu" style="display:none">
                  <oj-option id="pref" value="pref">Preferences</oj-option>
                  <oj-option id="help" value="help">Help</oj-option>
                  <oj-option id="about" value="about">About</oj-option>
                  <oj-option id="out" value="out">Sign Out</oj-option>
                </oj-menu>
              </oj-menu-button>
            </oj-toolbar>
          </div>
        </div>
        <div role="navigation" class="oj-web-applayout-max-width oj-web-applayout-navbar">
          <oj-navigation-list class="
          oj-sm-only-hide oj-md-condense oj-md-justify-content-flex-end neo-color"
            data="[[navDataSource]]" edge="top" item.renderer="[[oj.KnockoutTemplateUtils.getRenderer('navTemplate', true)]]"
            selection="{{router.stateId}}">
          </oj-navigation-list>
        </div>
      </header>
      <oj-module role="main" class="oj-web-applayout-max-width oj-web-applayout-content neo-color" config="[[moduleConfig]]">
      </oj-module>
      <footer class="oj-web-applayout-footer neo-color" role="contentinfo">
        <div style="display:inline-block" class="oj-web-applayout-footer-item oj-web-applayout-max-width neo-color">
          <ul>
            <oj-bind-for-each data="[[footerLinks]]">
              <template>
                <li><a class="neo-color" :id="[[$current.data.linkId]]" :href="[[$current.data.linkTarget]]">
                    <oj-bind-text value="[[$current.data.name]]"></oj-bind-text>
                  </a></li>
              </template>
            </oj-bind-for-each>
          </ul>
        </div>
        <div style="display:inline-block" class="oj-web-applayout-footer-item oj-web-applayout-max-width oj-text-secondary-color oj-text-sm neo-color">
          <oj-bind-text value="[[appName]]"></oj-bind-text>
          <oj-bind-text value="[[neoVersion]]"></oj-bind-text>
        </div>
      </footer>
    </div>
  </div>

  <script type="text/javascript" src="js/libs/require/require.js"></script>
  <script type="text/javascript" src="js/main.js"></script>

</body>

</html>

# 7  
Old 10-22-2018
And this completes my "homework project" for the excellent Oracle JET online course:


Soar higher with Oracle JavaScript Extension Toolkit (JET)

I strongly recommend this Oracle JET course for anyone interested in custom web development.

The code I shared could be optimized, or course, and a lot of vars could be moved to a JSON config file, etc; but this project was a good way to learn Oracle JET basics, and the dashboard is useful and works.

Additional indicators and modules can easily be added as required; and we are only scratching the surface of Oracle JET in this simple example.

Ref: Creating a Very Simple Linux Dashboard with Ora... | Oracle Community
Login or Register to Ask a Question

Previous Thread | Next Thread

4 More Discussions You Might Find Interesting

1. Web Development

A Quick Web Developers Review of Oracle JET

Oracle JET is marketed as a kind of "anti-framework" approach to web development but from my experience Oracle JET is just another type of framework. So, I would describe JET as "a meta-framework" because JET is a framework that is built to import and use other frameworks and Javascript... (4 Replies)
Discussion started by: Neo
4 Replies

2. Web Development

Oracle JET 4.x - Lesson 1 - Part 9: Oracle JET Cookbook (Gauges and Ints)

Working on: 10. Lesson 1: Oracle JET 4.x - Lesson 1 - Part 9: Oracle JET Cookbook (which I highly recommend) and using the server loadavg code I wrote and have been adding gauges. All is great so far, and I'm loving JET, but have ran into an issue. Here is the loadavg.js code: /** ... (1 Reply)
Discussion started by: Neo
1 Replies

3. Web Development

Oracle Jet - LP: 10. Lesson 1: Oracle JET 4.x - Lesson 1 - Part 4: Data Binding

Working on LP: 10. Lesson 1: Oracle JET 4.x - Lesson 1 - Part 4: Data Binding in this Oracle JET online course - Soar higher with Oracle JavaScript Extension Toolkit (JET), I have created this code for incidents.js I cannot get the load average data in this Oracle JET test to update the... (4 Replies)
Discussion started by: Neo
4 Replies

4. What is on Your Mind?

Excellent Oracle JET Video - "Finally, JavaScript Is Easy!"

This is a video well worth watching if you have any interests at all in the future of web development, web development frameworks and Javascript. https://www.youtube.com/watch?v=V8mhIEeTMCc . Fixed typo in Oracle Jet URL (oraclejet.org) (0 Replies)
Discussion started by: Neo
0 Replies
Login or Register to Ask a Question