commit 98f4e4a6a255371b9899a9a23ecbbb21e28f8020
Author: dsorber <david.sorber@gmail.com>
Date:   Sat Jul 26 22:45:36 2014 -0400

    Continued working on the web GUI, taking baby steps.

diff --git a/software/bookmark_library/bmklib/web/base_controller.py b/software/bookmark_library/bmklib/web/base_controller.py
index 2c0af44..cff142a 100644
--- a/software/bookmark_library/bmklib/web/base_controller.py
+++ b/software/bookmark_library/bmklib/web/base_controller.py
@@ -2,9 +2,9 @@ import os
 
 from genshi.template import TemplateLoader
 
-BASE_PATH = '/home/dsorber/Documents/phalanx-repo/software/bookmark_library/web'
-DB_PATH = os.path.join(BASE_PATH, 'beer_temps.db')
-TEMPLATE_PATH = os.path.join(BASE_PATH, 'templates')
+BASE_PATH = '/home/dsorber/Documents/phalanx-repo/software/bookmark_library/'
+DB_PATH = os.path.join(BASE_PATH, 'bookmarks.db')
+TEMPLATE_PATH = os.path.join(BASE_PATH, 'bmklib', 'web', 'templates')
 
 class BaseHTMLController(object):
     
@@ -32,8 +32,10 @@ class BaseHTMLController(object):
         """ This function generates the actual response which is made up of two
         parts, the response headers and the response body.
         """
+        self.build_content()
+        
         # Generate the stream and then render it to HTML
-        stream = self.template.generate(**response_args)
+        stream = self.template.generate(**self.content)
         body = stream.render('html', doctype='html', encoding='utf-8')
         
         # Set the appropriate response headers
@@ -50,7 +52,7 @@ class BaseTextController(object):
         self.environ = environ
 
         # This string will be the response body
