X-Git-Url: http://git.roojs.org/?a=blobdiff_plain;f=dbgenerate.js;h=0ea16fda806638b796beb905bec622c88ae15d72;hb=119290bc3234e9ece1c64dbd72ca486d9633b5b7;hp=6f09cc302c948fd6a5c1abc6b66d56ae4dba7e09;hpb=5f5a9de96df47563e47c4508d10a053db476d9f1;p=app.Builder.js diff --git a/dbgenerate.js b/dbgenerate.js index 6f09cc302..0ea16fda8 100644 --- a/dbgenerate.js +++ b/dbgenerate.js @@ -13,7 +13,25 @@ * * write readers.. * - * usage: seed generate.js + * usage: seed generate.js + * + * + * + * + *Hack needed to latest GLib-2.0.gir + * + * + + + + + + * + * + * remove introspectable =0 from g_key_file_get_groups + * and add transfer-owneership = none to return value + * remove introspectable =0 from g_key_file_get_keys + * and add transfer-owneership = none to return value* * */ Gda = imports.gi.Gda; @@ -25,7 +43,7 @@ console = imports.console; File = imports.File.File; Options = imports.Options.Options; -Gda.init(); +//Gda.init(); var prov = Gda.Config.list_providers (); //print(prov.dump_as_string()); @@ -34,10 +52,12 @@ var o = new Options({ help_description : 'Element builder for App Builder based on database schema', options: [ + { arg_long : 'DBTYPE' , arg_short : 't', description : 'Database Type (eg. MySQL or PostgreSQL ' }, { arg_long : 'DBNAME' , arg_short : 'd', description : 'Database Name' }, { arg_long : 'USERNAME' , arg_short : 'u', description : 'Username'}, - { arg_long : 'PASSWORD' , arg_short : 'p', description : '' , arg_default :'' }, - { arg_long : 'INI' , arg_short : 'I', description : 'Either base directory which has Pman/***/DataObjects/***.ini or location of ini file.' }, + { arg_long : 'PASSWORD' , arg_short : 'p', description : 'Password' , arg_default :'' }, + { arg_long : 'INI' , arg_short : 'I', description : + 'Either base directory which has Pman/***/DataObjects/***.links.ini or location of ini file.' }, ] }) @@ -47,9 +67,10 @@ var o = new Options({ var cfg = o.parse(Seed.argv); print(JSON.stringify(cfg, null,4)); -var cnc = Gda.Connection.open_from_string ("MySQL", "DB_NAME=" + cfg.DBNAME, - "USERNAME=" + cfg.USERNAME + ';PASSWORD=' + cfg.PASSWORD, - Gda.ConnectionOptions.NONE, null); +var cnc = Gda.Connection.open_from_string (cfg.DBTYPE, + "DB_NAME=" + cfg.DBNAME, + "USERNAME=" + cfg.USERNAME + ';PASSWORD=' + cfg.PASSWORD, + Gda.ConnectionOptions.NONE, null); @@ -96,14 +117,22 @@ Gda.DataSelect.prototype.fetchAll = function() var map = { 'date' : 'date', - 'datetime' : 'string', + 'datetime' : 'date', + 'timestamp with time zone' : 'date', + 'timestamp without time zone' : 'date', + 'time' : 'string', //bogus 'int' : 'int', + 'integer' : 'int', 'bigint' : 'int', - + 'double' : 'float', 'tinyint' : 'int', + 'smallint' : 'int', 'decimal' : 'float', 'float' : 'float', + 'numeric' : 'float', 'char' : 'string', + 'character' : 'string', + 'character varying' : 'string', 'varchar' : 'string', 'text' : 'string', 'longtext' : 'string', @@ -111,7 +140,10 @@ var map = { 'mediumtext' : 'string', 'enum' : 'string', 'timestamp' : 'number', - 'blob' : 'text' + 'blob' : 'text', + 'bytea' : 'text', + 'boolean' : 'int', + 'text[]' : 'string', } @@ -127,15 +159,22 @@ function readIni(fn) var groups = key_file.get_groups(); groups.forEach(function(g) { + //print("KEY:"+g); ini[g] = {} - + var keys = key_file.get_keys(g); + if (!keys) { return; } + keys.forEach(function(k) { - ini[g][k] = key_file.get_value(g,k); - }) - }) - + print("GET val: " + k); + ini[g][k] = key_file.get_value(g,k); + print(ini[g][k] ); + }); + //print("DONE KEY:"+g); + }); + //print("DONE KEYS"); } + if (File.isFile(cfg.INI)) { if (cfg.INI.match(/links\.ini$/)) { readIni(cfg.INI); @@ -144,6 +183,7 @@ if (File.isFile(cfg.INI)) { } } + if (File.isDirectory(cfg.INI)) { @@ -194,21 +234,80 @@ if (File.isDirectory(cfg.INI)) { } //print(JSON.stringify(ini, null,4)); //console.dump(ini); - +print("DONE INI"); //Seed.quit(); //GLib.key_file_load_from_file (key_file, String file, KeyFileFlags flags) : Boolean +switch(cfg.DBTYPE) { + case "MySQL": + query_tables = "SHOW TABLES"; + query_describe_table = "DESCRIBE `%s`"; + break; + + case 'PostgreSQL': + query_tables = "select c.relname FROM pg_catalog.pg_class c " + + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace " + + "WHERE c.relkind IN ('r','') AND n.nspname NOT IN ('pg_catalog', 'pg_toast')" + + "AND pg_catalog.pg_table_is_visible(c.oid) "; + query_describe_table = + "SELECT " + + "f.attnum AS number, " + + "f.attname AS Field, " + + "f.attnum, " + + "CASE WHEN f.attnotnull = 't' THEN 'NO' ELSE 'YES' END AS isNull, " + + "pg_catalog.format_type(f.atttypid,f.atttypmod) AS Type, " + + "CASE WHEN p.contype = 'p' THEN 't' ELSE 'f' END AS primarykey, " + + "CASE WHEN p.contype = 'u' THEN 't' ELSE 'f' END AS uniquekey, " + + "CASE WHEN p.contype = 'f' THEN g.relname END AS foreignkey, " + + "CASE WHEN p.contype = 'f' THEN p.confkey END AS foreignkey_fieldnum, " + + "CASE WHEN p.contype = 'f' THEN g.relname END AS foreignkey, " + + "CASE WHEN p.contype = 'f' THEN p.conkey END AS foreignkey_connnum, " + + "CASE WHEN f.atthasdef = 't' THEN d.adsrc END AS default " + + "FROM pg_attribute f JOIN pg_class c ON c.oid = f.attrelid " + + " JOIN pg_type t ON t.oid = f.atttypid " + + " LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum " + + " LEFT JOIN pg_namespace n ON n.oid = c.relnamespace " + + " LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY ( p.conkey ) " + + " LEFT JOIN pg_class AS g ON p.confrelid = g.oid " + + "WHERE c.relkind = 'r'::char AND n.nspname = '%n' " + + "AND c.relname = '%s' AND f.attnum > 0 ORDER BY number"; + + + + break; + default: + throw { + name: "ArgumentError", + message: "Invalid data base type " + cfg.DBTYPE + " should be MySQL or PostgreSQL" + }; + +/* + "Field": "province", + "Type": "varchar(255)", + "Null": "NO", << or is null + "Key": null, + "Default": null, + "Extra": +*/ +} + -var tables = Gda.execute_select_command(cnc, "SHOW TABLES").fetchAll(); +var tables = cnc.execute_select_command( query_tables).fetchAll(); +print(JSON.stringify(tables)); + var readers = []; tables.forEach(function(table) { //print(table); - var schema = Gda.execute_select_command(cnc, "DESCRIBE `" + table+'`').fetchAll(); + var schema = cnc.execute_select_command( + query_describe_table.replace(/%s/, table).replace(/%n/,'public') + ).fetchAll(); + + var reader = []; var colmodel = []; var combofields= [ { name : 'id', type: 'int' } ]; // technically the primary key.. @@ -217,9 +316,12 @@ tables.forEach(function(table) { var firstTxtCol = ''; - print(JSON.stringify(schema, null,4)); + //print(JSON.stringify(schema, null,4)); Seed.quit(); schema.forEach(function(e) { + e.Type = e.Type || e.type; + e.Field = e.Field || e.field; + var type = e.Type.match(/([^(]+)\(([^\)]+)\)/); var row = { }; if (type) { @@ -270,6 +372,8 @@ tables.forEach(function(table) { "*prop": "colModel[]" }); var xtype = 'TextField'; + + if (row.type == 'number') { xtype = 'NumberField'; } @@ -279,9 +383,9 @@ tables.forEach(function(table) { if (e.Type == 'text') { xtype = 'TextArea'; } - if (e.name == 'id') { + if (row.name == 'id') { xtype = 'Hidden'; - } + } // what about booleans.. -> checkboxes.. @@ -293,18 +397,26 @@ tables.forEach(function(table) { '|xns' : 'Roo.form', xtype : xtype } + if (xtype == 'DateField') { + form[row.name].format = 'Y-m-d'; + form[row.name].width = 100; + } + if (xtype == 'TextArea') { form[row.name].height = 100; } - + if (xtype == 'Hidden') { + delete form[row.name].fieldLabel; + delete form[row.name].width; + } }); var combo = { '|xns' : 'Roo.form', xtype: 'ComboBox', - allowBlank : 'false', - editable : 'false', + allowBlank : false, + editable : false, emptyText : 'Select ' + table, forceSelection : true, listWidth : 400, @@ -419,6 +531,7 @@ readers.forEach(function(reader) { continue; } if (typeof(reader.form[col]) == 'undefined') { + print (JSON.stringify(reader.form, null,4)); print("missing linked column " + col); continue; } @@ -454,6 +567,7 @@ readers.forEach(function(reader) { var dir = GLib.get_home_dir() + '/.Builder/Roo.data.JsonReader'; if (!File.isDirectory(dir)) { + print("mkdir " + dir); File.mkdir(dir); } @@ -468,6 +582,7 @@ readers.forEach(function(reader) { root : "data", '*prop' : "reader", id : 'id', // maybe no.. + '|fields' : JSON.stringify(reader.reader, null,4).replace(/"/g,"'") }; @@ -480,6 +595,7 @@ readers.forEach(function(reader) { // GRIDS dir = GLib.get_home_dir() + '/.Builder/Roo.GridPanel'; if (!File.isDirectory(dir)) { + print("mkdir " + dir); File.mkdir(dir); } @@ -498,6 +614,7 @@ readers.forEach(function(reader) { "fitContainer": true, "tableName": reader.table, "background": true, + "region" : 'center', "listeners": { "|activate": "function() {\n _this.panel = this;\n if (_this.grid) {\n _this.grid.footer.onClick('first');\n }\n}" }, @@ -510,12 +627,19 @@ readers.forEach(function(reader) { "listeners": { "|render": "function() \n" + "{\n" + - " _this.grid = this; \n" + + " _this.grid = this; \n" + " //_this.dialog = Pman.Dialog.FILL_IN\n" + " if (_this.panel.active) {\n" + " this.footer.onClick('first');\n" + " }\n" + - "}" + "}", + "|rowdblclick": "function (_self, rowIndex, e)\n" + + "{\n" + + " if (!_this.dialog) return;\n" + + " _this.dialog.show( this.getDataSource().getAt(rowIndex).data, function() {\n" + + " _this.grid.footer.onClick('first');\n" + + " }); \n" + + "}\n" }, "|xns": "Roo.grid", @@ -523,7 +647,8 @@ readers.forEach(function(reader) { { "*prop": "dataSource", "xtype": "Store", - + remoteSort : true, + '|sortInfo' : "{ field : '" + reader.firstTxtCol + "', direction: 'ASC' }", "|xns": "Roo.data", "items": [ @@ -559,9 +684,10 @@ readers.forEach(function(reader) { "listeners": { "|click": "function()\n"+ "{\n"+ - " //yourdialog.show( { id : 0 } , function() {\n"+ - " // _this.grid.footer.onClick('first');\n"+ - " //}); \n"+ + " if (!_this.dialog) return;\n" + + " _this.dialog.show( { id : 0 } , function() {\n"+ + " _this.grid.footer.onClick('first');\n"+ + " }); \n"+ "}\n" }, "|xns": "Roo.Toolbar" @@ -579,10 +705,10 @@ readers.forEach(function(reader) { " Roo.MessageBox.alert(\"Error\", s.length ? \"Select only one Row\" : \"Select a Row\");\n"+ " return;\n"+ " }\n"+ - " \n"+ - " //_this.dialog.show(s[0].data, function() {\n"+ - " // _this.grid.footer.onClick('first');\n"+ - " // }); \n"+ + " if (!_this.dialog) return;\n" + + " _this.dialog.show(s[0].data, function() {\n"+ + " _this.grid.footer.onClick('first');\n"+ + " }); \n"+ " \n"+ "}\n" @@ -597,7 +723,7 @@ readers.forEach(function(reader) { "listeners": { "|click": "function()\n"+ "{\n"+ - " //Pman.genericDelete(_this, _this.grid.tableName); \n"+ + " Pman.genericDelete(_this, '" + reader.table + "'); \n"+ "}\n"+ " " }, @@ -617,61 +743,71 @@ readers.forEach(function(reader) { dir = GLib.get_home_dir() + '/.Builder/Roo.form.Form'; if (!File.isDirectory(dir)) { + print("mkdir " + dir); File.mkdir(dir); } var formElements = []; + var formHeight = 50; for (var k in reader.form) { if (k == 'id') { // should really do primary key testing.. continue; } + formHeight += reader.form[k].xtype == 'TextArea' ? 100 : 30; + formElements.push(reader.form[k]); } - formElements.push(reader.form['id']); + if (reader.form['id']) { + formElements.push(reader.form['id']); + } + print("WRITE: " + dir + '/' + cfg.DBNAME + '_' + reader.table + '.json'); + var frmCfg = + { + '|xns' : 'Roo.form', + xtype : "Form", + listeners : { + "|actioncomplete" : "function(_self,action)\n"+ + "{\n"+ + " if (action.type == 'setdata') {\n"+ + " //_this.dialog.el.mask(\"Loading\");\n"+ + " //this.load({ method: 'GET', params: { '_id' : _this.data.id }});\n"+ + " return;\n"+ + " }\n"+ + " if (action.type == 'load') {\n"+ + " _this.dialog.el.unmask();\n"+ + " return;\n"+ + " }\n"+ + " if (action.type =='submit') {\n"+ + " \n"+ + " _this.dialog.el.unmask();\n"+ + " _this.dialog.hide();\n"+ + " \n"+ + " if (_this.callback) {\n"+ + " _this.callback.call(_this, _this.form.getValues());\n"+ + " }\n"+ + " _this.form.reset();\n"+ + " return;\n"+ + " }\n"+ + "}\n", + + "|rendered" : "function (form)\n"+ + "{\n"+ + " _this.form= form;\n"+ + "}\n" + }, + method : "POST", + style : "margin:10px;", + "|url" : "baseURL + '/Roo/" + reader.table + ".php'", + items : formElements + }; + File.write( dir + '/' + cfg.DBNAME + '_' + reader.table + '.json', - JSON.stringify({ - '|xns' : 'Roo.form', - xtype : "Form", - listeners : { - "|actioncomplete" : "function(_self,action)\n"+ - "{\n"+ - " if (action.type == 'setdata') {\n"+ - " //_this.dialog.el.mask(\"Loading\");\n"+ - " //this.load({ method: 'GET', params: { '_id' : _this.data.id }});\n"+ - " return;\n"+ - " }\n"+ - " if (action.type == 'load') {\n"+ - " _this.dialog.el.unmask();\n"+ - " return;\n"+ - " }\n"+ - " if (action.type =='submit') {\n"+ - " \n"+ - " _this.dialog.el.unmask();\n"+ - " _this.dialog.hide();\n"+ - " \n"+ - " if (_this.callback) {\n"+ - " _this.callback.call(_this, _this.form.getValues());\n"+ - " }\n"+ - " _this.form.reset();\n"+ - " return;\n"+ - " }\n"+ - "}\n", - - "|rendered" : "function (form)\n"+ - "{\n"+ - " _this.form= form;\n"+ - "}\n" - }, - method : "POST", - style : "margin:10px;", - "|url" : "baseURL + '/Roo/" + reader.table + ".php'", - items : formElements - }, null, 4) + JSON.stringify( frmCfg, null, 4) ); @@ -682,6 +818,7 @@ readers.forEach(function(reader) { dir = GLib.get_home_dir() + '/.Builder/Roo.form.ComboBox'; if (!File.isDirectory(dir)) { + print("mkdir " + dir); File.mkdir(dir); } @@ -699,12 +836,79 @@ readers.forEach(function(reader) { + // DIALOG. + dir = GLib.get_home_dir() + '/.Builder/Roo.LayoutDialog'; + if (!File.isDirectory(dir)) { + print("mkdir " + dir); + File.mkdir(dir); + } + var formElements = []; + for (var k in reader.form) { + if (k == 'id') { // should really do primary key testing.. + continue; + } + formElements.push(reader.form[k]); + } + formElements.push(reader.form['id']); + + print("WRITE: " + dir + '/' + cfg.DBNAME + '_' + reader.table + '.json'); + + File.write( + dir + '/' + cfg.DBNAME + '_' + reader.table + '.json', + + + JSON.stringify({ + + "closable": false, + "collapsible": false, + "height": formHeight, + "resizable": false, + "title": "Edit / Create " + reader.table, + "width": 400, + "modal" : true, + "xtype": "LayoutDialog", + "|xns": "Roo", + "items": [ + { + "|xns": "Roo", + "xtype": "LayoutRegion", + "*prop": "center" + }, + { + "region": "center", + "xtype": "ContentPanel", + "|xns": "Roo", + "items": [ + frmCfg + ] + }, + + { + "listeners": { + "click": "function (_self, e)\n{\n _this.dialog.hide();\n}" + }, + "*prop": "buttons[]", + "text": "Cancel", + "xtype": "Button", + "|xns": "Roo" + }, + { + "listeners": { + "click": "function (_self, e)\n{\n // do some checks?\n \n \n _this.dialog.el.mask(\"Saving\");\n _this.form.doAction(\"submit\");\n\n}" + }, + "*prop": "buttons[]", + "text": "Save", + "xtype": "Button", + "|xns": "Roo" + } + ] + }, null,4) + ); -}); - - + +});