2015-12-27 13:30:20 -06:00
|
|
|
define(
|
|
|
|
['jquery', 'underscore', 'pgadmin', 'backbone', 'backform', 'alertify', 'pgadmin.browser.node'],
|
|
|
|
function($, _, pgAdmin, Backbone, Backform, Alertify, Node) {
|
|
|
|
|
|
|
|
var pgBrowser = pgAdmin.Browser;
|
|
|
|
|
2016-01-09 06:29:56 -06:00
|
|
|
// Store value in DOM as stringified JSON.
|
|
|
|
var StringOrJSONFormatter = function() {};
|
|
|
|
_.extend(StringOrJSONFormatter.prototype, {
|
|
|
|
fromRaw: function(rawData, model) {
|
2016-02-03 05:11:06 -06:00
|
|
|
return JSON.stringify(_.escape(rawData));
|
2016-01-09 06:29:56 -06:00
|
|
|
},
|
|
|
|
toRaw: function(formattedData, model) {
|
|
|
|
if (typeof(formattedData) == 'string') {
|
2016-02-03 05:11:06 -06:00
|
|
|
return _.unescape(formattedData);
|
2016-01-09 06:29:56 -06:00
|
|
|
}
|
2016-02-10 01:39:06 -06:00
|
|
|
if (formattedData instanceof Array) {
|
|
|
|
return JSON.stringify(JSON.parse(JSON.stringify(formattedData)));
|
|
|
|
}
|
2016-01-09 06:29:56 -06:00
|
|
|
return JSON.parse(formattedData);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-12-27 13:30:20 -06:00
|
|
|
/*
|
|
|
|
* NodeAjaxOptionsControl
|
|
|
|
* This control will fetch the options required to render the select
|
|
|
|
* control, from the url specific to the pgAdmin.Browser node object.
|
|
|
|
*
|
|
|
|
* In order to use this properly, schema require to set the 'url' property,
|
|
|
|
* which exposes the data for this node.
|
|
|
|
*
|
|
|
|
* In case the url is not providing the data in proper format, we can
|
|
|
|
* specify the 'transform' function too, which will convert the fetched
|
|
|
|
* data to proper 'label', 'value' format.
|
|
|
|
*/
|
|
|
|
var NodeAjaxOptionsControl = Backform.NodeAjaxOptionsControl =
|
|
|
|
Backform.SelectControl.extend({
|
|
|
|
defaults: _.extend(Backform.SelectControl.prototype.defaults, {
|
|
|
|
url: undefined,
|
2016-01-04 01:13:24 -06:00
|
|
|
transform: undefined,
|
2016-01-09 06:29:56 -06:00
|
|
|
url_with_id: false,
|
|
|
|
first_empty: false,
|
2016-01-19 07:50:14 -06:00
|
|
|
empty_value: '-- None --',
|
2016-01-09 06:29:56 -06:00
|
|
|
select2: {
|
|
|
|
allowClear: true,
|
|
|
|
placeholder: 'Select from the list',
|
|
|
|
width: 'style'
|
|
|
|
}
|
2015-12-27 13:30:20 -06:00
|
|
|
}),
|
2016-01-09 06:29:56 -06:00
|
|
|
template: _.template([
|
|
|
|
'<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
|
|
|
|
'<div class="<%=Backform.controlsClassName%> <%=extraClasses.join(\' \')%>">',
|
2016-04-01 04:47:28 -05:00
|
|
|
' <select class="pgadmin-node-select form-control" name="<%=name%>" style="width:100%;" value="<%-value%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> >',
|
2016-01-09 06:29:56 -06:00
|
|
|
' <% if (first_empty) { %>',
|
|
|
|
' <option value="" <%="" === rawValue ? "selected" : "" %>><%- empty_value %></option>',
|
|
|
|
' <% } %>',
|
|
|
|
' <% for (var i=0; i < options.length; i++) { %>',
|
|
|
|
' <% var option = options[i]; %>',
|
|
|
|
' <option <% if (option.image) { %> data-image=<%= option.image %> <% } %> value=<%= formatter.fromRaw(option.value) %> <%=option.value === rawValue ? "selected=\'selected\'" : "" %>><%-option.label%></option>',
|
|
|
|
' <% } %>',
|
|
|
|
' </select>',
|
|
|
|
'</div>'].join("\n")),
|
|
|
|
formatter: StringOrJSONFormatter,
|
2015-12-27 13:30:20 -06:00
|
|
|
initialize: function() {
|
|
|
|
/*
|
|
|
|
* Initialization from the original control.
|
|
|
|
*/
|
|
|
|
Backform.SelectControl.prototype.initialize.apply(this, arguments);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We're about to fetch the options required for this control.
|
|
|
|
*/
|
|
|
|
var self = this,
|
|
|
|
url = self.field.get('url') || self.defaults.url,
|
2016-01-15 05:17:17 -06:00
|
|
|
m = self.model.top || self.model;
|
2015-12-27 13:30:20 -06:00
|
|
|
|
|
|
|
// Hmm - we found the url option.
|
|
|
|
// That means - we needs to fetch the options from that node.
|
|
|
|
if (url) {
|
|
|
|
var node = this.field.get('schema_node'),
|
2016-01-05 03:06:30 -06:00
|
|
|
node_info = this.field.get('node_info'),
|
2016-04-29 05:11:24 -05:00
|
|
|
with_id = this.field.get('url_with_id') || false,
|
2015-12-27 13:30:20 -06:00
|
|
|
full_url = node.generate_url.apply(
|
|
|
|
node, [
|
2016-04-29 05:11:24 -05:00
|
|
|
null, url, this.field.get('node_data'), with_id, node_info
|
2015-12-27 13:30:20 -06:00
|
|
|
]),
|
2016-04-29 05:11:24 -05:00
|
|
|
cache_level,
|
2016-01-09 06:29:56 -06:00
|
|
|
cache_node = this.field.get('cache_node');
|
|
|
|
|
|
|
|
cache_node = (cache_node && pgAdmin.Browser.Nodes['cache_node']) || node;
|
|
|
|
|
2016-04-29 05:11:24 -05:00
|
|
|
if (this.field.has('cache_level')) {
|
|
|
|
cache_level = this.field.get('cache_level');
|
|
|
|
} else {
|
|
|
|
cache_level = cache_node.cache_level(node_info, with_id);
|
|
|
|
}
|
|
|
|
|
2016-01-09 06:29:56 -06:00
|
|
|
/*
|
|
|
|
* We needs to check, if we have already cached data for this url.
|
|
|
|
* If yes - use that, and do not bother about fetching it again,
|
|
|
|
* and use it.
|
|
|
|
*/
|
2016-04-29 05:11:24 -05:00
|
|
|
var data = cache_node.cache(node.type + '#' + url, node_info, cache_level);
|
2016-01-09 06:29:56 -06:00
|
|
|
|
2016-02-10 00:42:06 -06:00
|
|
|
if (this.field.get('version_compatible') &&
|
2016-01-12 00:31:45 -06:00
|
|
|
(_.isUndefined(data) || _.isNull(data))) {
|
2016-01-09 06:29:56 -06:00
|
|
|
m.trigger('pgadmin:view:fetching', m, self.field);
|
2015-12-27 13:30:20 -06:00
|
|
|
$.ajax({
|
|
|
|
async: false,
|
|
|
|
url: full_url,
|
|
|
|
success: function(res) {
|
|
|
|
/*
|
|
|
|
* We will cache this data for short period of time for avoiding
|
|
|
|
* same calls.
|
|
|
|
*/
|
2016-04-29 05:11:24 -05:00
|
|
|
data = cache_node.cache(node.type + '#' + url, node_info, cache_level, res.data);
|
2015-12-27 13:30:20 -06:00
|
|
|
},
|
|
|
|
error: function() {
|
2016-01-09 06:29:56 -06:00
|
|
|
m.trigger('pgadmin:view:fetch:error', m, self.field);
|
2015-12-27 13:30:20 -06:00
|
|
|
}
|
|
|
|
});
|
2016-01-09 06:29:56 -06:00
|
|
|
m.trigger('pgadmin:view:fetched', m, self.field);
|
2015-12-27 13:30:20 -06:00
|
|
|
}
|
2016-01-05 03:06:30 -06:00
|
|
|
// To fetch only options from cache, we do not need time from 'at'
|
|
|
|
// attribute but only options.
|
2016-01-06 07:50:49 -06:00
|
|
|
//
|
|
|
|
// It is feasible that the data may not have been fetched.
|
|
|
|
data = (data && data.data) || [];
|
2015-12-27 13:30:20 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Transform the data
|
|
|
|
*/
|
|
|
|
transform = this.field.get('transform') || self.defaults.transform;
|
|
|
|
if (transform && _.isFunction(transform)) {
|
2016-01-04 00:04:40 -06:00
|
|
|
// We will transform the data later, when rendering.
|
|
|
|
// It will allow us to generate different data based on the
|
|
|
|
// dependencies.
|
|
|
|
self.field.set('options', transform.bind(self, data));
|
2016-01-04 00:49:00 -06:00
|
|
|
} else {
|
|
|
|
self.field.set('options', data);
|
2015-12-27 13:30:20 -06:00
|
|
|
}
|
|
|
|
}
|
2016-01-09 06:29:56 -06:00
|
|
|
},
|
|
|
|
render: function() {
|
2016-05-12 05:44:01 -05:00
|
|
|
|
|
|
|
if(this.$sel && this.$sel.select2) {
|
|
|
|
this.$sel.select2('destroy')
|
|
|
|
}
|
|
|
|
|
2016-01-09 06:29:56 -06:00
|
|
|
/*
|
|
|
|
* Let SelectControl render it, we will do our magic on the
|
|
|
|
* select control in it.
|
|
|
|
*/
|
|
|
|
Backform.SelectControl.prototype.render.apply(this, arguments);
|
|
|
|
|
|
|
|
var d = this.field.toJSON(),
|
2016-01-12 00:36:50 -06:00
|
|
|
select2_opts = _.defaults({}, d.select2, this.defaults.select2),
|
|
|
|
evalF = function(f, d, m) {
|
|
|
|
return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If select2 options do not have any disabled property on this field
|
|
|
|
* and schema has disabled property then we need to apply it
|
|
|
|
*/
|
|
|
|
if(!_.has(select2_opts, 'disabled') && (d && d.disabled)) {
|
Improvised the 'transform/options' function usage with the Select2Cell.
The current implementaton binds the cell/control object, and the ajax
data in the asychronous Cells/Controls with the 'options' functions
extended from the Select2Cell.
The problem starts when we try to fetch the current model from that
options/transform/filter function to do some operation, which does not
require in most of the cases. Except the privileges control - where we
needed the current model for omitting the existing selected object
during transformation, and filtering.
In order resolved the issue, we need a common object, which is shared
among the Cell. In backgrid, the 'Column' object is mong the cell,
hence - implementation logic has been changed to bid the 'Column' object
with the 'options' function and, passed the 'Cell' object as an
arguments.
Because - we do use the common function 'transform' between 'Control'
and 'Cell', we needed make changes in the Select2Control to pass the
Control object as an arguments.
And, make the changes in the privileges control to use the new
implementation. The same logic is also required in some of the
operations, we will be/are working on the table/column nodes.
2016-04-08 00:30:48 -05:00
|
|
|
_.extend(select2_opts, {disabled: evalF(d.disabled, d, this.model)
|
2016-01-12 00:36:50 -06:00
|
|
|
});
|
|
|
|
}
|
2016-01-09 06:29:56 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add empty option as Select2 requires any empty '<option><option>' for
|
|
|
|
* some of its functionality to work and initialize select2 control.
|
|
|
|
*/
|
2016-05-12 05:44:01 -05:00
|
|
|
this.$sel = this.$el.find("select").select2(select2_opts);
|
2016-01-09 06:29:56 -06:00
|
|
|
|
|
|
|
return this;
|
2015-12-27 13:30:20 -06:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-01-09 06:29:56 -06:00
|
|
|
var formatNode = function(opt) {
|
|
|
|
if (!opt.id) {
|
|
|
|
return opt.text;
|
|
|
|
}
|
|
|
|
|
|
|
|
var optimage = $(opt.element).data('image');
|
|
|
|
|
|
|
|
if(!optimage){
|
|
|
|
return opt.text;
|
|
|
|
} else {
|
Improvised the 'transform/options' function usage with the Select2Cell.
The current implementaton binds the cell/control object, and the ajax
data in the asychronous Cells/Controls with the 'options' functions
extended from the Select2Cell.
The problem starts when we try to fetch the current model from that
options/transform/filter function to do some operation, which does not
require in most of the cases. Except the privileges control - where we
needed the current model for omitting the existing selected object
during transformation, and filtering.
In order resolved the issue, we need a common object, which is shared
among the Cell. In backgrid, the 'Column' object is mong the cell,
hence - implementation logic has been changed to bid the 'Column' object
with the 'options' function and, passed the 'Cell' object as an
arguments.
Because - we do use the common function 'transform' between 'Control'
and 'Cell', we needed make changes in the Select2Control to pass the
Control object as an arguments.
And, make the changes in the privileges control to use the new
implementation. The same logic is also required in some of the
operations, we will be/are working on the table/column nodes.
2016-04-08 00:30:48 -05:00
|
|
|
return $('<span></span>').append(
|
|
|
|
$('<span></span>', {class: "wcTabIcon " + optimage})
|
|
|
|
).append(
|
|
|
|
$('<span></span>').text(opt.text)
|
|
|
|
);
|
2016-01-09 06:29:56 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-12-27 13:30:20 -06:00
|
|
|
var NodeListByIdControl = Backform.NodeListByIdControl = NodeAjaxOptionsControl.extend({
|
|
|
|
controlClassName: 'pgadmin-node-select form-control',
|
2016-01-15 06:55:13 -06:00
|
|
|
defaults: _.extend({}, NodeAjaxOptionsControl.prototype.defaults, {
|
2015-12-27 13:30:20 -06:00
|
|
|
first_empty: true,
|
|
|
|
empty_value: '-- None --',
|
|
|
|
url: 'nodes',
|
2016-01-04 01:13:24 -06:00
|
|
|
filter: undefined,
|
2015-12-27 13:30:20 -06:00
|
|
|
transform: function(rows) {
|
|
|
|
var self = this,
|
|
|
|
node = self.field.get('schema_node'),
|
2016-01-04 01:13:24 -06:00
|
|
|
res = [],
|
|
|
|
filter = self.field.get('filter') || function() { return true; };
|
2015-12-27 13:30:20 -06:00
|
|
|
|
2016-01-05 14:55:13 -06:00
|
|
|
filter = filter.bind(self);
|
|
|
|
|
2015-12-27 13:30:20 -06:00
|
|
|
_.each(rows, function(r) {
|
2016-01-04 01:13:24 -06:00
|
|
|
if (filter(r)) {
|
|
|
|
var l = (_.isFunction(node['node_label']) ?
|
|
|
|
(node['node_label']).apply(node, [r, self.model, self]) :
|
|
|
|
r.label),
|
2016-01-04 01:28:29 -06:00
|
|
|
image= (_.isFunction(node['node_image']) ?
|
2016-01-09 06:29:56 -06:00
|
|
|
(node['node_image']).apply(
|
|
|
|
node, [r, self.model, self]
|
|
|
|
) :
|
|
|
|
(node['node_image'] || ('icon-' + node.type)));
|
|
|
|
|
2016-01-04 01:13:24 -06:00
|
|
|
res.push({
|
|
|
|
'value': r._id,
|
2016-01-09 06:29:56 -06:00
|
|
|
'image': image,
|
2016-01-04 01:13:24 -06:00
|
|
|
'label': l
|
|
|
|
});
|
|
|
|
}
|
2015-12-27 13:30:20 -06:00
|
|
|
});
|
|
|
|
|
|
|
|
return res;
|
2016-01-09 06:29:56 -06:00
|
|
|
},
|
|
|
|
select2: {
|
|
|
|
allowClear: true,
|
|
|
|
placeholder: 'Select from the list',
|
|
|
|
width: 'style',
|
|
|
|
templateResult: formatNode,
|
|
|
|
templateSelection: formatNode
|
2015-12-27 13:30:20 -06:00
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var NodeListByNameControl = Backform.NodeListByNameControl = NodeListByIdControl.extend({
|
2016-01-15 06:55:13 -06:00
|
|
|
defaults: _.extend({}, NodeListByIdControl.prototype.defaults, {
|
2015-12-27 13:30:20 -06:00
|
|
|
transform: function(rows) {
|
|
|
|
var self = this,
|
|
|
|
node = self.field.get('schema_node'),
|
2016-01-04 01:13:24 -06:00
|
|
|
res = [],
|
|
|
|
filter = self.field.get('filter') || function() { return true; };
|
2015-12-27 13:30:20 -06:00
|
|
|
|
2016-01-05 14:55:13 -06:00
|
|
|
filter = filter.bind(self);
|
|
|
|
|
2015-12-27 13:30:20 -06:00
|
|
|
_.each(rows, function(r) {
|
2016-01-04 01:13:24 -06:00
|
|
|
if (filter(r)) {
|
|
|
|
var l = (_.isFunction(node['node_label']) ?
|
|
|
|
(node['node_label']).apply(node, [r, self.model, self]) :
|
|
|
|
r.label),
|
2016-01-09 06:29:56 -06:00
|
|
|
image = (_.isFunction(node['node_image']) ?
|
|
|
|
(node['node_image']).apply(
|
|
|
|
node, [r, self.model, self]
|
|
|
|
) :
|
|
|
|
(node['node_image'] || ('icon-' + node.type)));
|
2016-01-04 01:13:24 -06:00
|
|
|
res.push({
|
2016-01-05 14:55:13 -06:00
|
|
|
'value': r.label,
|
2016-01-09 06:29:56 -06:00
|
|
|
'image': image,
|
2016-01-04 01:13:24 -06:00
|
|
|
'label': l
|
|
|
|
});
|
|
|
|
}
|
2015-12-27 13:30:20 -06:00
|
|
|
});
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2016-01-09 06:29:56 -06:00
|
|
|
/*
|
|
|
|
* Global function to make visible particular dom element in it's parent
|
|
|
|
* with given class.
|
|
|
|
*/
|
|
|
|
$.fn.pgMakeVisible = function( cls ) {
|
|
|
|
return this.each(function() {
|
|
|
|
if (!this || !$(this.length))
|
|
|
|
return;
|
|
|
|
var top, p = $(this), hasScrollbar = function(j) {
|
|
|
|
if (j && j.length > 0) {
|
|
|
|
return j.get(0).scrollHeight > j.height();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2016-04-13 10:11:43 -05:00
|
|
|
// check if p is not empty
|
|
|
|
while(p && p.length > 0) {
|
2016-01-09 06:29:56 -06:00
|
|
|
top = p.get(0).offsetTop + p.height();
|
|
|
|
p = p.parent();
|
|
|
|
if (hasScrollbar(p)) {
|
|
|
|
p.scrollTop(top);
|
|
|
|
}
|
|
|
|
if (p.hasClass(cls)) //'backform-tab'
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-01-15 06:55:13 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* NodeAjaxOptionsCell
|
|
|
|
* This cell will fetch the options required to render the select
|
|
|
|
* cell, from the url specific to the pgAdmin.Browser node object.
|
|
|
|
*
|
|
|
|
* In order to use this properly, schema require to set the 'url' property,
|
|
|
|
* which exposes the data for this node.
|
|
|
|
*
|
|
|
|
* In case the url is not providing the data in proper format, we can
|
|
|
|
* specify the 'transform' function too, which will convert the fetched
|
|
|
|
* data to proper 'label', 'value' format.
|
|
|
|
*/
|
|
|
|
var NodeAjaxOptionsCell = Backgrid.Extension.NodeAjaxOptionsCell = Backgrid.Extension.Select2Cell.extend({
|
|
|
|
defaults: _.extend({}, Backgrid.Extension.Select2Cell.prototype.defaults, {
|
|
|
|
url: undefined,
|
|
|
|
transform: undefined,
|
|
|
|
url_with_id: false,
|
|
|
|
select2: {
|
|
|
|
allowClear: true,
|
|
|
|
placeholder: 'Select from the list',
|
|
|
|
width: 'style'
|
Improvised Select2Cell, and SwitchCell.
Removed the use of separate editor for both of these cell types. There
were two instance of select2 were getting created in the Select2Cell,
one in the Select2Cell itself, and another in Select2CellEditor. And,
loosing the focus mysteriously, and making the scrollbar in the property
dialog non-responsive.
Also, modified the NodeAjaxOptionsCell to use the above logic, and
removed its own version of render function to make it consitent across
the system.
This patch [changes sent by Murtuza] also includes improvisation in the
DeleteCell, and ObjectCell, which will honour now 'canRemoveRow', and
''canEditRow' respective properties of Column.
2016-04-12 06:20:43 -05:00
|
|
|
},
|
|
|
|
opt: {
|
|
|
|
label: null,
|
|
|
|
value: null,
|
|
|
|
image: null,
|
|
|
|
selected: false
|
|
|
|
}
|
2016-01-15 06:55:13 -06:00
|
|
|
}),
|
|
|
|
template: _.template(
|
Improvised Select2Cell, and SwitchCell.
Removed the use of separate editor for both of these cell types. There
were two instance of select2 were getting created in the Select2Cell,
one in the Select2Cell itself, and another in Select2CellEditor. And,
loosing the focus mysteriously, and making the scrollbar in the property
dialog non-responsive.
Also, modified the NodeAjaxOptionsCell to use the above logic, and
removed its own version of render function to make it consitent across
the system.
This patch [changes sent by Murtuza] also includes improvisation in the
DeleteCell, and ObjectCell, which will honour now 'canRemoveRow', and
''canEditRow' respective properties of Column.
2016-04-12 06:20:43 -05:00
|
|
|
'<option <% if (image) { %> data-image=<%= image %> <% } %> value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- label %></option>'
|
2016-01-15 06:55:13 -06:00
|
|
|
),
|
|
|
|
initialize: function () {
|
|
|
|
Backgrid.Extension.Select2Cell.prototype.initialize.apply(this, arguments);
|
|
|
|
|
2016-03-15 08:28:16 -05:00
|
|
|
var url = this.column.get('url') || this.defaults.url,
|
|
|
|
options_cached = this.column.get('options_cached');
|
2016-01-15 06:55:13 -06:00
|
|
|
|
|
|
|
// Hmm - we found the url option.
|
|
|
|
// That means - we needs to fetch the options from that node.
|
2016-03-15 08:28:16 -05:00
|
|
|
if (url && !options_cached) {
|
|
|
|
|
|
|
|
var self = this,
|
2016-03-18 06:59:49 -05:00
|
|
|
m = this.model, column = this.column,
|
|
|
|
eventHandler = m.top || m,
|
2016-03-15 08:28:16 -05:00
|
|
|
node = column.get('schema_node'),
|
|
|
|
node_info = column.get('node_info'),
|
2016-04-29 05:11:24 -05:00
|
|
|
with_id = column.get('url_with_id') || false,
|
2016-01-15 06:55:13 -06:00
|
|
|
full_url = node.generate_url.apply(
|
|
|
|
node, [
|
2016-04-29 05:11:24 -05:00
|
|
|
null, url, column.get('node_data'), with_id, node_info
|
2016-01-15 06:55:13 -06:00
|
|
|
]),
|
2016-04-29 05:11:24 -05:00
|
|
|
cache_level,
|
2016-03-15 08:28:16 -05:00
|
|
|
cache_node = column.get('cache_node');
|
2016-01-15 06:55:13 -06:00
|
|
|
|
|
|
|
cache_node = (cache_node && pgAdmin.Browser.Nodes['cache_node']) || node;
|
|
|
|
|
2016-04-29 06:55:16 -05:00
|
|
|
if (column.has('cache_level')) {
|
|
|
|
cache_level = column.get('cache_level');
|
2016-04-29 05:11:24 -05:00
|
|
|
} else {
|
|
|
|
cache_level = cache_node.cache_level(node_info, with_id);
|
|
|
|
}
|
|
|
|
|
2016-01-15 06:55:13 -06:00
|
|
|
/*
|
|
|
|
* We needs to check, if we have already cached data for this url.
|
|
|
|
* If yes - use that, and do not bother about fetching it again,
|
|
|
|
* and use it.
|
|
|
|
*/
|
2016-04-29 05:11:24 -05:00
|
|
|
var data = cache_node.cache(node.type + '#' + url, node_info, cache_level);
|
2016-01-15 06:55:13 -06:00
|
|
|
|
2016-03-15 08:28:16 -05:00
|
|
|
if (column.get('version_compatible') &&
|
2016-01-15 06:55:13 -06:00
|
|
|
(_.isUndefined(data) || _.isNull(data))) {
|
2016-03-15 08:28:16 -05:00
|
|
|
eventHandler.trigger('pgadmin:view:fetching', m, column);
|
2016-01-15 06:55:13 -06:00
|
|
|
$.ajax({
|
|
|
|
async: false,
|
|
|
|
url: full_url,
|
|
|
|
success: function(res) {
|
|
|
|
/*
|
|
|
|
* We will cache this data for short period of time for avoiding
|
|
|
|
* same calls.
|
|
|
|
*/
|
2016-04-29 05:11:24 -05:00
|
|
|
data = cache_node.cache(node.type + '#' + url, node_info, cache_level, res.data);
|
2016-01-15 06:55:13 -06:00
|
|
|
},
|
|
|
|
error: function() {
|
2016-03-15 08:28:16 -05:00
|
|
|
eventHandler.trigger('pgadmin:view:fetch:error', m, column);
|
2016-01-15 06:55:13 -06:00
|
|
|
}
|
|
|
|
});
|
2016-03-15 08:28:16 -05:00
|
|
|
eventHandler.trigger('pgadmin:view:fetched', m, column);
|
2016-01-15 06:55:13 -06:00
|
|
|
}
|
|
|
|
// To fetch only options from cache, we do not need time from 'at'
|
|
|
|
// attribute but only options.
|
|
|
|
//
|
|
|
|
// It is feasible that the data may not have been fetched.
|
|
|
|
data = (data && data.data) || [];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Transform the data
|
|
|
|
*/
|
2016-03-15 08:28:16 -05:00
|
|
|
transform = column.get('transform') || self.defaults.transform;
|
2016-01-15 06:55:13 -06:00
|
|
|
if (transform && _.isFunction(transform)) {
|
|
|
|
// We will transform the data later, when rendering.
|
|
|
|
// It will allow us to generate different data based on the
|
|
|
|
// dependencies.
|
Improvised the 'transform/options' function usage with the Select2Cell.
The current implementaton binds the cell/control object, and the ajax
data in the asychronous Cells/Controls with the 'options' functions
extended from the Select2Cell.
The problem starts when we try to fetch the current model from that
options/transform/filter function to do some operation, which does not
require in most of the cases. Except the privileges control - where we
needed the current model for omitting the existing selected object
during transformation, and filtering.
In order resolved the issue, we need a common object, which is shared
among the Cell. In backgrid, the 'Column' object is mong the cell,
hence - implementation logic has been changed to bid the 'Column' object
with the 'options' function and, passed the 'Cell' object as an
arguments.
Because - we do use the common function 'transform' between 'Control'
and 'Cell', we needed make changes in the Select2Control to pass the
Control object as an arguments.
And, make the changes in the privileges control to use the new
implementation. The same logic is also required in some of the
operations, we will be/are working on the table/column nodes.
2016-04-08 00:30:48 -05:00
|
|
|
column.set('options', transform.bind(column, data));
|
2016-01-15 06:55:13 -06:00
|
|
|
} else {
|
2016-03-15 08:28:16 -05:00
|
|
|
column.set('options', data);
|
2016-01-15 06:55:13 -06:00
|
|
|
}
|
2016-03-15 08:28:16 -05:00
|
|
|
column.set('options_cached', true);
|
2016-01-15 06:55:13 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var NodeListByIdCell = Backgrid.Extension.NodeListByIdCell = NodeAjaxOptionsCell.extend({
|
|
|
|
controlClassName: 'pgadmin-node-select backgrid-cell',
|
|
|
|
defaults: _.extend({}, NodeAjaxOptionsCell.prototype.defaults, {
|
|
|
|
url: 'nodes',
|
|
|
|
filter: undefined,
|
Improvised the 'transform/options' function usage with the Select2Cell.
The current implementaton binds the cell/control object, and the ajax
data in the asychronous Cells/Controls with the 'options' functions
extended from the Select2Cell.
The problem starts when we try to fetch the current model from that
options/transform/filter function to do some operation, which does not
require in most of the cases. Except the privileges control - where we
needed the current model for omitting the existing selected object
during transformation, and filtering.
In order resolved the issue, we need a common object, which is shared
among the Cell. In backgrid, the 'Column' object is mong the cell,
hence - implementation logic has been changed to bid the 'Column' object
with the 'options' function and, passed the 'Cell' object as an
arguments.
Because - we do use the common function 'transform' between 'Control'
and 'Cell', we needed make changes in the Select2Control to pass the
Control object as an arguments.
And, make the changes in the privileges control to use the new
implementation. The same logic is also required in some of the
operations, we will be/are working on the table/column nodes.
2016-04-08 00:30:48 -05:00
|
|
|
transform: function(rows, control) {
|
|
|
|
var self = control || this,
|
2016-01-15 06:55:13 -06:00
|
|
|
node = self.column.get('schema_node'),
|
|
|
|
res = [],
|
|
|
|
filter = self.column.get('filter') || function() { return true; };
|
|
|
|
|
|
|
|
filter = filter.bind(self);
|
|
|
|
|
|
|
|
_.each(rows, function(r) {
|
|
|
|
if (filter(r)) {
|
|
|
|
var l = (_.isFunction(node['node_label']) ?
|
|
|
|
(node['node_label']).apply(node, [r, self.model, self]) :
|
|
|
|
r.label),
|
|
|
|
image= (_.isFunction(node['node_image']) ?
|
|
|
|
(node['node_image']).apply(
|
|
|
|
node, [r, self.model, self]
|
|
|
|
) :
|
|
|
|
(node['node_image'] || ('icon-' + node.type)));
|
|
|
|
|
|
|
|
res.push({
|
|
|
|
'value': r._id,
|
|
|
|
'image': image,
|
|
|
|
'label': l
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return res;
|
|
|
|
},
|
|
|
|
select2: {
|
|
|
|
placeholder: 'Select from the list',
|
|
|
|
width: 'style',
|
|
|
|
templateResult: formatNode,
|
|
|
|
templateSelection: formatNode
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var NodeListByNameCell = Backgrid.Extension.NodeListByNameCell = NodeAjaxOptionsCell.extend({
|
|
|
|
controlClassName: 'pgadmin-node-select backgrid-cell',
|
|
|
|
defaults: _.extend({}, NodeAjaxOptionsCell.prototype.defaults, {
|
|
|
|
url: 'nodes',
|
|
|
|
filter: undefined,
|
Improvised the 'transform/options' function usage with the Select2Cell.
The current implementaton binds the cell/control object, and the ajax
data in the asychronous Cells/Controls with the 'options' functions
extended from the Select2Cell.
The problem starts when we try to fetch the current model from that
options/transform/filter function to do some operation, which does not
require in most of the cases. Except the privileges control - where we
needed the current model for omitting the existing selected object
during transformation, and filtering.
In order resolved the issue, we need a common object, which is shared
among the Cell. In backgrid, the 'Column' object is mong the cell,
hence - implementation logic has been changed to bid the 'Column' object
with the 'options' function and, passed the 'Cell' object as an
arguments.
Because - we do use the common function 'transform' between 'Control'
and 'Cell', we needed make changes in the Select2Control to pass the
Control object as an arguments.
And, make the changes in the privileges control to use the new
implementation. The same logic is also required in some of the
operations, we will be/are working on the table/column nodes.
2016-04-08 00:30:48 -05:00
|
|
|
transform: function(rows, control) {
|
|
|
|
var self = control || this,
|
2016-01-15 06:55:13 -06:00
|
|
|
node = self.column.get('schema_node'),
|
|
|
|
res = [],
|
|
|
|
filter = self.column.get('filter') || function() { return true; };
|
|
|
|
|
|
|
|
filter = filter.bind(self);
|
|
|
|
|
|
|
|
_.each(rows, function(r) {
|
|
|
|
if (filter(r)) {
|
|
|
|
var l = (_.isFunction(node['node_label']) ?
|
|
|
|
(node['node_label']).apply(node, [r, self.model, self]) :
|
|
|
|
r.label),
|
|
|
|
image= (_.isFunction(node['node_image']) ?
|
|
|
|
(node['node_image']).apply(
|
|
|
|
node, [r, self.model, self]
|
|
|
|
) :
|
|
|
|
(node['node_image'] || ('icon-' + node.type)));
|
|
|
|
|
|
|
|
res.push({
|
|
|
|
'value': r.label,
|
|
|
|
'image': image,
|
|
|
|
'label': l
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return res;
|
|
|
|
},
|
|
|
|
select2: {
|
|
|
|
placeholder: 'Select from the list',
|
|
|
|
width: 'style',
|
|
|
|
templateResult: formatNode,
|
|
|
|
templateSelection: formatNode
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2016-05-19 10:33:26 -05:00
|
|
|
// Extend the browser's node model class to create a option/value pair
|
|
|
|
var MultiSelectAjaxCell = Backgrid.Extension.MultiSelectAjaxCell = Backgrid.Extension.NodeAjaxOptionsCell.extend({
|
|
|
|
defaults: _.extend({}, NodeAjaxOptionsCell.prototype.defaults, {
|
|
|
|
transform: undefined,
|
|
|
|
url_with_id: false,
|
|
|
|
select2: {
|
|
|
|
allowClear: true,
|
|
|
|
placeholder: 'Select from the list',
|
|
|
|
width: 'style',
|
|
|
|
multiple: true
|
|
|
|
},
|
|
|
|
opt: {
|
|
|
|
label: null,
|
|
|
|
value: null,
|
|
|
|
image: null,
|
|
|
|
selected: false
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
getValueFromDOM: function() {
|
|
|
|
var res = [];
|
|
|
|
|
|
|
|
this.$el.find("select").find(':selected').each(function() {
|
|
|
|
res.push($(this).attr('value'));
|
|
|
|
});
|
|
|
|
|
|
|
|
return res;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
Backform control for selecting multiple columns.
Usage:
{
id: 'columns', label: '{{ _('Columns') }}',
type: 'collection', group: '{{ _('Definition') }}', editable:true,
canDelete: true, canAdd: true, control: Backform.MultiColumnSelectControl,
deps: ['index'], node: 'column',
model: pgBrowser.Node.Model.extend({
keys: ['column'],
defaults: {
column: undefined
}
})
}
Note: When using this control model should have column attribute. And node property should be column.
2016-03-22 11:52:34 -05:00
|
|
|
/*
|
|
|
|
* Control to select multiple columns.
|
|
|
|
*/
|
|
|
|
var MultiSelectAjaxControl = Backform.MultiSelectAjaxControl = NodeAjaxOptionsControl.extend({
|
|
|
|
formatter: {
|
|
|
|
fromRaw: function (rawData, model) {
|
|
|
|
return (_.isUndefined(rawData) || _.isObject(rawData)) ? rawData : JSON.parse(rawData);
|
|
|
|
},
|
|
|
|
toRaw: function (formattedData, model) {
|
|
|
|
return formattedData;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
template: _.template([
|
|
|
|
'<label class="control-label col-sm-4"><%=label%></label>',
|
|
|
|
'<div class="pgadmin-controls col-sm-8">',
|
|
|
|
' <select multiple="multiple" style="width:100%;" class="pgadmin-controls <%=extraClasses.join(\' \')%>" name="<%=name%>" value="<%-JSON.stringify(value)%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%>>',
|
|
|
|
' <% for (var i=0; i < options.length; i++) { %>',
|
|
|
|
' <% var option = options[i]; %>',
|
|
|
|
' <option value=<%-option.value%> <%=value != null && _.indexOf(value, option.value) != -1 ? "selected" : ""%> <%=option.disabled ? "disabled=\'disabled\'" : ""%>><%-option.label%></option>',
|
|
|
|
' <% } %>',
|
|
|
|
' </select>',
|
|
|
|
'</div>'
|
|
|
|
].join("\n")),
|
|
|
|
getValueFromDOM: function() {
|
|
|
|
var res = [];
|
|
|
|
|
|
|
|
this.$el.find("select").find(':selected').each(function() {
|
|
|
|
res.push($(this).attr('value'));
|
|
|
|
});
|
|
|
|
|
|
|
|
return res;
|
|
|
|
},
|
|
|
|
defaults: _.extend({}, NodeAjaxOptionsControl.prototype.defaults, {
|
|
|
|
select2: {
|
|
|
|
multiple: true,
|
|
|
|
allowClear: true,
|
|
|
|
width: 'style'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
2016-01-15 06:55:13 -06:00
|
|
|
|
2016-01-09 06:29:56 -06:00
|
|
|
return Backform;
|
2015-12-27 13:30:20 -06:00
|
|
|
});
|