commit 836bf7f995f8e0dac49d37ee758f335c624f59cc
Author: dsorber <david.sorber@gmail.com>
Date:   Mon Jan 19 17:05:07 2015 -0500

    Well I was trying to get bookmark display and update functionality working, but I really only got started. I need to work out how to make the update_bookmark handler work as I would like it to.

diff --git a/software/bookmark_library/bmklib/web/bmklib.wsgi b/software/bookmark_library/bmklib/web/bmklib.wsgi
index ec202d9..e5c0236 100644
--- a/software/bookmark_library/bmklib/web/bmklib.wsgi
+++ b/software/bookmark_library/bmklib/web/bmklib.wsgi
@@ -1,7 +1,9 @@
 import re
 
 from bmklib.web.controllers.all_bookmarks import AllBookmarksPageController
+from bmklib.web.controllers.bookmark import BookmarkPageController
 from bmklib.web.controllers.main import MainPageController
+from bmklib.web.controllers.update_bookmark import UpdateBookmarkController
 
 # It accepts two arguments:
 # environ points to a dictionary containing CGI like environment variables
@@ -13,14 +15,24 @@ def application(environ, start_response):
     path = environ['PATH_INFO']
 
     if not path or path == '/':
-        
+        # Main page
         controller = MainPageController(environ)
         response_headers, response_body = controller.generate_response()
 
     elif re.search('^/bookmarks$', path) or re.search('^/bookmarks/', path):
-        
+        # All bookmarks page
         controller = AllBookmarksPageController(environ)
         response_headers, response_body = controller.generate_response()
+    
+    elif re.search('^/bookmark$', path) or re.search('^/bookmark/', path):
+        # Specific bookmark page
+        controller = BookmarkPageController(environ)
+        response_headers, response_body = controller.generate_response()
+        
+    elif re.search('^/update_bookmark$', path) or re.search('^/update_bookmark/$', path):
+        # Update bookmark
+        controller = UpdateBookmarkController(environ)
+        response_headers, response_body = controller.generate_response()
         
     else:
         # User supplied an invalid URL
diff --git a/software/bookmark_library/bmklib/web/controllers/all_bookmarks.py b/software/bookmark_library/bmklib/web/controllers/all_bookmarks.py
index 83f94e9..5953ec3 100644
--- a/software/bookmark_library/bmklib/web/controllers/all_bookmarks.py
+++ b/software/bookmark_library/bmklib/web/controllers/all_bookmarks.py
@@ -20,12 +20,14 @@ class AllBookmarksPageController(BaseHTMLController):
         conn = sqlite3.connect(DB_PATH)        
         db = conn.cursor()
         
+        # Grab the total number of bookmarks
         db = conn.cursor()
         db.execute("SELECT COUNT(*) FROM bookmarks")
         total_bmks = int(db.fetchone()[0])
         self.content['total_num_bmks'] = total_bmks
         self.content['max_page_idx'] = math.ceil(float(total_bmks) / MAX_PER_PAGE)
         
+        # Start pagination at 1 (instead of 0)
         page_idx = 1
         
         # Parse the path and modify the query as needed
@@ -61,7 +63,7 @@ class AllBookmarksPageController(BaseHTMLController):
             self.content['previous'] = None
         else:
             prev_idx = page_idx - 1
-            prev_path = ['..']  * len(path_parts)
+            prev_path = ['..']  * (len(path_parts) - 1)
             prev_path.extend(['bookmarks', str(prev_idx)])
             self.content['previous'] = os.path.join(*prev_path)
         
@@ -70,6 +72,6 @@ class AllBookmarksPageController(BaseHTMLController):
         if next_idx > self.content['max_page_idx']:
             self.content['next'] = None
         else:
-            next_path = ['..']  * len(path_parts)
+            next_path = ['..']  * (len(path_parts) - 1)
             next_path.extend(['bookmarks', str(next_idx)])
             self.content['next'] = os.path.join(*next_path)
