*
* write readers..
*
- * usage: seed generate.js
+ * usage: seed generate.js
+ *
+ *
+ *
+ *
+ *Hack needed to latest GLib-2.0.gir
+ *
+ * <record name="KeyFile" c:type="GKeyFile" disguised="1">
+ <constructor name="new" c:identifier="g_key_file_new">
+ <return-value transfer-ownership="full">
+ <type name="KeyFile" c:type="GKeyFile*"/>
+ </return-value>
+ </constructor>
+ *
+ *
+ * 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;
File = imports.File.File;
Options = imports.Options.Options;
-Gda.init();
+//Gda.init();
var prov = Gda.Config.list_providers ();
//print(prov.dump_as_string());
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.' },
]
})
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);
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',
'mediumtext' : 'string',
'enum' : 'string',
'timestamp' : 'number',
- 'blob' : 'text'
+ 'blob' : 'text',
+ 'bytea' : 'text',
+ 'boolean' : 'int',
+ 'text[]' : 'string',
}
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);
}
}
+
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..
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) {
"*prop": "colModel[]"
});
var xtype = 'TextField';
+
+
if (row.type == 'number') {
xtype = 'NumberField';
}
if (e.Type == 'text') {
xtype = 'TextArea';
}
- if (e.name == 'id') {
+ if (row.name == 'id') {
xtype = 'Hidden';
- }
+ }
// what about booleans.. -> checkboxes..
'|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,
continue;
}
if (typeof(reader.form[col]) == 'undefined') {
+ print (JSON.stringify(reader.form, null,4));
print("missing linked column " + col);
continue;
}
var dir = GLib.get_home_dir() + '/.Builder/Roo.data.JsonReader';
if (!File.isDirectory(dir)) {
+ print("mkdir " + dir);
File.mkdir(dir);
}
root : "data",
'*prop' : "reader",
id : 'id', // maybe no..
+
'|fields' : JSON.stringify(reader.reader, null,4).replace(/"/g,"'")
};
// GRIDS
dir = GLib.get_home_dir() + '/.Builder/Roo.GridPanel';
if (!File.isDirectory(dir)) {
+ print("mkdir " + dir);
File.mkdir(dir);
}
"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}"
},
"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",
{
"*prop": "dataSource",
"xtype": "Store",
-
+ remoteSort : true,
+ '|sortInfo' : "{ field : '" + reader.firstTxtCol + "', direction: 'ASC' }",
"|xns": "Roo.data",
"items": [
"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"
" 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"
"listeners": {
"|click": "function()\n"+
"{\n"+
- " //Pman.genericDelete(_this, _this.grid.tableName); \n"+
+ " Pman.genericDelete(_this, '" + reader.table + "'); \n"+
"}\n"+
" "
},
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)
);
dir = GLib.get_home_dir() + '/.Builder/Roo.form.ComboBox';
if (!File.isDirectory(dir)) {
+ print("mkdir " + dir);
File.mkdir(dir);
}
+ // 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)
+ );
-});
-
-
+
+});