changeset 70:9ec7e32e8ad3

working on maps nicer HTML (with xhtml DTD) better unicode handling for psycopg
author casties
date Tue, 23 Nov 2010 17:16:25 +0100
parents 752ce3dfd23e
children 6f7f8dee6cd2
files .hgignore RestDbGisApi.py RestDbInterface.py RestDbJsonStore.py gis_gui/blocks/map.js gis_gui/blocks/table.js zpt/GIS_schema_table.zpt zpt/HTML_index.zpt zpt/HTML_schema.zpt zpt/HTML_schema_table.zpt zpt/HTML_schema_usertables.zpt zpt/JSONHTML_index.zpt zpt/JSONHTML_schema.zpt zpt/JSONHTML_schema_table.zpt
diffstat 14 files changed, 132 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Tue Nov 23 17:16:25 2010 +0100
@@ -0,0 +1,7 @@
+
+syntax: regexp
+^\.settings$
+syntax: regexp
+^\.project$
+syntax: regexp
+^\.pydevproject$
\ No newline at end of file
--- a/RestDbGisApi.py	Tue Nov 23 12:54:22 2010 +0100
+++ b/RestDbGisApi.py	Tue Nov 23 17:16:25 2010 +0100
@@ -16,14 +16,6 @@
 from RestDbInterface import *
 
 
-gisToSqlTypeMap = {
-                   "text": "text",
-                   "number": "numeric",
-                   "id": "text",
-                   "gis_id": "text",
-                   "coord_lat": "numeric",
-                   "coord_lon": "numeric"
-                   }
 
 def kmlEncode(s):
     """returns string encoded for displaying in KML attribute"""
@@ -59,6 +51,15 @@
     #
     # database methods
     #
+    toSqlTypeMap = {
+                    "text": "text",
+                    "number": "numeric",
+                    "id": "text",
+                    "gis_id": "text",
+                    "coord_lat": "numeric",
+                    "coord_lon": "numeric"
+                   }
+    
     def getTableOwner(self,schema,table):
         """returns the owner of the table"""
         # what do we do with the schema?
--- a/RestDbInterface.py	Tue Nov 23 12:54:22 2010 +0100
+++ b/RestDbInterface.py	Tue Nov 23 17:16:25 2010 +0100
@@ -10,9 +10,13 @@
 from Products.ZSQLExtend import ZSQLExtend
 import logging
 import re
-import psycopg2
 import json
 import time
+import psycopg2
+# make psycopg use unicode objects
+import psycopg2.extensions
+psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
+psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
 
 from zope.interface import implements
 from zope.publisher.interfaces import IPublishTraverse
@@ -24,6 +28,28 @@
 from Products.ZSQLMethods.SQL import SQLConnectionIDs
 
 
+def unicodify(s,alternate='latin-1'):
+    """decode str (utf-8 or latin-1 representation) into unicode object"""
+    if not s:
+        return u""
+    if isinstance(s, str):
+        try:
+            return s.decode('utf-8')
+        except:
+            return s.decode(alternate)
+    else:
+        return s
+
+def utf8ify(s):
+    """encode unicode object or string into byte string in utf-8 representation.
+       assumes string objects to be utf-8"""
+    if not s:
+        return ""
+    if isinstance(s, str):
+        return s
+    else:
+        return s.encode('utf-8')
+
 def getTextFromNode(node):
     """get the cdata content of a XML node"""
     if node is None:
@@ -52,14 +78,6 @@
     
     return s
 