diff --git a/software/bookmark_library/bmklib/web/controllers/bookmark.py b/software/bookmark_library/bmklib/web/controllers/bookmark.py
new file mode 100644
index 0000000..d31ad2e
--- /dev/null
+++ b/software/bookmark_library/bmklib/web/controllers/bookmark.py
@@ -0,0 +1,43 @@
+import math
+import os.path
+
+import sqlite3
+
+from bmklib.lib.bookmark import Bookmark, BookmarkNotFoundError
+from bmklib.web.base_controller import BaseHTMLController, DB_PATH, MAX_PER_PAGE
+
+class BookmarkPageController(BaseHTMLController):
+    
+    def __init__(self, environ, template_name='bookmark.html'):
+        super(BookmarkPageController, self).__init__(environ, template_name)
+    
+    def build_content(self):
+        
+        # Split the path so we can parse it below
+        path = self.environ['PATH_INFO'][1:]
+        path_parts = path.split('/')
+        
+        conn = sqlite3.connect(DB_PATH)        
+        db = conn.cursor()
+        
+        # Do some basic validation
+        try:
+            bmk_id = int(path_parts[1])
+        except (ValueError, IndexError):
+            bmk_id = None
+        
+        if bmk_id is None or len(path_parts) != 2:
+            self.content['invalid'] = True
+            self.content['error'] = 'Invalid bookmark path'
+        else:
+            self.content['invalid'] = False
+            
+            # Build Bookmark object
+            try:
+                bookmark = Bookmark(conn, id=bmk_id)
+                self.content['bookmark'] = bookmark
+            except BookmarkNotFoundError:
+                self.content['invalid'] = True
+                self.content['error'] = '{:d} is not a valid bookmark ID'.format(bmk_id)
+                return
+
diff --git a/software/bookmark_library/bmklib/web/controllers/update_bookmark.py b/software/bookmark_library/bmklib/web/controllers/update_bookmark.py
new file mode 100644
index 0000000..38ae371
--- /dev/null
+++ b/software/bookmark_library/bmklib/web/controllers/update_bookmark.py
@@ -0,0 +1,48 @@
+import math
+import os.path
+
+import sqlite3
+
+from bmklib.lib.bookmark import Bookmark, BookmarkNotFoundError
+from bmklib.web.base_controller import BaseHTMLController, DB_PATH, MAX_PER_PAGE
+
+class UpdateBookmarkController(BaseHTMLController):
+    
+    def __init__(self, environ, template_name='bookmark.html'):
+        super(UpdateBookmarkController, self).__init__(environ, template_name)
+    
+    def build_content(self):
+        
+        f = open('/home/dsorber/Desktop/poop', 'w')
+        f.write(environ['wsgi.input'])
+        f.close()
+        return
+        
+        # Split the path so we can parse it below
+        path = self.environ['PATH_INFO'][1:]
+        path_parts = path.split('/')
+        
+        conn = sqlite3.connect(DB_PATH)        
+        db = conn.cursor()
+        
+        # Do some basic validation
+        try:
+            bmk_id = int(path_parts[1])
+        except (ValueError, IndexError):
+            bmk_id = None
+        
+        if bmk_id is None or len(path_parts) != 2:
+            self.content['invalid'] = True
+            self.content['error'] = 'Invalid bookmark path'
+        else:
+            self.content['invalid'] = False
+            
+            # Build Bookmark object
+            try:
+                bookmark = Bookmark(conn, id=bmk_id)
+                self.content['bookmark'] = bookmark
+            except BookmarkNotFoundError:
+                self.content['invalid'] = True
+                self.content['error'] = '{:d} is not a valid bookmark ID'.format(bmk_id)
+                return
+
diff --git a/software/bookmark_library/bmklib/web/htdocs/css/bmk_form.css b/software/bookmark_library/bmklib/web/htdocs/css/bmk_form.css
new file mode 100644
index 0000000..ab804d0
--- /dev/null
+++ b/software/bookmark_library/bmklib/web/htdocs/css/bmk_form.css
@@ -0,0 +1,55 @@
+    input {
+        font-size: 20px;
+        padding: 0.3em;
+        width:100%;
+        box-sizing: border-box;         /* For IE and modern versions of Chrome */
+        -moz-box-sizing: border-box;    /* For Firefox                          */
+        -webkit-box-sizing: border-box; /* For Safari                           */
+    }
+
+    textarea {
+        font-size: 20px;
+        padding: 0.3em;
+        width:100%;
+        height:100%; 
+        box-sizing: border-box;         /* For IE and modern versions of Chrome */
+        -moz-box-sizing: border-box;    /* For Firefox                          */
+        -webkit-box-sizing: border-box; /* For Safari                           */
+    }
+
+    input:focus, textarea:focus {
+        border: 2px solid #C00;
+    }
+
+    input.checkbox {
+        width: auto;
+        display: block;
+        margin: 0.7em;
+    }
+
+    input.button {
+        width: auto;
+        font-size: 14px;
+    }
+
+    div.container {
+        border: 0px;
+        border-spacing: 0px;
+        width: 80%;
+        margin-left: auto;
+        margin-right: auto;
+    }
+
+    div.container p {
+        font-size: 20px;
+        margin-top: 0.1em;
+    }
+
+    span.form_label {
+        font-size: 13px;
+    }
+
+    div.not_first {
+        margin-top: 1.5em;
+    }
+
diff --git a/software/bookmark_library/bmklib/web/htdocs/css/bmk_main.css b/software/bookmark_library/bmklib/web/htdocs/css/bmk_main.css
index 12a9e48..4ee9669 100644
--- a/software/bookmark_library/bmklib/web/htdocs/css/bmk_main.css
+++ b/software/bookmark_library/bmklib/web/htdocs/css/bmk_main.css
@@ -49,8 +49,12 @@
     }
 
     .tag {
-        background-color: #CCC;
+        background-color: #DDD;
         font-size: 12px
-        padding: 4px;
+        padding: 0.5em;
         border-right: 2px;
     }
