commit 3838ca66d9cc3e49786aac60f443bc2ccfecfacc
Author: David Sorber <david.sorber@gmail.com>
Date:   Wed Mar 13 18:35:29 2019 -0400

    Thanks to hbkcd, the interface portion can now just be some javascript
    (and CSS and HTML).

diff --git a/software/hbkif/conf/apache/hbkif.conf b/software/hbkif/conf/apache/hbkif.conf
deleted file mode 100644
index e272504..0000000
--- a/software/hbkif/conf/apache/hbkif.conf
+++ /dev/null
@@ -1,19 +0,0 @@
-WSGIScriptAlias /hbkif    /home/dsorber/Documents/repo/software/hbkif/hbkif.wsgi
-<Directory /home/dsorber/Documents/repo/software/hbkif/>
-        WSGIApplicationGroup %{GLOBAL}
-        WSGIPassAuthorization On
-        Require all granted
-</Directory>
-
-#Alias "/docs/uspto/claims" "/ryftone/regression/uspto/claims/"
-#<Directory /ryftone/regression/uspto/claims/>
-#        Options +Indexes
-#        Require all granted
-#</Directory>
-
-#Alias "/docs/uspto/parsed" "/ryftone/regression/uspto/split-parsed/"
-#<Directory /ryftone/regression/uspto/split-parsed/>
-#        Options +Indexes
-#        Require all granted
-#</Directory>
-
diff --git a/software/hbkif/hbkif.wsgi b/software/hbkif/hbkif.wsgi
deleted file mode 100755
index 0525215..0000000
--- a/software/hbkif/hbkif.wsgi
+++ /dev/null
@@ -1,38 +0,0 @@
-import re
-
-from hbkif.controllers.status import StatusController
-from hbkif.controllers.version import VersionController
-
-class Delegator(object):
-
-    def __init__(self):
-        pass
-
-    def __call__(self, environ, start_response):
-        path = environ['PATH_INFO']
-
-        if re.match('^/status(/)?$', path):
-            # Authenticate user
-            controller = StatusController(environ)
-            status, headers, body = controller.generate_response()
-        elif re.match('^/version(/)?$', path):
-           # All bookmarks page
-           controller = VersionController(environ)
-           status, headers, body = controller.generate_response()
-        else:
-            # User supplied an invalid URL
-            status = '200 OK'
-            body = 'hbkif is working!\n\nInvalid URL "{:s}"'.format(environ['PATH_INFO'])
-            body = body.encode()
-            headers = [('Content-Type', 'text/plain'),
-                       ('Content-Length', str(len(body)))]
-
-        # Send the status and response headers to the server
-        start_response(status, headers)
-        # Return the response body. (Notice it is wrapped in a list although it
-        # could be any iterable.)
-        return [body]
-        
-
-# Set the callable object
-application = Delegator()
diff --git a/software/hbkif/hbkif/__init__.py b/software/hbkif/hbkif/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/software/hbkif/hbkif/config.py b/software/hbkif/hbkif/config.py
deleted file mode 100644
index 4edad4e..0000000
--- a/software/hbkif/hbkif/config.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import logging
-
-# Version information
-VERSION_MAJOR  = 0
-VERSION_MINOR  = 1
-VERSION_BUGFIX = 0
-
-VERSION_STR = '{:d}.{:d}.{:d}'.format(VERSION_MAJOR, VERSION_MINOR, 
-                                      VERSION_BUGFIX)
-
-# Logfile information
-LOGFILE_PATH = '/var/log/hbkif/hbkif.log'
-LOG_FORMAT_STR = '%(asctime)s|%(levelname)s|%(filename)s:%(lineno)s|%(message)s'
-LOG_DATE_FORMAT_STR = '%a %b %d %H:%M:%S %Y'
-DEFAULT_LOG_LEVEL = logging.DEBUG
-
-
diff --git a/software/hbkif/hbkif/controllers/__init__.py b/software/hbkif/hbkif/controllers/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/software/hbkif/hbkif/controllers/base.py b/software/hbkif/hbkif/controllers/base.py
deleted file mode 100644
index c5c26d5..0000000
--- a/software/hbkif/hbkif/controllers/base.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import logging
-
-from hbkif.config import LOGFILE_PATH, LOG_FORMAT_STR, LOG_DATE_FORMAT_STR, \
-                         DEFAULT_LOG_LEVEL
-
-
-def auth_with_jwt(func):
-    """ Method decorator for setting up JWT authorization for controllers that
-    require it.
-    """
-    def func_wrapper(self, *args, **kwargs):
-        self.status = '403 Forbidden'
-        self.content = b''
-        
-        http_auth = self.environ.get('HTTP_AUTHORIZATION', '')
-        logging.debug('HTTP_AUTHORIZATION: {:s}'.format(http_auth))
-        if http_auth.startswith('Bearer '):
-            logging.debug('Attempting to authorize JWT')
-            self.token_valid, self.token_expired, self.user_id = \
-                authorize_jwt(http_auth[7:])
-            
-            if not self.token_expired:
-                # The token is not expired, so decide what to do next...
-                # For now we'll fully authorize if the token is valid (this 
-                # can be changed in the future if fine-grained permissions are 
-                # needed)
-                self.authorized = self.token_valid
-            else:
-                # TODO: handle expired... 
-                logging.debug('JWT is expired')
-        return func(self, *args, **kwargs)
-        
-    return func_wrapper
-    
-
-class BaseController(object):
-   
-    def __init__(self, environ):
-            
-        logging.basicConfig(format=LOG_FORMAT_STR, 
-                            datefmt=LOG_DATE_FORMAT_STR, 
-                            filename=LOGFILE_PATH, level=DEFAULT_LOG_LEVEL)
-       
-        self.environ = environ
-        self.content = ''
-        
-        # Override this as necessary
-        self.content_type = 'text/html; charset=utf-8'
-        
-        # Unless overridden status should be 200 for success
-        self.status = '200 OK'
-        
-        # Add custom headers as needed (formatted as tuple of: name, value)
-        self.custom_headers = []
-        
-        # Used for token authorization
-        self.authorized = False
-        self.token_valid = False
-        self.token_expired = False
-        self.user_id = None
-       
-    def build_content(self):
-        """ This method is used to build the content that is used to generate
-        the response. This method should populate the self.content dict.
-       
-        Override this method with your own to make this controller actually
-        do stuff!
-        """
-        return self.content.encode()
-       
-    def generate_response(self):
-        """ This function generates the actual response which is made up of two
-        parts, the response headers and the response body. It then returns the
-        status along with the headers and body.
-        """
-        body = self.build_content()
-                        
-        # Set the appropriate response headers
-        headers = [('Content-Type', self.content_type),
-                   ('Content-Length', str(len(body)))]
-        
-        # Include any custom headers
-        if self.custom_headers:
-            headers.extend(self.custom_headers)
-        
-        return self.status, headers, body
diff --git a/software/hbkif/hbkif/controllers/status.py b/software/hbkif/hbkif/controllers/status.py
deleted file mode 100644
index be1bba8..0000000
--- a/software/hbkif/hbkif/controllers/status.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import datetime
-import json
-import logging
-import subprocess
-
-from hbkif.controllers.base import BaseController
-from hbkif.config import VERSION_STR
-
-pwd = 'admin'
-
-class StatusController(BaseController):
-   
-    def __init__(self, environ):
-        super(StatusController, self).__init__(environ)
-        
-        # We return JSON
-        self.content_type = 'application/json'
-   
-    def build_content(self):
-        logging.info('Handling /status request')
-        
-        # Build command
-        cmd = 'ipmitool -I lanplus -U admin -P {:s} -H brutus-ipmi power status'
-        cmd = cmd.format(pwd)
-        proc = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, 
-                              stderr=subprocess.STDOUT)
-        
-        version_dict = {'returncode': proc.returncode,
-                        'status': proc.stdout.decode('utf-8').strip()}
-        self.content = json.dumps(version_dict).encode()
-        return self.content
diff --git a/software/hbkif/hbkif/controllers/version.py b/software/hbkif/hbkif/controllers/version.py
deleted file mode 100644
index 1a5f98d..0000000
--- a/software/hbkif/hbkif/controllers/version.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import datetime
-import json
-import logging
-
-from hbkif.controllers.base import BaseController
-from hbkif.config import VERSION_STR
-
-class VersionController(BaseController):
-   
-    def __init__(self, environ):
-        super(VersionController, self).__init__(environ)
-        
-        # We return JSON
-        self.content_type = 'application/json'
-   
-    def build_content(self):
-        logging.info('Handling /version request')
-        now = datetime.datetime.now()        
-        version_dict = {'version': VERSION_STR,
-                        'timestamp': now.strftime('%Y-%m-%d %H:%M:%S')}
-        self.content = json.dumps(version_dict).encode()
-        return self.content
diff --git a/software/hbkif/index.html b/software/hbkif/index.html
new file mode 100644
index 0000000..2ef975d
--- /dev/null
+++ b/software/hbkif/index.html
@@ -0,0 +1,189 @@
+<html>
+<!--
+    Note: This requires recent JQuery and JQuery UI (for the dope ass progress 
+          bar).
+-->
+
+    <head>
+    <title>hbkif</title>
+    
+    <style type="text/css">
+    @font-face {
+        font-family: Roboto;
+        src: url(htdocs/Roboto-Regular.ttf);
+    }
+
+    body {
+        background-color: #EEE;
+        font-family: Roboto, sans-serif, Arial;
+        font-size 18px;
+    }
+
+    div.queue_item {
+        width: 70%;
+        background-color: #FFF;
+        border: 1px solid #000;
+        padding: 0.4em;
+        margin-left: auto;
+        margin-right: auto;
+        margin-bottom: 1em;
+    }
+
+    div.position {
+        display: inline-block;
+        width: 10%;
+        font-size: 48px;
+        padding: 1%;
+        vertical-align: top;
+        text-align: center;
+    }
+
+    div.side {
+        display: inline-block;
+        width: 80%;
+    }
+
+    div.title {
+        margin-top: 1em;
+    }
+
+    div.particulars {
+        font-size: 12px;
+    }
+
+    .bold {
+        font-weight: bold;
+    }
+
+    div#pbar {
+        height: 8px;
+        margin-top: 0.6em;
+        margin-bottom: 0.6em;
+    }
+
+    </style>
+    <link rel="stylesheet" href="htdocs/js/jquery-ui/jquery-ui.css">
+
+    <script type="text/javascript" src="htdocs/js/jquery-3.3.1.min.js"></script>
+    <script src="htdocs/js/jquery-ui/jquery-ui.js"></script>
+		
+    <script type="text/javascript" language="javascript">
+        function format_size(bytes)
+        {
+            var tera = 1024 * 1024 * 1024 * 1024;
+            var giga = 1024 * 1024 * 1024;
+            var mega = 1024 * 1024;
+            var kilo = 1024;
+
+            var output;
+            if (bytes >= tera)
+            {   
+                output = (bytes / tera).toFixed(2) + ' TB';
+            }
+            else if (bytes >= giga)
+            {
+                output = (bytes / giga).toFixed(2) + ' GB';
+            }
+            else if (bytes >= mega)
+            {
+                output = (bytes / mega).toFixed(2) + ' MB';
+            }
+            else if (bytes >= kilo)
+            {
+                output = (bytes / kil).toFixed(2) + ' KB';
+            }
+            else
+            {
+                output = bytes + ' bytes';
+            }
+            
+            return output;
+        }
+
+        // Load JSON and display it
+        function getAndDisplay(event) {
+            $.getJSON("http://brutus:8081/queue", function(data) {
+                // Clear the stage DIV
+                $("#stage").empty();
+
+                var progress_value = 0.0;
+
+                // Iterate over the contents of the queue
+                var queue = data["queue"]                    
+                for (var idx = 0; idx < queue.length; idx++)
+                {
+                    // For the first entry parse out the progress value
+                    if (idx == 0)
+                    {
+                        progress_value = parseFloat(queue[idx]["status"].split(" ")[0]);
+                        $("#stage").append('<div class="queue_item">' + 
+                                           '    <div class="position">' + queue[idx]["position"] + '</div>' + 
+                                           '    <div class="side">' + 
+                                           '        <div class="title">' + queue[idx]["path"] + '</div>' + 
+                                           '        <div id="pbar"></div>' + 
+                                           '        <div class="particulars">' + 
+                                           '            <ul>' + 
+                                           '                <li><span class="bold">Status:</span> ' + queue[idx]["status"] + '</li>' + 
+                                           '                <li><span class="bold">Details:</span> ' + queue[idx]["width"] + 'x' + queue[idx]["height"] + ' @ ' + queue[idx]["framerate"] + 'fps</li>' + 
+                                           '                <li><span class="bold">Size:</span> ' + format_size(queue[idx]["initial_size"]) + '</li>' + 
+                                           '                <li><span class="bold">Added:</span> ' + queue[idx]["time_added"] + '</li>' + 
+                                           '                <li><span class="bold">Started:</span> ' + queue[idx]["encode_started"] + '</li>' + 
+                                           '            </ul>' + 
+                                           '        </div>' + 
+                                           '    </div>' + 
+                                           '</div>');
+                    }
+                    else
+                    {
+                        // There's got to be a better way...
+                        $("#stage").append('<div class="queue_item">' + 
+                                           '    <div class="position">' + queue[idx]["position"] + '</div>' + 
+                                           '    <div class="side">' + 
+                                           '        <div class="title">' + queue[idx]["path"] + '</div>' + 
+                                           '        <div class="particulars">' + 
+                                           '            <ul>' + 
+                                           '                <li><span class="bold">Status:</span> ' + queue[idx]["status"] + '</li>' + 
+                                           '                <li><span class="bold">Details:</span> ' + queue[idx]["width"] + 'x' + queue[idx]["height"] + ' @ ' + queue[idx]["framerate"] + 'fps</li>' + 
+                                           '                <li><span class="bold">Size:</span> ' + format_size(queue[idx]["initial_size"]) + '</li>' + 
+                                           '                <li><span class="bold">Added:</span> ' + queue[idx]["time_added"] + '</li>' + 
+                                           '                <li><span class="bold">Started:</span> ' + queue[idx]["encode_started"] + '</li>' + 
+                                           '            </ul>' + 
+                                           '        </div>' + 
+                                           '    </div>' + 
+                                           '</div>');
+                    }
+                }
+
+                $("#pbar").progressbar({
+                    value: progress_value
+                });
+
+                // The div we're looking for gets dynamically added so we can't 
+                // make this part of the regular CSS.
+                $("#pbar").find(".ui-progressbar-value").css({
+                    'background-color': '#f60'
+                });
+
+            });
+        }
+
+        // Call the getAndDisplay function once the page loads
+        $(document).ready(function() {
+            getAndDisplay("");
+            //$("#driver").click(getAndDisplay);
+         });
+
+        // Call the getAndDisplay function every 2 sec
+        window.setInterval(function() {
+            getAndDisplay("");
+        }, 2000);
+      </script>
+   </head>
+	
+   <body>
+      <p>Encode status:</p>
+		
+      <div id="stage">STAGE</div>
+		
+   </body>
+</html>
diff --git a/software/hbkif/setup.py b/software/hbkif/setup.py
deleted file mode 100644
index cd1be1b..0000000
--- a/software/hbkif/setup.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from setuptools import setup, find_packages
-
-# Use implicit ryft namespace package to keep things organized
-setup(
-    name='hbkif',
-    version='0.1.0',
-    description='Handbrake web interface',
-    packages=['hbkif', 'hbkif.controllers'],
-    # ~ packages=find_packages('hbkif'),
-    # ~ entry_points = {
-        # ~ 'console_scripts': [
-            # ~ 'docsim_daemon = ryft.xrest.docsim_daemon:main',
-        # ~ ]
-    # ~ },
-    zip_safe=False,
-)