-gisToSqlTypeMap = {
-                   "text": "text",
-                   "number": "numeric",
-                   "id": "text",
-                   "gis_id": "text",
-                   "coord_lat": "numeric",
-                   "coord_lon": "numeric"
-                   }
 
 class RestDbInterface(Folder):
     """Object for RESTful database queries
@@ -179,8 +197,8 @@
             # get all data in an array
             data = cur.fetchall()
             cur.close()
-            #logging.debug("fields: %s"%repr(fields))
-            #logging.debug("rows: %s"%repr(data))
+            logging.debug("fields: %s"%repr(fields))
+            logging.debug("rows: %s"%repr(data))
             return {"fields":fields, "rows":data}
         else:
             cur.close()
@@ -445,7 +463,10 @@
                 # {name: XX, type: YY}
                 name = sqlName(f['name'])
                 type = f['type']
-                sqltype = gisToSqlTypeMap[type]
+                if hasattr(self, 'toSqlTypeMap'):
+                    sqltype = self.toSqlTypeMap[type]
+                else:
+                    sqltype = 'text'
             
             else:
                 # name only
--- a/RestDbJsonStore.py	Tue Nov 23 12:54:22 2010 +0100
+++ b/RestDbJsonStore.py	Tue Nov 23 17:16:25 2010 +0100
@@ -199,12 +199,14 @@
             items = self.getListOfItemsAndValues(schema, table, tag, type)
             # items contain JSON-strings
             its = ",".join(['{"key":"%s","val":%s}'%(i[0],i[1]) for i in items])
-            its = "["+its+"]"
+            its = "[%s]"%its
             if resultFormat == 'JSON':
                 self.REQUEST.RESPONSE.setHeader("Content-Type", "application/json")
-                self.REQUEST.RESPONSE.write(its)       
+                # we assume utf-8
+                self.REQUEST.RESPONSE.write(utf8ify(its))       
             else:
-                self.REQUEST.RESPONSE.write(its)       
+                # we assume utf-8
+                self.REQUEST.RESPONSE.write(utf8ify(its))       
 
         else:
             items = self.getListOfItems(schema, table, tag, type)
--- a/gis_gui/blocks/map.js	Tue Nov 23 12:54:22 2010 +0100
+++ b/gis_gui/blocks/map.js	Tue Nov 23 17:16:25 2010 +0100
@@ -30,13 +30,13 @@
             block.addMapLayer(be,params);
         });
         // update button
-        $(be).find(".map_update_button").click(function() {
+        $(be).find(".map_update_button").click(function () {
             console.debug("map update");
             params = block.readMapParams();
             block.updateMap(be,params);
         });
         // save button
-        $(be).find(".map_save_button").click(function() {
+        $(be).find(".map_save_button").click(function () {
             console.debug("map save. this=",this," block=",block);
             params = block.readMapParams(be,params);
             block.storeBlock("test1");
@@ -44,9 +44,12 @@
     });
 };
 
-guiBlocks.Block.prototype.appendMapLayer = function(layerparams) {
+guiBlocks.Block.prototype.appendMapLayer = function (layerparams) {
     // add layer to this map
-    var layerinfo = {display: true, layer:layerparams};
+    var layerinfo = {
+        display: true, 
+        layer: layerparams
+        };
     var layers = this.params.map_layers;
     layers.push(layerinfo);
     // update indexes
@@ -56,9 +59,9 @@
     return this.params;
 };
 
-guiBlocks.Block.prototype.showMapParams = function(elem,params) {
+guiBlocks.Block.prototype.showMapParams = function (elem, params) {
     // create html with layer parameters from params
-    var i = 0;
+    var i, layers, tmpl, lp, idx;
     if (elem == null) {
         elem = this.element;
     }
@@ -66,19 +69,23 @@
         params = this.params;
     }
     $(elem).find(".map_name").val(params.name);
-    var layers = params.map_layers;
+    layers = params.map_layers;
     // remove old info
     $(elem).find(".map_layer_table .layer_info").remove();
     // write new info
     if (layers.length > 0) {
-        var tmpl = $(elem).find(".layer_info_tmpl").tmpl(layers);
+        tmpl = $(elem).find(".layer_info_tmpl").tmpl(layers);
         $(elem).find(".map_layer_header").after(tmpl);
         // arm edit and delete buttons
-        for (i = 0; i < layers.length; ++i)
-            
-            tmpl.find(".layer_edit_"+i).click(function() {
-                blocks.addLayerBlock("blocks/layer.html?table="+escape(params.table),"layer", params)
-        });
+        for (i = 0; i < layers.length; ++i) {
+            lp = layers[i].layer;
+            idx = layers[i].idx;
+            console.debug("showmapparams lp=", lp, " idx=", idx);
+            tmpl.find(".layer_edit_"+idx).click(function () {
+                console.debug("open layer ",idx);
+                blocks.addLayerBlock("blocks/layer.html?table="+escape(lp.table),"layer", lp);
+            });
+        }
     }
 };
 
--- a/gis_gui/blocks/table.js	Tue Nov 23 12:54:22 2010 +0100
+++ b/gis_gui/blocks/table.js	Tue Nov 23 17:16:25 2010 +0100
@@ -1,22 +1,27 @@
 
-guiBlocks.prototype.addTableBlock = function(url, baseId, tablename) {
-    var block = this.addBlock(url, baseId, function() {
+guiBlocks.prototype.addTableBlock = function (url, baseId, params) {
+    if (typeof(params) === "string") {
+        // then its the table name
+        params = {"type": "table", "table": params};
+    }
+    var block = this.addBlock(url, baseId, params, function () {
         // function after add block finished
         var id = block.id;
-        var tbl = $(block.element).find(".datatable");
+        var tablename = params.table;
+        var $tbl = $(block.element).find(".datatable");
         console.debug("in tableblock after block load!");
         console.debug("this=", this);
         console.debug("block=",block);
-        console.debug(tbl);
-        $(tbl).load(
+        console.debug($tbl);
+        $tbl.load(
             "../db/RESTdb/db/public/" + tablename + "?format=HTML&layout=table&element_id=newtable #newtable>*",
-            function() {
+            function () {
                 // function after load table finished
                 console.debug("In table load! this=");
                 console.debug(this);
-                $(tbl).find("td").addClass('compacted');
+                $tbl.find("td").addClass('compacted');
                 // Add DataTables functionality
-                $(tbl).dataTable( {
+                $tbl.dataTable( {
                     'bPaginate' : true,
                     'sPaginationType' : 'full_numbers'
                 });
@@ -27,9 +32,9 @@
 };
 
     
-guiBlocks.prototype.checkTableSubmitFn = function(oldsegment) {
+guiBlocks.prototype.checkTableSubmitFn = function (oldsegment) {
     // we need oldsegment in the returned function
-    return function() {
+    return function () {
         var tablename = $(this).find(".create_table_name").val();
         console.debug("check table="+tablename," this=",this);
         var uploadUrl = "../db/RESTdb/db/public/" + tablename;
@@ -38,13 +43,13 @@
         $(this).find("input[type=hidden][name=format]").remove();
         $(this).prepend('<input type="hidden" name="format" value="JSONHTML"/>');
         //foldBlock(oldsegment);
-    }
-}
+    };
+};
 
-guiBlocks.prototype.checkTableCompleteFn = function(oldsegment,uploadForm) {
+guiBlocks.prototype.checkTableCompleteFn = function (oldsegment,uploadForm) {
     // we need the blocks object in the returned function
     var gui_blocks = this;
-    return function(result) {
+    return function (result) {
         console.debug("check complete. this=", this, " result=",result);
         // json inside pre tag
         var txtres = $(result).text(); 
@@ -74,8 +79,8 @@
             foldBlock(oldsegment);
             gui_blocks.addTableStructureBlock("blocks/tablestructure.html?table="+escape(tablename),"tablestruct", tablename, res.fields, uploadForm);
         }
-    }
-}
+    };
+};
 
 guiBlocks.prototype.uploadTableSubmitFn = function(oldsegment,fields) {
     // we need oldsegment in the returned function
@@ -92,13 +97,13 @@
         $(this).find("input[type=hidden][name=create_table_fields]").remove();
         var fieldsStr = "";
         for (var i = 0; i < fields.length; i++) {
-            if (i > 0) { fieldsStr += ","}
+            if (i > 0) { fieldsStr += ",";}
             fieldsStr += fields[i].name + ":" + fields[i].type;
         }
         $(this).prepend('<input type="hidden" name="create_table_fields" value="'+fieldsStr+'"/>');
         foldBlock(oldsegment);
-    }
-}
+    };
+};
 
 /* function that returns an upload complete function.
  */
@@ -114,8 +119,8 @@
         var tablename = res.tablename;
         // open new table block
         var newblock = gui_blocks.addTableBlock("blocks/table.html?table="+escape(tablename),"table", tablename);
-    }
-}
+    };
+};
 
 // Show Tooltip
 $("td.compacted").livequery(function() {
--- a/zpt/GIS_schema_table.zpt	Tue Nov 23 12:54:22 2010 +0100
+++ b/zpt/GIS_schema_table.zpt	Tue Nov 23 17:16:25 2010 +0100
@@ -1,5 +1,7 @@
-<!DOCTYPE html>
-<html tal:define="root here/getRestDbUrl;
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  tal:define="root here/getRestDbUrl;
         schema options/schema; table options/table;
         kmlUrl python:here.getLiveKmlUrl(schema=schema,table=table);
 ">
--- a/zpt/HTML_index.zpt	Tue Nov 23 12:54:22 2010 +0100
+++ b/zpt/HTML_index.zpt	Tue Nov 23 17:16:25 2010 +0100
@@ -1,4 +1,7 @@
-<html tal:define="layout python:request.get('layout','table'); element_id python:request.get('element_id',None);
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  tal:define="layout python:request.get('layout','table'); element_id python:request.get('element_id',None);
   data here/getListOfSchemas">
   <head>
     <meta http-equiv="content-type" content="text/html;charset=utf-8">
--- a/zpt/HTML_schema.zpt	Tue Nov 23 12:54:22 2010 +0100
+++ b/zpt/HTML_schema.zpt	Tue Nov 23 17:16:25 2010 +0100
@@ -1,4 +1,7 @@
-<html tal:define="layout python:request.get('layout','table'); element_id python:request.get('element_id',None);
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  tal:define="layout python:request.get('layout','table'); element_id python:request.get('element_id',None);
   schema options/schema; data python:here.getListOfTables(schema)">
   <head>
     <meta http-equiv="content-type" content="text/html;charset=utf-8">
--- a/zpt/HTML_schema_table.zpt	Tue Nov 23 12:54:22 2010 +0100
+++ b/zpt/HTML_schema_table.zpt	Tue Nov 23 17:16:25 2010 +0100
@@ -1,4 +1,7 @@
-<html tal:define="layout python:request.get('layout','table'); element_id python:request.get('element_id',None); 
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  tal:define="layout python:request.get('layout','table'); element_id python:request.get('element_id',None); 
     schema options/schema; table options/table; data python:here.getTable(schema=schema,table=table);
     fields data/fields; rows data/rows;">
   <head>
--- a/zpt/HTML_schema_usertables.zpt	Tue Nov 23 12:54:22 2010 +0100
+++ b/zpt/HTML_schema_usertables.zpt	Tue Nov 23 17:16:25 2010 +0100
@@ -1,4 +1,7 @@
-<html tal:define="layout python:request.get('layout','table'); element_id python:request.get('element_id',None);
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  tal:define="layout python:request.get('layout','table'); element_id python:request.get('element_id',None);
   schema python:options.get('schema','public'); data python:here.getListOfUserTables(schema)">
   <head>
     <meta http-equiv="content-type" content="text/html;charset=utf-8">
--- a/zpt/JSONHTML_index.zpt	Tue Nov 23 12:54:22 2010 +0100
+++ b/zpt/JSONHTML_index.zpt	Tue Nov 23 17:16:25 2010 +0100
@@ -1,4 +1,7 @@
-<html tal:define="layout python:request.get('layout','pre'); element_id python:request.get('element_id',None);
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  tal:define="layout python:request.get('layout','pre'); element_id python:request.get('element_id',None);
   data here/getListOfSchemas">
   <head>
     <meta http-equiv="content-type" content="text/html;charset=utf-8">
--- a/zpt/JSONHTML_schema.zpt	Tue Nov 23 12:54:22 2010 +0100
+++ b/zpt/JSONHTML_schema.zpt	Tue Nov 23 17:16:25 2010 +0100
@@ -1,4 +1,7 @@
-<html tal:define="layout python:request.get('layout','pre'); element_id python:request.get('element_id',None);
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  tal:define="layout python:request.get('layout','pre'); element_id python:request.get('element_id',None);
   schema options/schema; data python:here.getListOfTables(schema)">
   <head>
     <meta http-equiv="content-type" content="text/html;charset=utf-8">
--- a/zpt/JSONHTML_schema_table.zpt	Tue Nov 23 12:54:22 2010 +0100
+++ b/zpt/JSONHTML_schema_table.zpt	Tue Nov 23 17:16:25 2010 +0100
@@ -1,4 +1,7 @@
-<html tal:define="layout python:request.get('layout','pre'); element_id python:request.get('element_id',None)
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  tal:define="layout python:request.get('layout','pre'); element_id python:request.get('element_id',None)
     schema options/schema; table options/table; data python:here.getTable(schema=schema,table=table);">
   <head>
     <meta http-equiv="content-type" content="text/html;charset=utf-8">