+
+    .detail_link {
+        font-size: 10px;
+    }
diff --git a/software/bookmark_library/bmklib/web/templates/all_bookmarks.html b/software/bookmark_library/bmklib/web/templates/all_bookmarks.html
index 74a4fe2..458add4 100644
--- a/software/bookmark_library/bmklib/web/templates/all_bookmarks.html
+++ b/software/bookmark_library/bmklib/web/templates/all_bookmarks.html
@@ -10,15 +10,15 @@
 <p>${page_idx} of ${max_page_idx}</p>
 <table>
     <tr py:for="idx, bookmark in enumerate(bookmarks)" class="${idx % 2 == 1 and 'odd' or 'even'}">
-        <td>${bookmark.id}</td>
+        <td>${idx + ((page_idx - 1) * len(bookmarks)) + 1} <a class="detail_link" href="../bookmark/${bookmark.id}">+</a></td>
         <td><a href="${bookmark.url}">${bookmark.title and bookmark.title or 'no title'}</a></td>
         <td><py:for each="tag in bookmark.category_tags"><span class="tag">${tag.value}</span></py:for></td>
         <td><py:for each="tag in bookmark.description_tags"><span class="tag">${tag.value}</span></py:for></td>
     </tr>
 </table>
 
-<py:if test="previous is not None"><a href="bookmark/${previous}">Previous</a></py:if>
+<py:if test="previous is not None"><a href="${previous}">Previous</a></py:if>
 
-<py:if test="next is not None"><a href="bookmark/${next}">Next</a></py:if>
+<py:if test="next is not None"><a href="${next}">Next</a></py:if>
 </body>
 </html>
diff --git a/software/bookmark_library/bmklib/web/templates/bookmark.html b/software/bookmark_library/bmklib/web/templates/bookmark.html
new file mode 100644
index 0000000..0dc4bc7
--- /dev/null
+++ b/software/bookmark_library/bmklib/web/templates/bookmark.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:py="http://genshi.edgewall.org/">
+<head>
+<title>Bookmark Library</title>
+<link rel="stylesheet" type="text/css" href="http://127.0.0.1/htdocs/css/bmk_main.css"></link>
+<link rel="stylesheet" type="text/css" href="http://127.0.0.1/htdocs/css/bmk_form.css"></link>
+</head>
+
+<body>
+<h1>Bookmarks</h1>
+
+<py:choose test="invalid">
+  <py:when test="True">
+    <p>${error}</p>
+    <p><a href="/bmk">Return</a></p>
+  </py:when>
+
+  <py:when test="False">
+    <p>Bookmark ID: ${bookmark.id}</p>
+    <form method="post" action="/bmk/update_bookmark">
+        <input type="hidden" name="id" value="${bookmark.id}" />
+        <div class="container">
+            <div>
+                <span class="form_label">Title:</span>
+                <input type="text" name="title" value="${bookmark.title}" />
+            </div>
+            <div class="not_first">
+                <span class="form_label">URL:</span>
+                <input type="text" name="url" value="${bookmark.url}" />
+            </div >
+            <div class="not_first">
+                <span class="form_label">Description:</span>
+                <textarea name="description">${bookmark.description}</textarea>
+            </div>
+            <div class="not_first">
+                <span class="form_label">Deleted:</span>
+                <input class="checkbox" type="checkbox" name="deleted" />
+            </div>
+            <div class="not_first">
+                <span class="form_label">Date added:</span>
+                <p>${bookmark.date_added.month}/${bookmark.date_added.day}/${bookmark.date_added.year}</p>
+            </div>
+            <input class="button" type="submit" />
+        </div>
+    </form>
+  </py:when>
+</py:choose>
+
+</body>
+</html>