-        self.body
+        self.body = ''
         
     def build_content(self):
         """ This method is used to build the content that is used to generate
@@ -65,7 +67,15 @@ class BaseTextController(object):
         """ This function generates the actual response which is made up of two
         parts, the response headers and the response body.
         """
+        self.build_content()
+        
         headers = [('Content-Type', 'text/plain'),
                    ('Content-Length', str(len(self.body)))]
                    
         return headers, self.body
+        
+        
+class TestController(BaseTextController):
+    
+    def build_content(self):
+        self.body = 'hello there handsome'
diff --git a/software/bookmark_library/bmklib/web/bmklib.wsgi b/software/bookmark_library/bmklib/web/bmklib.wsgi
index 81b60e4..0704c3e 100644
--- a/software/bookmark_library/bmklib/web/bmklib.wsgi
+++ b/software/bookmark_library/bmklib/web/bmklib.wsgi
@@ -1,13 +1,4 @@
-import cgi
-import datetime
-import os
-import sqlite3
-from genshi.template import TemplateLoader
-from genshi.template.base import Context
-
-BASE_PATH = '/home/dsorber/bfcs'
-DB_PATH = os.path.join(BASE_PATH, 'beer_temps.db')
-TEMPLATE_PATH = os.path.join(BASE_PATH, 'templates')
+from bmklib.web.controllers.main import MainPageController
 
 # It accepts two arguments:
 # environ points to a dictionary containing CGI like environment variables
@@ -15,155 +6,12 @@ TEMPLATE_PATH = os.path.join(BASE_PATH, 'templates')
 # start_response is a callback function supplied by the server
 # which will be used to send the HTTP status and headers to the server
 def application(environ, start_response):
-    loader = TemplateLoader(TEMPLATE_PATH, auto_reload=True)
+
     if not environ['PATH_INFO'] or environ['PATH_INFO'] == '/':
-        # Load the index template
-        template = loader.load('index.html')
-        # Create the response args
-        response_args = {'title': 'Beer Fermentation Control System'}
-        # Open up the connection to the database, execute the query,
-        # grab the results, then close the DB connection.
-        db_conn = sqlite3.connect(DB_PATH)
-        db = db_conn.cursor()
-        db.execute("select strftime('%m/%d/%Y', date(ts, 'unixepoch')), "
-                   "       count(ts), avg(temp1), max(temp1), min(temp1),"
-                   "       avg(temp2), max(temp2), min(temp2), avg(temp3),"
-                   "       max(temp3), min(temp3), avg(temp4), max(temp4),"
-                   "       min(temp4)"
-                   "from temp_data "
-                   "group by date(ts, 'unixepoch')")
-        response_args['results'] = db.fetchall()
-        db_conn.close()
-        # Generate the stream and then render it to HTML
-        stream = template.generate(**response_args)
-        response_body = stream.render('html', doctype='html', encoding='utf-8')
-        # Set the appropriate response headers
-        response_headers = [('Content-Type', 'text/html; charset=utf-8'),
-                            ('Content-Length', str(len(response_body)))]
-    elif environ['PATH_INFO'].startswith('/day/') and environ['PATH_INFO'].endswith('/all'):
-        # Load the all template
-        template = loader.load('all.html')
-        # Parse the date out of the URL (TODO: validate all this)
-        day = environ['PATH_INFO'][5:7]
-        month = environ['PATH_INFO'][7:9]
-        year = environ['PATH_INFO'][9:13]
-        date = '%s/%s/%s' % (month, day, year)
-        # Create the response args
-        response_args = {'title': 'Sensor Readings for %s' % date}
-        # Open up the connection to the database, execute the query
-        # (limit to today and the past 5 minutes),
-        # grab the results, then close the DB connection.
-        db_conn = sqlite3.connect(DB_PATH)
-        db = db_conn.cursor()
-        db.execute("select strftime('%%H:%%M:%%S', ts, 'unixepoch'), "
-                   "       temp1, temp2, temp3, temp4, relay_status "
-                   "from temp_data "
-                   "where date(ts, 'unixepoch') is date('%s-%s-%s')"
-                   "order by ts desc" % (year, month, day))
-        response_args['results'] = db.fetchall()
-        db_conn.close()
-        # Generate the stream and then render it to HTML
-        stream = template.generate(**response_args)
-        response_body = stream.render('html', doctype='html', encoding='utf-8')
-        # Set the appropriate response headers
-        response_headers = [('Content-Type', 'text/html; charset=utf-8'),
-                            ('Content-Length', str(len(response_body)))]
-    elif environ['PATH_INFO'].startswith('/day/'):
-        # Load the day template
-        template = loader.load('day.html')
-       
-        # Parse the date out of the URL (TODO: validate all this)
-        day = environ['PATH_INFO'][5:7]
-        month = environ['PATH_INFO'][7:9]
-        year = environ['PATH_INFO'][9:13]
-        date = '%s/%s/%s' % (month, day, year)
-        # Create the response args
-        response_args = {'title': 'Sensor Readings for %s' % date,
-                         'url_date': environ['PATH_INFO'][5:13]}
-        # Open up the connection to the database, execute the query
-        # (limit to today and the past 5 minutes),
-        # grab the results, then close the DB connection.
-        db_conn = sqlite3.connect(DB_PATH)
-        db = db_conn.cursor()
-        db.execute("select strftime('%%H:%%M:%%S', ts, 'unixepoch'), "
-                   "       temp1, temp2, temp3, temp4, relay_status "
-                   "from temp_data "
-                   "where date(ts, 'unixepoch') is date('%s-%s-%s')"
-                   "order by ts desc limit 300" % (year, month, day))
-        response_args['results'] = db.fetchall()
-        # Chart query
-        #
-        db.execute("select strftime('%%H:%%M:%%S', ts, 'unixepoch'), ts, temp1, "
-                   "       temp2, temp3, temp4 from ( "
-                   "select ts, temp1, temp2, temp3, temp4 "
-                   "from temp_data "
-                   "where date(ts, 'unixepoch') is date('%s-%s-%s')"
-                   "order by ts desc limit 60) order by ts"
-                   % (year, month, day))
-        chart_results = db.fetchall()
-        # Process chart query results
-        sensor1_data = []
-        sensor2_data = []
-        sensor3_data = []
-        sensor4_data = []
-        for row in chart_results:
-            sensor1_data.append([int(row[1]) * 1000, row[2]])
-            sensor2_data.append([int(row[1]) * 1000, row[3]])
-            sensor3_data.append([int(row[1]) * 1000, row[4]])
-            sensor4_data.append([int(row[1]) * 1000, row[5]])
-        response_args['sensor1_data'] = str(sensor1_data)
-        response_args['sensor2_data'] = str(sensor2_data)
-        response_args['sensor3_data'] = str(sensor3_data)
-        response_args['sensor4_data'] = str(sensor4_data)
-        # This is a bit of hack to get around a javascript issue in
-        # the template
-        # response_args['chart_results'] = chart_results[:-1]
-        # response_args['chart_last_row'] = chart_results[-1]
-        db_conn.close()
-        # Generate the stream and then render it to HTML
-        stream = template.generate(**response_args)
-        response_body = stream.render('html', doctype='html', encoding='utf-8')
-        # Set the appropriate response headers
-        response_headers = [('Content-Type', 'text/html; charset=utf-8'),
-                            ('Content-Length', str(len(response_body)))]
-    elif environ['PATH_INFO'] == ('/chart_update'):
-        # Update the self updating chart
-        response_body = ''
-        if environ['QUERY_STRING']:
-            # Parse the query string to get the last timestamp from the client
-            get_args = cgi.parse_qs(environ['QUERY_STRING'])
-            last_ts = int(get_args['last_ts'][0])
-            date_from_ts = datetime.datetime.fromtimestamp(last_ts)
-            # Reconstruct portions of the date from the ts
-            year = date_from_ts.year
-            month = '%02d' % date_from_ts.month
-            day = '%02d' % date_from_ts.day
-           
-            # Grab any entries from the supplied date that are greater than
-            # the last timestamp sent from the client javascript
-            db_conn = sqlite3.connect(DB_PATH)
-            db = db_conn.cursor()
-            db.execute("select strftime('%%H:%%M:%%S', ts, 'unixepoch'), ts, "
-                       "       temp1, temp2, temp3, temp4, relay_status "
-                       "from temp_data "
-                       "where date(ts, 'unixepoch') is date('%s-%s-%s') and "
-                       "      ts > %s "
-                       "order by ts asc limit 60" % (year, month, day, last_ts))
-            db_rows = db.fetchall()
-            db_conn.close()
-            # Iterate over the rows fetched by the query and pretty them up
-            # in preparation of being sent back to the client javascript for
-            # display
-            result_rows = []
-            for row in db_rows:
-                result_rows.append('%s %s %s %s %s %s %s' %
-                                     (row[0], (int(row[1]) * 1000),
-                                     row[2], row[3], row[4], row[5],
-                                     int(row[6]) and 'on' or 'off'))
-            response_body = ','.join(result_rows)
-            response_body = response_body.encode('utf-8')
-        response_headers = [('Content-Type', 'text/plain; charset=utf-8'),
-                            ('Content-Length', str(len(response_body)))]
+        
+        controller = MainPageController('main.html', environ)
+        response_headers, response_body = controller.generate_response()
+
     else:
         # User supplied an invalid URL
         response_body = 'Invalid URL "%s"' % environ['PATH_INFO']
diff --git a/software/bookmark_library/bmklib/web/controllers/__init__.py b/software/bookmark_library/bmklib/web/controllers/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/software/bookmark_library/bmklib/web/controllers/main.py b/software/bookmark_library/bmklib/web/controllers/main.py
new file mode 100644
index 0000000..eda0a69
--- /dev/null
+++ b/software/bookmark_library/bmklib/web/controllers/main.py
@@ -0,0 +1,14 @@
+import sqlite3
+
+from bmklib.web.base_controller import BaseHTMLController, DB_PATH
+
+class MainPageController(BaseHTMLController):
+    
+    def build_content(self):
+        conn = sqlite3.connect(DB_PATH)
+        
+        db = conn.cursor()
+        db.execute("SELECT COUNT(*) FROM bookmarks")
+        row = db.fetchone()
+        
+        self.content['total_num_bmks'] = row[0]
diff --git a/software/bookmark_library/bmklib/web/templates/main.html b/software/bookmark_library/bmklib/web/templates/main.html
new file mode 100644
index 0000000..7013253
--- /dev/null
+++ b/software/bookmark_library/bmklib/web/templates/main.html
@@ -0,0 +1,65 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:py="http://genshi.edgewall.org/">
+<head>
+<title>Bookmark Library</title>
+<style type="text/css">
+
+    body {
+        font-family: sans-serif;
+        font-size: 16px
+    }
+
+    h3 {
+        font-size: 24px;
+    }
+
+    table {
+        border: 1px solid #000;
+        border-spacing: 0px;
+        margin-left: auto;
+        margin-right: auto;
+    }
+
+    table a:link {
+        color: #000;
+        text-decoration: none;
+    }
+
+    table a:visited {
+        color: #000;
+        text-decoration: none;
+    }
+
+    table a:hover {
+        color: #000;
+        text-decoration: underline;
+    }
+
+    tr.even {
+        background-color: #FFF;
+    }
+
+    tr.odd {
+        background-color: #FFC;
+    }
+
+    th {
+        border: 1px solid #000;
+        padding: 10px;
+        border-spacing: 2px;
+    }
+
+    td {
+        border-top: 1px solid #000;
+        padding: 2px 5px;
+    }
+</style>
+</head>
+
+<body>
+<h1>Bookmark Library</h1>
+
+There are currently ${total_num_bmks} bookmarks in the library.
+
+</body>
+</html>
