JANUS HTML Reporting

Bei der Projektarbeit für ein Labware LIMS - System hatte ich ein HTML Reporting Framework zu implementieren.
Der Labware - Client erzeugt HTML, das in Modulen wie dem Sample Folder, der Info Rule oder auch in Visual Workflows verwendet werden kann.
Was sehr früh störte, war dass mittels des Labware Clients lediglich statisches HTML generiert werden kann. Weiterführende Links oder "Load on demand" und damit der Aufbau perfomanter und interaktiver Seiten sind ohne einen richtigen Webserver nicht möglich.

So fasste ich den Entschluss, Node.JS als frei verfügbare Server-Komponente zu verwenden. Mittels Node.JS läßt sich JavaScript auch auf der Backend - Seite verwenden. Viele Bibliotheken, die aus dem Client - Bereich bekannt sind gibt es auch als Server - Variante oder sie sind direkt kompatibel. Im Node.JS - Umfeld sind viele Bibliotheken Open Source verfügbar, was die Verwendung attraktiv macht.

Node.JS verwendet zum Publizieren von Eigenentwicklungen, aber auch zum Herunterladen von Fremdbibliotheken ein zentrales Repository namens npm .

Projektfokus

  • Funktional
    • HTML Report Server für Windows-Clientsysteme, in diesem Fall Labware LIMS
    • Aus gegebenem Anlass: Die " JANUS Code Quality Suite " - ein "Diff-Tool" für Labware LIMS
    • Grafische Visualisierung der Daten
  • Technisch: Auseinandersetzung mit modernen Technologien
    • MongoDB als dokumentenbasierte NoSQL-Datenbank
    • Docker als Container- Option für das Backend

Backend-Komponenten

  • node-oracledb und mssql für den Zugriff auf Oracle- und MSSQL-Datenbanken
  • Express als http und https - Server
  • Socket.IO für die Websocket - Kommunikation mit älteren Browsern wie IE8 - nicht mehr benötigt :-)
  • Passport.js für die Benutzer - Authentifizierung
  • mammoth , eine Bibliothek zur Konvertierung von Microsoft Word - Dokumenten in HTML
  • Office.JS für Web-basierte Plugins für Microsoft Office - Produkte

Client-Komponenten

Charting

Basics

  • jQuery
  • Underscore
  • Twitter Bootstrap
  • require.js

JANUS verwendet folgende Charting - Bibliotheken:

Sonstige Bibliotheken

Nicht nur für JANUS verwendet, sondern Teil auch anderer Web - basierter Entwicklungen und Oracle APEX - Projekte

  • Oracle JET - "Oracle JET empowers developers by providing a modular open source toolkit"
  • Knockout - "Simplify dynamic JavaScript UIs with Model-View / View-Model pattern"
  • CodeMirror - "a versatile text editor implemented in JavaScript"
  • ACE Code Editor - "The high performance code editor for the web"
  • Highlight.JS - "Syntax highlighting for the Web"
  • PaPaParse - "The powerful, in-browser CSV parser for big boys and girls"
  • FancyTree - "Dynamic tree view plugin for jQuery"
  • Viewer.JS - "Documents. On your site. Now."
  • CKEditor - "Smart WYSIWYG editor components with collaborative editing"
  • Google DiffMatchPath - "High-performance library in multiple languages that finds differences and matches in plain text and applies patches"
  • JSZip - "JSZip is a javascript library for creating, reading and editing .zip files, with a lovely and simple API."
  • QRious - "QRious is a pure JavaScript library for generating QR codes using HTML5 canvas"
  • Split.JS - "Split.js is a 2kb unopinionated utility for resizeable split views"

Der npm Build - Prozess

Mittels npm lassen sich Builds automatisieren. Es wird eine Package-Datei definiert, die alle Abhängigkeiten der Software beinhaltet.
Hier die package.json - Datei für JANUS .
Gestartet wird der Build aus der Konsole mittels:
                                                        
                                                            npm install
                                                        
                                                    
                                                

MongoDB

Labware LIMS kann programmiert werden. Der Code, der dabei entsteht befindet sich in verschiedenen Tabellen wie z.B. SUBROUTINE, CALCULATION oder FORMAT_CALCULATION.

JANUS erlaubt es, in den entsprechenden Tabellen nach Code zu suchen, um z.B. die Verwendung einer bestimmten Subroutine oder einer Variablen bestimmten Namens herauszufinden.

Das ist mit SQL möglich, ist aber langsam, da nicht nur eine Tabelle auf Code hin überprüft werden muss sondern eben mehrere. MongoDB als dokumentenbasierte NoSQL Datenbank ist ideal, um Text in Objekten zu suchen.

MongoDB Data Store aufbauen

Zuerst muss der MongoDB Store aufgebaut werden, indem die Daten aus der Oracle-DB ausgelesen werden

Das geschieht durech eine SQL SELECT * - Abfrage gegen die entsprechenden Tabellen, die Treffer werden in die MongoDB persistiert.

Wir benötigen folgende Packages

  • nodeoracledb
  • mongodb
Hier Code zur Persistierung von SQL-Abfragen in einer MongoDB

Volltextsuche im Store

Die Volltextsuche in einer MongoDB gestaltet sich unglaublich viel schneller als in einer relationalen Datenbank.

Die Abfrage erfolgt allerdings nicht über eine Abfragesprache wie SQL, sondern mittels des Aufrufs von bestimmten befehlen wie find(), die gegen eine Datenmenge (Collection) ausgeführt werden.

Die find() - Funktion erwartert als Parameter vorkonfigurierte JSON - Objekte mit den Abfrageparametern.

                                                        
                                                            function find(database, collection, expression, callBack) {
    var projection;
    projection = {};
    var sortObj = {"NAME": 1};
    mongoClient.connect(mongoURL, function (err, db) {
        if (err) throw err;
        var dbo = db.db(database);
        try {
            dbo.collection(collection).find(expression, projection).sort(sortObj)
                .toArray(function (err, result) {
                    if (err) throw err;
                    callBack(result);
                    db.close();
                });
        } catch(e){
            console.log("mongo.find: error:" + expression + ":");
        }
    });
}


var searchExpr = "ArrayFromCSV";
var expression =
    {
        $text:
            {
                $search: "\"" + searchExpr + "\"",
                $caseSensitive: false,
            }
    }

find("DEV", "SUBROUTINE", expression, function(result){
    console.log(result);
})
                                                        
                                                    

Das Ganze kann dann in einer Webanwendung etwa so aussehen:

Gantt Chart

Docker

...to be done...