(function(root, factory) { // Set up Backform appropriately for the environment. Start with AMD. if (typeof define === 'function' && define.amd) { define([ 'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify', 'pgadmin', 'pgadmin.browser.node', 'pgadmin.browser.node.ui' ], function(_, $, Backbone, Backform, Backgrid, Alertify, pgAdmin, pgNode) { // Export global even in AMD case in case this script is loaded with // others that may still expect a global Backform. return factory(root, _, $, Backbone, Backform, Alertify, pgAdmin, pgNode); }); // Next for Node.js or CommonJS. jQuery may not be needed as a module. } else if (typeof exports !== 'undefined') { var _ = require('underscore') || root._, $ = root.jQuery || root.$ || root.Zepto || root.ender, Backbone = require('backbone') || root.Backbone, Backform = require('backform') || root.Backform; Alertify = require('alertify') || root.Alertify; pgAdmin = require('pgadmin') || root.pgAdmin, pgNode = require('pgadmin.browser.node') || root.pgAdmin.Browser.Node; factory(root, _, $, Backbone, Backform, Alertify, pgAdmin, pgNode); // Finally, as a browser global. } else { factory( root, root._, (root.jQuery || root.Zepto || root.ender || root.$), root.Backbone, root.Backform, root.pgAdmin.Browser.Node ); } } (this, function(root, _, $, Backbone, Backform, Alertify, pgAdmin, pgNode) { /** * VariableModel used to represent configuration parameters (variables tab) * for database objects. **/ var VariableModel = pgNode.VariableModel = pgNode.Model.extend({ defaults: { name: undefined, value: '', role: undefined, database: undefined, }, keys: ['name', 'role', 'database'], schema: [ {id: 'name', label:'Name', type:'text', editable: false, cellHeaderClasses: 'width_percent_30'}, { id: 'value', label:'Value', type: 'text', cell: 'dynamic-variable', editable: true, cellHeaderClasses: 'width_percent_50' }, {id: 'database', label:'Database', type: 'text', editable: false}, {id: 'role', label:'Role', type: 'text', editable: false} ], toJSON: function() { var d = Backbone.Model.prototype.toJSON.apply(this); // Remove not defined values from model values. // i.e. // role, database if (_.isUndefined(d.database) || _.isNull(d.database)) { delete d.database; } if (_.isUndefined(d.role) || _.isNull(d.role)) { delete d.role; } return d; }, validate: function() { if (_.isUndefined(this.get('value')) || String(this.get('value')).replace(/^\s+|\s+$/g, '') == '') { var msg = 'Please enter some value!'; this.errorModel.set('value', msg); return msg; } else { this.errorModel.unset('value'); } return null; } }); /* * Dynamic Variable cell. Used for variable data type column in Variables tab. * Behaviour of cell depends on variable data type. */ var DynamicVariableCell = Backgrid.Extension.DynamicVariableCell = Backgrid.Cell.extend({ /* * Mapping of postgres data type to backgrid cell type. */ variableCellMapper: { "bool":Backgrid.Extension.SwitchCell, "enum":Backgrid.Extension.Select2Cell, "string":Backgrid.Cell, "integer":Backgrid.IntegerCell, "real":Backgrid.NumberCell }, initialize: function (opts) { var self = this, name = opts.model.get("name"); self.availVariables = opts.column.get('availVariables'); var variable = (self.availVariables[name]), cell = self.variableCellMapper[variable && variable.vartype] || Backgrid.Cell; /* * Set properties for dynamic cell. */ _.each(cell.prototype, function(v,k) { self[k] = v; }); DynamicVariableCell.__super__.initialize.apply(self, arguments); switch(variable && variable.vartype) { case "bool": // There are no specific properties for BooleanCell. break; case "enum": var options = [], name = self.model.get("name"), enumVals = variable.enumvals; _.each(enumVals, function(enumVal) { options.push([enumVal, enumVal]); }); self.optionValues = options; self.multiple = cell.prototype.multiple; self.delimiter = cell.prototype.delimiter; self.listenTo( self.model, "backgrid:edit", function (model, column, cell, editor) { if (column.get("name") == self.column.get("name")) { editor.setOptionValues(self.optionValues); editor.setMultiple(self.multiple); } }); break; case "integer": self.decimals = 0; self.decimalSeparator = cell.prototype.decimalSeparator; self.orderSeparator = cell.prototype.orderSeparator; var formatter = self.formatter; formatter.decimals = self.decimals; formatter.decimalSeparator = self.decimalSeparator; formatter.orderSeparator = self.orderSeparator; break; case "real": self.decimals = cell.prototype.decimals; self.decimalSeparator = cell.prototype.decimalSeparator; self.orderSeparator = cell.prototype.orderSeparator; var formatter = self.formatter; formatter.decimals = self.decimals; formatter.decimalSeparator = self.decimalSeparator; formatter.orderSeparator = self.orderSeparator; break; case "string": default: // There are no specific properties for StringCell and Cell. break; } } }); /** * Variable Tab Control to set/update configuration values for database object. * **/ var VariableCollectionControl = Backform.VariableCollectionControl = Backform.UniqueColCollectionControl.extend({ hasDatabase: false, hasRole: false, defaults: _.extend({ uniqueCol: ['name', 'role', 'database'] }, Backform.UniqueColCollectionControl.prototype.defaults ), initialize: function(opts) { var self = this; // Overriding the uniqueCol in the field if (opts && opts.field) { if (opts.field instanceof Backform.Field) { opts.field.set({ uniqueCol: ['name', 'role', 'database'], model: pgNode.VariableModel }, { silent: true }); } else { opts.field.extend({ uniqueCol: ['name', 'role', 'database'], model: pgNode.VariableModel }); } } Backform.UniqueColCollectionControl.prototype.initialize.apply( self, arguments ); self.hasDatabase = self.field.get('hasDatabase'); self.hasRole = self.field.get('hasRole'); self.availVariables = {}; var node = self.field.get('node').type, headerSchema = [{ id: 'name', label:'', type:'text', url: self.field.get('variable_opts') || 'vopts', control: Backform.NodeAjaxOptionsControl, cache_level: 'server', select2: { allowClear: false, width: 'style' }, availVariables: self.availVariables, node: node, first_empty: false, version_compitible: self.field.get('version_compitible'), transform: function(vars) { var self = this, opts = self.field.get('availVariables'); res = []; for (var prop in opts) { if (opts.hasOwnProperty(prop)) { delete opts[prop]; } } _.each(vars, function(v) { opts[v.name] = _.extend({}, v); res.push({ 'label': v.name, 'value': v.name }); }); return res; } }], headerDefaults = {name: null}, gridCols = ['name', 'value']; if (self.hasDatabase) { headerSchema.push({ id: 'database', label:'', type: 'text', cache_level: 'server', control: Backform.NodeListByNameControl, node: 'database', version_compitible: self.field.get('version_compitible') }); headerDefaults['database'] = null; gridCols.push('database'); } if (self.hasRole) { headerSchema.push({ id: 'role', label:'', type: 'text', cache_level: 'server', control: Backform.NodeListByNameControl, node: 'role', version_compitible: self.field.get('version_compitible') }); headerDefaults['role'] = null; gridCols.push('role'); } self.headerData = new (Backbone.Model.extend({ defaults: headerDefaults, schema: headerSchema }))({}); var headerGroups = Backform.generateViewSchema( self.field.get('node_info'), self.headerData, 'create', node, self.field.get('node_data') ); var fields = []; _.each(headerGroups, function(val, key) { fields = fields.concat(headerGroups[key]); }); self.headerFields = new Backform.Fields(fields); self.gridSchema = Backform.generateGridColumnsFromModel( null, VariableModel, 'edit', gridCols ); // Make sure - we do have the data for variables self.getVariables(); self.controls = []; self.listenTo(self.headerData, "change", self.headerDataChanged); self.listenTo(self.headerData, "select2", self.headerDataChanged); self.listenTo(self.collection, "remove", self.onRemoveVariable); }, /* * Get the variable data for this node. */ getVariables: function() { var self = this, url = this.field.get('url'), m = self.model; if (!this.field.get('version_compitible')) return; if (url && !m.isNew()) { var node = self.field.get('node'), node_data = self.field.get('node_data'), node_info = self.field.get('node_info'), full_url = node.generate_url.apply( node, [ null, url, node_data, true, node_info ]), data, isTracking = self.collection.trackChanges; if (isTracking) { self.collection.stopSession(); } m.trigger('pgadmin-view:fetching', m, self.field); $.ajax({ async: false, url: full_url, success: function (res) { data = res.data; }, error: function() { m.trigger('pgadmin-view:fetch:error', m, self.field); } }); m.trigger('pgadmin-view:fetched', m, self.field); if (data && _.isArray(data)) { self.collection.reset(data, {silent: true}); } /* * Make sure - new data will be taken care by the session management */ if (isTracking) { self.collection.startNewSession(); } } }, generateHeader: function(data) { var header = [ '