Port Foreign Table node to react. Fixes #6678.
parent
261cec1d20
commit
42eac6f846
|
@ -338,6 +338,8 @@ class ForeignTableView(PGChildNodeView, DataTypeReader,
|
|||
|
||||
if not isinstance(req[key], list) and req[key]:
|
||||
data[key] = json.loads(req[key], encoding='utf-8')
|
||||
elif req[key]:
|
||||
data[key] = req[key]
|
||||
|
||||
if key == 'inherits':
|
||||
# Convert Table ids from unicode/string to int
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import { getNodeListByName, getNodeAjaxOptions } from '../../../../../../../static/js/node_ajax';
|
||||
import { getNodeVariableSchema } from '../../../../../static/js/variable.ui';
|
||||
import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
|
||||
import ForeignTableSchema from './foreign_table.ui';
|
||||
|
||||
/* Create and Register Foreign Table Collection and Node. */
|
||||
define('pgadmin.node.foreign_table', [
|
||||
|
@ -90,7 +94,8 @@ define('pgadmin.node.foreign_table', [
|
|||
self.model.type_options = d;
|
||||
return d;
|
||||
},
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'typlen', label: gettext('Length'),
|
||||
cell: 'string', group: gettext('Definition'),
|
||||
type: 'int', deps: ['datatype'],
|
||||
|
@ -147,7 +152,8 @@ define('pgadmin.node.foreign_table', [
|
|||
return true;
|
||||
},
|
||||
cellHeaderClasses: 'width_percent_10',
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'precision', label: gettext('Precision'),
|
||||
type: 'int', deps: ['datatype'],
|
||||
cell: 'string', group: gettext('Definition'),
|
||||
|
@ -200,7 +206,8 @@ define('pgadmin.node.foreign_table', [
|
|||
}
|
||||
return true;
|
||||
}, cellHeaderClasses: 'width_percent_10',
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'typdefault', label: gettext('Default'), type: 'text',
|
||||
cell: 'string', min_version: 90300, group: gettext('Definition'),
|
||||
placeholder: gettext('Enter an expression or a value.'),
|
||||
|
@ -215,11 +222,13 @@ define('pgadmin.node.foreign_table', [
|
|||
}
|
||||
return true;
|
||||
},
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'attnotnull', label: gettext('Not NULL?'),
|
||||
cell: 'boolean',type: 'switch', editable: 'is_editable_column',
|
||||
cellHeaderClasses: 'width_percent_10', group: gettext('Definition'),
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'attstattarget', label: gettext('Statistics'), min_version: 90200,
|
||||
cell: 'integer', type: 'int', group: gettext('Definition'),
|
||||
editable: function(m) {
|
||||
|
@ -230,7 +239,8 @@ define('pgadmin.node.foreign_table', [
|
|||
return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid'))
|
||||
|| _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false;
|
||||
}, cellHeaderClasses: 'width_percent_10',
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'collname', label: gettext('Collation'), cell: 'node-ajax-options',
|
||||
control: 'node-ajax-options', type: 'text', url: 'get_collations',
|
||||
min_version: 90300, editable: function(m) {
|
||||
|
@ -239,13 +249,16 @@ define('pgadmin.node.foreign_table', [
|
|||
|| _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false;
|
||||
},
|
||||
cellHeaderClasses: 'width_percent_20', group: gettext('Definition'),
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'attnum', cell: 'string',type: 'text', visible: false,
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'inheritedfrom', label: gettext('Inherited From'), cell: 'string',
|
||||
type: 'text', visible: false, mode: ['properties', 'edit'],
|
||||
cellHeaderClasses: 'width_percent_10',
|
||||
},{
|
||||
},
|
||||
{
|
||||
id: 'coloptions', label: gettext('Options'), cell: 'string',
|
||||
type: 'collection', group: gettext('Options'), mode: ['edit', 'create'],
|
||||
model: ColumnOptionsModel, canAdd: true, canDelete: true, canEdit: false,
|
||||
|
@ -490,6 +503,7 @@ define('pgadmin.node.foreign_table', [
|
|||
collection_type: 'coll-foreign_table',
|
||||
hasSQL: true,
|
||||
hasDepends: true,
|
||||
width: pgBrowser.stdW.md + 'px',
|
||||
hasScriptTypes: ['create', 'select', 'insert', 'update', 'delete'],
|
||||
parent_type: ['schema'],
|
||||
Init: function() {
|
||||
|
@ -521,6 +535,32 @@ define('pgadmin.node.foreign_table', [
|
|||
]);
|
||||
|
||||
},
|
||||
getSchema: function(treeNodeInfo, itemNodeData) {
|
||||
return new ForeignTableSchema(
|
||||
(privileges)=>getNodePrivilegeRoleSchema('', treeNodeInfo, itemNodeData, privileges),
|
||||
()=>getNodeVariableSchema(this, treeNodeInfo, itemNodeData, false, false),
|
||||
(params)=>{
|
||||
return getNodeAjaxOptions('get_columns', pgBrowser.Nodes['foreign_table'], treeNodeInfo, itemNodeData, {urlParams: params, useCache:false});
|
||||
},
|
||||
{
|
||||
role: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData),
|
||||
schema: ()=>getNodeListByName('schema', treeNodeInfo, itemNodeData, {cacheLevel: 'database'}),
|
||||
foreignServers: ()=>getNodeAjaxOptions('get_foreign_servers', this, treeNodeInfo, itemNodeData, {cacheLevel: 'database'}, (res) => {
|
||||
return _.reject(res, function(o) {
|
||||
return o.label == '' || o.label == null;
|
||||
});
|
||||
}),
|
||||
tables: ()=>getNodeAjaxOptions('get_tables', this, treeNodeInfo, itemNodeData, {cacheLevel: 'database'}),
|
||||
nodeInfo: treeNodeInfo,
|
||||
nodeData: itemNodeData,
|
||||
pgBrowser: pgBrowser
|
||||
},
|
||||
{
|
||||
owner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name,
|
||||
basensp: treeNodeInfo.schema ? treeNodeInfo.schema.label : ''
|
||||
}
|
||||
);
|
||||
},
|
||||
model: pgBrowser.Node.Model.extend({
|
||||
idAttribute: 'oid',
|
||||
initialize: function(attrs, args) {
|
||||
|
|
|
@ -0,0 +1,545 @@
|
|||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import gettext from 'sources/gettext';
|
||||
import SecLabelSchema from '../../../../../static/js/sec_label.ui';
|
||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||
import OptionsSchema from '../../../../../static/js/options.ui';
|
||||
import { isEmptyString } from 'sources/validators';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
|
||||
import { getNodeAjaxOptions } from '../../../../../../../static/js/node_ajax';
|
||||
|
||||
|
||||
export default class ForeignTableSchema extends BaseUISchema {
|
||||
constructor(getPrivilegeRoleSchema, getVariableSchema, getColumns, fieldOptions={}, initValues) {
|
||||
super({
|
||||
name: undefined,
|
||||
oid: undefined,
|
||||
owner: undefined,
|
||||
basensp: undefined,
|
||||
is_sys_obj: undefined,
|
||||
description: undefined,
|
||||
ftsrvname: undefined,
|
||||
strftoptions: undefined,
|
||||
inherits: [],
|
||||
columns: [],
|
||||
ftoptions: [],
|
||||
relacl: [],
|
||||
stracl: [],
|
||||
seclabels: [],
|
||||
...initValues
|
||||
});
|
||||
|
||||
this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
|
||||
this.getVariableSchema = getVariableSchema;
|
||||
this.getColumns = getColumns;
|
||||
this.inheritedTableList = [];
|
||||
this.fieldOptions = {
|
||||
role: [],
|
||||
schema: [],
|
||||
foreignServers: [],
|
||||
tables: [],
|
||||
nodeInfo: null,
|
||||
...fieldOptions,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'oid';
|
||||
}
|
||||
|
||||
canEditDeleteRowColumns(colstate) {
|
||||
if (!isEmptyString(colstate.inheritedfrom)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getTableOid(tabId) {
|
||||
// Here we will fetch the table oid from table name
|
||||
// iterate over list to find table oid
|
||||
for(const t of this.inheritedTableList) {
|
||||
if(t.value === tabId) {
|
||||
return t.value;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
get baseFields() {
|
||||
let obj = this;
|
||||
return [
|
||||
{
|
||||
id: 'name', label: gettext('Name'), cell: 'text',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'],
|
||||
noEmpty: true
|
||||
},{
|
||||
id: 'oid', label: gettext('OID'), cell: 'text',
|
||||
type: 'text' , mode: ['properties'],
|
||||
},{
|
||||
id: 'owner', label: gettext('Owner'), cell: 'text',
|
||||
type: 'select', controlProps: { allowClear: false },
|
||||
options: obj.fieldOptions.role
|
||||
},{
|
||||
id: 'basensp', label: gettext('Schema'), cell: 'text',
|
||||
type: 'select', mode:['create', 'edit'],
|
||||
options: obj.fieldOptions.schema
|
||||
},{
|
||||
id: 'is_sys_obj', label: gettext('System foreign table?'),
|
||||
cell:'boolean', type: 'switch', mode: ['properties'],
|
||||
},{
|
||||
id: 'description', label: gettext('Comment'), cell: 'text',
|
||||
type: 'multiline',
|
||||
},{
|
||||
id: 'ftsrvname', label: gettext('Foreign server'), cell: 'text',
|
||||
type: 'select', group: gettext('Definition'),
|
||||
options: obj.fieldOptions.foreignServers,
|
||||
readonly: (state) => { return !obj.isNew(state); },
|
||||
},{
|
||||
id: 'inherits', label: gettext('Inherits'), group: gettext('Definition'),
|
||||
type: 'select', min_version: 90500, controlProps: {multiple: true},
|
||||
options: obj.fieldOptions.tables,
|
||||
optionsLoaded: (res)=>obj.inheritedTableList=res,
|
||||
deferredDepChange: (state, source, topState, actionObj)=>{
|
||||
return new Promise((resolve)=>{
|
||||
// current table list and previous table list
|
||||
let newColInherits = state.inherits || [];
|
||||
let oldColInherits = actionObj.oldState.inherits || [];
|
||||
|
||||
var tabName = undefined;
|
||||
let tabColsResponse;
|
||||
|
||||
// Add columns logic
|
||||
// If new table is added in list
|
||||
if(newColInherits.length > 1 && newColInherits.length > oldColInherits.length) {
|
||||
// Find newly added table from current list
|
||||
tabName = _.difference(newColInherits, oldColInherits);
|
||||
tabColsResponse = obj.getColumns({attrelid: this.getTableOid(tabName[0])});
|
||||
} else if (newColInherits.length == 1) {
|
||||
// First table added
|
||||
tabColsResponse = obj.getColumns({attrelid: this.getTableOid(newColInherits[0])});
|
||||
}
|
||||
|
||||
if(tabColsResponse) {
|
||||
tabColsResponse.then((res)=>{
|
||||
resolve((state)=>{
|
||||
let finalCols = res.map((col)=> col);
|
||||
finalCols = [...state.columns, ...finalCols];
|
||||
return {
|
||||
adding_inherit_cols: false,
|
||||
columns: finalCols,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Remove columns logic
|
||||
let removeOid;
|
||||
if(newColInherits.length > 0 && newColInherits.length < oldColInherits.length) {
|
||||
// Find deleted table from previous list
|
||||
tabName = _.difference(oldColInherits, newColInherits);
|
||||
removeOid = this.getTableOid(tabName[0]);
|
||||
} else if (oldColInherits.length === 1 && newColInherits.length < 1) {
|
||||
// We got last table from list
|
||||
tabName = oldColInherits[0];
|
||||
removeOid = this.getTableOid(tabName);
|
||||
}
|
||||
if(removeOid) {
|
||||
resolve((state)=>{
|
||||
let finalCols = state.columns;
|
||||
_.remove(state.columns, (col)=>col.inheritedid==removeOid);
|
||||
return {
|
||||
adding_inherit_cols: false,
|
||||
columns: finalCols
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'columns', label: gettext('Columns'), cell: 'text',
|
||||
type: 'collection', group: gettext('Columns'), mode: ['edit', 'create'],
|
||||
schema: new getNodeColumnSchema(obj.fieldOptions.nodeInfo, obj.fieldOptions.nodeData, obj.fieldOptions.pgBrowser),
|
||||
canAdd: true, canDelete: true, canEdit: true, columns: ['attname', 'datatype', 'inheritedfrom'],
|
||||
// For each row edit/delete button enable/disable
|
||||
canEditRow: this.canEditDeleteRowColumns,
|
||||
canDeleteRow: this.canEditDeleteRowColumns,
|
||||
},
|
||||
{
|
||||
id: 'constraints', label: gettext('Constraints'), cell: 'text',
|
||||
type: 'collection', group: gettext('Constraints'), mode: ['edit', 'create'],
|
||||
schema: new CheckConstraintSchema(),
|
||||
canAdd: true, canDelete: true, columns: ['conname','consrc', 'connoinherit', 'convalidated'],
|
||||
canEdit: true,
|
||||
canDeleteRow: function(state) {
|
||||
return (state.conislocal == true || _.isUndefined(state.conislocal)) ? true : false;
|
||||
},
|
||||
canEditRow: function(state) {
|
||||
return obj.isNew(state);
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'strftoptions', label: gettext('Options'), cell: 'text',
|
||||
type: 'text', group: gettext('Definition'), mode: ['properties'],
|
||||
},
|
||||
{
|
||||
id: 'fdwoptions', label: gettext('Options'), type: 'collection',
|
||||
schema: new OptionsSchema('fdwoption', 'fdwvalue'),
|
||||
group: gettext('Options'),
|
||||
mode: ['edit', 'create'],
|
||||
canAdd: true, canDelete: true, uniqueCol : ['fdwoption'],
|
||||
},
|
||||
{
|
||||
id: 'relacl', label: gettext('Privileges'), cell: 'text',
|
||||
type: 'text', group: gettext('Security'),
|
||||
mode: ['properties'], min_version: 90200,
|
||||
},
|
||||
{
|
||||
id: 'acl', label: gettext('Privileges'), type: 'collection',
|
||||
schema: this.getPrivilegeRoleSchema(['a','r','w','x']),
|
||||
uniqueCol : ['grantee', 'grantor'],
|
||||
editable: false,
|
||||
group: gettext('Security'), mode: ['edit', 'create'],
|
||||
canAdd: true, canDelete: true,
|
||||
min_version: 90200
|
||||
},
|
||||
{
|
||||
id: 'seclabels', label: gettext('Security labels'), type: 'collection',
|
||||
schema: new SecLabelSchema(),
|
||||
editable: false, group: gettext('Security'),
|
||||
mode: ['edit', 'create'],
|
||||
canAdd: true, canEdit: false, canDelete: true,
|
||||
uniqueCol : ['provider'],
|
||||
min_version: 90100,
|
||||
disabled: obj.inCatalog()
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
validate(state, setError) {
|
||||
let errmsg = null;
|
||||
|
||||
if (isEmptyString(state.service)) {
|
||||
|
||||
/* code validation*/
|
||||
if (isEmptyString(state.ftsrvname)) {
|
||||
errmsg = gettext('Foreign server cannot be empty.');
|
||||
setError('ftsrvname', errmsg);
|
||||
return true;
|
||||
} else {
|
||||
errmsg = null;
|
||||
setError('ftsrvname', errmsg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function getNodeColumnSchema(treeNodeInfo, itemNodeData, pgBrowser) {
|
||||
return new ColumnSchema(
|
||||
{},
|
||||
(privileges)=>getNodePrivilegeRoleSchema(this, treeNodeInfo, itemNodeData, privileges),
|
||||
treeNodeInfo,
|
||||
()=>getNodeAjaxOptions('get_types', pgBrowser.Nodes['table'], treeNodeInfo, itemNodeData, {
|
||||
cacheLevel: 'table',
|
||||
}),
|
||||
()=>getNodeAjaxOptions('get_collations', pgBrowser.Nodes['collation'], treeNodeInfo, itemNodeData),
|
||||
);
|
||||
}
|
||||
|
||||
export class ColumnSchema extends BaseUISchema {
|
||||
constructor(initValues, getPrivilegeRoleSchema, nodeInfo, datatypeOptions, collspcnameOptions) {
|
||||
super({
|
||||
attname: undefined,
|
||||
datatype: undefined,
|
||||
typlen: undefined,
|
||||
precision: undefined,
|
||||
typdefault: undefined,
|
||||
attnotnull: undefined,
|
||||
collname: undefined,
|
||||
attnum: undefined,
|
||||
inheritedfrom: undefined,
|
||||
inheritedid: undefined,
|
||||
attstattarget: undefined,
|
||||
coloptions: [],
|
||||
});
|
||||
|
||||
this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
|
||||
this.nodeInfo = nodeInfo;
|
||||
this.datatypeOptions = datatypeOptions;
|
||||
this.collspcnameOptions = collspcnameOptions;
|
||||
|
||||
this.datatypes = [];
|
||||
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'attnum';
|
||||
}
|
||||
|
||||
editable_check_for_column(state) {
|
||||
return (_.isUndefined(state.inheritedid) || _.isNull(state.inheritedid) || _.isUndefined(state.inheritedfrom) || _.isNull(state.inheritedfrom)) ? true : false;
|
||||
}
|
||||
|
||||
get baseFields() {
|
||||
let obj = this;
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'attname', label: gettext('Name'), cell: 'text',
|
||||
type: 'text', editable: obj.editable_check_for_column, noEmpty: true,
|
||||
minWidth: 115,
|
||||
},
|
||||
{
|
||||
id: 'datatype', label: gettext('Data type'), minWidth: 150,
|
||||
group: gettext('Definition'), noEmpty: true,
|
||||
editable: obj.editable_check_for_column,
|
||||
options: obj.datatypeOptions,
|
||||
optionsLoaded: (options)=>{
|
||||
obj.datatypes = options;
|
||||
obj.type_options = options;
|
||||
},
|
||||
cell: 'select',
|
||||
controlProps: {
|
||||
allowClear: false,
|
||||
},
|
||||
type: 'select'
|
||||
},
|
||||
{
|
||||
id: 'inheritedfrom', label: gettext('Inherited From'), cell: 'label',
|
||||
type: 'label', readonly: true, editable: false, mode: ['properties', 'edit'],
|
||||
},
|
||||
{
|
||||
id: 'attnum', label: gettext('Position'), cell: 'text',
|
||||
type: 'text', disabled: obj.inCatalog(), mode: ['properties'],
|
||||
},
|
||||
{
|
||||
id: 'typlen', label: gettext('Length'), cell: 'int',
|
||||
deps: ['datatype'], type: 'int', group: gettext('Definition'), width: 120, minWidth: 120,
|
||||
disabled: (state) => {
|
||||
var val = state.typlen;
|
||||
// We will store type from selected from combobox
|
||||
if(!(_.isUndefined(state.inheritedid)
|
||||
|| _.isNull(state.inheritedid)
|
||||
|| _.isUndefined(state.inheritedfrom)
|
||||
|| _.isNull(state.inheritedfrom))) {
|
||||
|
||||
if (!_.isUndefined(val)) {
|
||||
state.typlen = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var of_type = state.datatype,
|
||||
has_length = false;
|
||||
if(obj.type_options) {
|
||||
state.is_tlength = false;
|
||||
|
||||
// iterating over all the types
|
||||
_.each(obj.type_options, function(o) {
|
||||
// if type from selected from combobox matches in options
|
||||
if ( of_type == o.value ) {
|
||||
// if length is allowed for selected type
|
||||
if(o.length)
|
||||
{
|
||||
// set the values in model
|
||||
has_length = true;
|
||||
state.is_tlength = true;
|
||||
state.min_val = o.min_val;
|
||||
state.max_val = o.max_val;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!has_length && !_.isUndefined(val)) {
|
||||
state.typlen = undefined;
|
||||
}
|
||||
|
||||
return !(state.is_tlength);
|
||||
}
|
||||
if (!has_length && !_.isUndefined(val)) {
|
||||
state.typlen = undefined;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'precision', label: gettext('Precision'), cell: 'int', minWidth: 60,
|
||||
deps: ['datatype'], type: 'int', group: gettext('Definition'),
|
||||
disabled: (state) => {
|
||||
var val = state.precision;
|
||||
if(!(_.isUndefined(state.inheritedid)
|
||||
|| _.isNull(state.inheritedid)
|
||||
|| _.isUndefined(state.inheritedfrom)
|
||||
|| _.isNull(state.inheritedfrom))) {
|
||||
|
||||
if (!_.isUndefined(val)) {
|
||||
state.precision = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var of_type = state.datatype,
|
||||
has_precision = false;
|
||||
|
||||
if(obj.type_options) {
|
||||
state.is_precision = false;
|
||||
// iterating over all the types
|
||||
_.each(obj.type_options, function(o) {
|
||||
// if type from selected from combobox matches in options
|
||||
if ( of_type == o.value ) {
|
||||
// if precession is allowed for selected type
|
||||
if(o.precision)
|
||||
{
|
||||
has_precision = true;
|
||||
// set the values in model
|
||||
state.is_precision = true;
|
||||
state.min_val = o.min_val;
|
||||
state.max_val = o.max_val;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!has_precision && !_.isUndefined(val)) {
|
||||
state.precision = undefined;
|
||||
}
|
||||
return !(state.is_precision);
|
||||
}
|
||||
if (!has_precision && !_.isUndefined(val)) {
|
||||
state.precision = undefined;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'typdefault', label: gettext('Default'), cell: 'text',
|
||||
type: 'text', group: gettext('Definition'),
|
||||
placeholder: gettext('Enter an expression or a value.'),
|
||||
editable: (state) => {
|
||||
if(!(_.isUndefined(state.inheritedid)
|
||||
|| _.isNull(state.inheritedid)
|
||||
|| _.isUndefined(state.inheritedfrom)
|
||||
|| _.isNull(state.inheritedfrom))) { return false; }
|
||||
if (obj.nodeInfo.server.version < 90300){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'attnotnull', label: gettext('Not NULL?'), cell: 'switch',
|
||||
type: 'switch', minWidth: 80,
|
||||
group: gettext('Definition'), editable: obj.editable_check_for_column,
|
||||
},
|
||||
{
|
||||
id: 'attstattarget', label: gettext('Statistics'), cell: 'text',
|
||||
type: 'text', disabled: (state) => {
|
||||
if (obj.isNew()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj.nodeInfo.server.version < 90200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (_.isUndefined(state.inheritedid) || _.isNull(state.inheritedid) ||
|
||||
_.isUndefined(state.inheritedfrom) || _.isNull(state.inheritedfrom)) ? true : false;
|
||||
}, mode: ['properties', 'edit'],
|
||||
group: gettext('Definition'),
|
||||
},
|
||||
{
|
||||
id: 'collname', label: gettext('Collation'), cell: 'select',
|
||||
type: 'select', group: gettext('Definition'),
|
||||
deps: ['datatype'], options: obj.collspcnameOptions,
|
||||
disabled: (state)=>{
|
||||
if (!(_.isUndefined(obj.isNew)) && !obj.isNew(state)) { return false; }
|
||||
|
||||
return (_.isUndefined(state.inheritedid) || _.isNull(state.inheritedid) ||
|
||||
_.isUndefined(state.inheritedfrom) || _.isNull(state.inheritedfrom)) ? true : false;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'coloptions', label: gettext('Options'), type: 'collection',
|
||||
group: gettext('Options'),
|
||||
schema: new OptionsSchema('option', 'value'),
|
||||
uniqueCol : ['option'], mode: ['edit', 'create'],
|
||||
canAdd: true, canEdit: false, canDelete: true,
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class CheckConstraintSchema extends BaseUISchema {
|
||||
constructor() {
|
||||
super({
|
||||
name: undefined,
|
||||
oid: undefined,
|
||||
description: undefined,
|
||||
consrc: undefined,
|
||||
connoinherit: undefined,
|
||||
convalidated: true,
|
||||
});
|
||||
|
||||
this.convalidated_default = true;
|
||||
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'conoid';
|
||||
}
|
||||
|
||||
isReadonly(state) {
|
||||
return !this.isNew(state);
|
||||
}
|
||||
|
||||
get baseFields() {
|
||||
let obj = this;
|
||||
|
||||
return [{
|
||||
id: 'conname', label: gettext('Name'), type:'text', cell:'text',
|
||||
mode: ['properties', 'create', 'edit'],
|
||||
editable: (state) => {
|
||||
return _.isUndefined(obj.isNew) ? true : obj.isNew(state);
|
||||
}, noEmpty: true, readonly: obj.isReadonly
|
||||
},{
|
||||
id: 'consrc', label: gettext('Check'), type: 'multiline', cell: 'text',
|
||||
mode: ['properties', 'create', 'edit'],
|
||||
editable: (state) => {
|
||||
return _.isUndefined(obj.isNew) ? true : obj.isNew(state);
|
||||
}, noEmpty: true, readonly: obj.isReadonly
|
||||
},{
|
||||
id: 'connoinherit', label: gettext('No inherit?'), type: 'switch', cell: 'switch',
|
||||
mode: ['properties', 'create', 'edit'],
|
||||
deps: [['is_partitioned']],
|
||||
editable: (state) => {
|
||||
return _.isUndefined(obj.isNew) ? true : obj.isNew(state);
|
||||
}, readonly: obj.isReadonly
|
||||
},{
|
||||
id: 'convalidated', label: gettext('Validate?'), type: 'switch', cell: 'switch',
|
||||
readonly: obj.isReadonly,
|
||||
editable: (state) => {
|
||||
if (_.isUndefined(obj.isNew)) { return true; }
|
||||
if (!obj.isNew(state)) {
|
||||
if(state.convalidated && obj.convalidated_default) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
mode: ['properties', 'create', 'edit'],
|
||||
}];
|
||||
}
|
||||
}
|
|
@ -139,139 +139,9 @@ define('pgadmin.node.trigger_function', [
|
|||
id: 'funcowner', label: gettext('Owner'), cell: 'string',
|
||||
control: Backform.NodeListByNameControl, node: 'role', type:
|
||||
'text', disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'pronamespace', label: gettext('Schema'), cell: 'string',
|
||||
control: 'node-list-by-id', type: 'text', cache_level: 'database',
|
||||
node: 'schema', disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
mode: ['create', 'edit'],
|
||||
},{
|
||||
id: 'sysfunc', label: gettext('System trigger function?'),
|
||||
cell:'boolean', type: 'switch',
|
||||
mode: ['properties'], visible: 'isVisible',
|
||||
},{
|
||||
id: 'sysproc', label: gettext('System procedure?'),
|
||||
cell:'boolean', type: 'switch',
|
||||
mode: ['properties'], visible: 'isVisible',
|
||||
},{
|
||||
id: 'description', label: gettext('Comment'), cell: 'string',
|
||||
type: 'multiline', disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'pronargs', label: gettext('Argument count'), cell: 'string',
|
||||
type: 'text', group: gettext('Definition'), mode: ['properties'],
|
||||
},{
|
||||
id: 'proargs', label: gettext('Arguments'), cell: 'string',
|
||||
type: 'text', group: gettext('Definition'), mode: ['properties', 'edit'],
|
||||
disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'proargtypenames', label: gettext('Signature arguments'), cell:
|
||||
'string', type: 'text', group: gettext('Definition'), mode: ['properties'],
|
||||
disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'prorettypename', label: gettext('Return type'), cell: 'string',
|
||||
control: 'select2', type: 'text', group: gettext('Definition'),
|
||||
disabled: 'isDisabled', readonly: 'isReadonly', first_empty: true,
|
||||
select2: { width: '100%', allowClear: false },
|
||||
mode: ['create'], visible: 'isVisible', options: [
|
||||
{label: gettext('trigger'), value: 'trigger'},
|
||||
{label: gettext('event_trigger'), value: 'event_trigger'},
|
||||
],
|
||||
},{
|
||||
id: 'prorettypename', label: gettext('Return type'), cell: 'string',
|
||||
type: 'text', group: gettext('Definition'),
|
||||
mode: ['properties', 'edit'], disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
visible: 'isVisible',
|
||||
}, {
|
||||
id: 'lanname', label: gettext('Language'), cell: 'string',
|
||||
control: 'node-ajax-options', type: 'text', group: gettext('Definition'),
|
||||
url: 'get_languages', disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
transform: function(d) {
|
||||
return _.reject(d, function(o) {
|
||||
return o.label == 'sql' || o.label == 'edbspl';
|
||||
});
|
||||
}, select2: { allowClear: false },
|
||||
},{
|
||||
id: 'prosrc', label: gettext('Code'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'],
|
||||
group: gettext('Code'), deps: ['lanname'],
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
visible: function(m) {
|
||||
if (m.get('lanname') == 'c') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'probin', label: gettext('Object file'), cell: 'string',
|
||||
type: 'text', group: gettext('Definition'), deps: ['lanname'], visible:
|
||||
function(m) {
|
||||
if (m.get('lanname') == 'c') { return true; }
|
||||
return false;
|
||||
}, disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'prosrc_c', label: gettext('Link symbol'), cell: 'string',
|
||||
type: 'text', group: gettext('Definition'), deps: ['lanname'], visible:
|
||||
function(m) {
|
||||
if (m.get('lanname') == 'c') { return true; }
|
||||
return false;
|
||||
}, disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'provolatile', label: gettext('Volatility'), cell: 'string',
|
||||
control: 'node-ajax-options', type: 'text', group: gettext('Options'),
|
||||
options:[
|
||||
{'label': 'VOLATILE', 'value': 'v'},
|
||||
{'label': 'STABLE', 'value': 's'},
|
||||
{'label': 'IMMUTABLE', 'value': 'i'},
|
||||
], disabled: 'isDisabled', readonly: 'isReadonly', select2: { allowClear: false },
|
||||
},{
|
||||
id: 'proretset', label: gettext('Returns a set?'), type: 'switch',
|
||||
group: gettext('Options'), disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
visible: 'isVisible',
|
||||
},{
|
||||
id: 'proisstrict', label: gettext('Strict?'), type: 'switch',
|
||||
disabled: 'isDisabled', readonly: 'isReadonly', group: gettext('Options'),
|
||||
},{
|
||||
id: 'prosecdef', label: gettext('Security of definer?'),
|
||||
group: gettext('Options'), cell:'boolean', type: 'switch',
|
||||
disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'proiswindow', label: gettext('Window?'),
|
||||
group: gettext('Options'), cell:'boolean', type: 'switch',
|
||||
disabled: 'isDisabled', readonly: 'isReadonly', visible: 'isVisible',
|
||||
},{
|
||||
id: 'procost', label: gettext('Estimated cost'), type: 'text',
|
||||
group: gettext('Options'), disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'prorows', label: gettext('Estimated rows'), type: 'text',
|
||||
group: gettext('Options'),
|
||||
disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
deps: ['proretset'], visible: 'isVisible',
|
||||
},{
|
||||
id: 'proleakproof', label: gettext('Leak proof?'),
|
||||
group: gettext('Options'), cell:'boolean', type: 'switch', min_version: 90200,
|
||||
disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
}, pgBrowser.SecurityGroupSchema, {
|
||||
id: 'proacl', label: gettext('Privileges'), mode: ['properties'],
|
||||
group: gettext('Security'), type: 'text',
|
||||
},{
|
||||
id: 'variables', label: '', type: 'collection',
|
||||
group: gettext('Parameters'), control: 'variable-collection',
|
||||
model: pgBrowser.Node.VariableModel,
|
||||
mode: ['edit', 'create'], canAdd: 'canVarAdd', canEdit: false,
|
||||
canDelete: true, disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
},{
|
||||
id: 'acl', label: gettext('Privileges'), editable: false,
|
||||
type: 'collection', group: 'security', mode: ['edit', 'create'],
|
||||
model: pgBrowser.Node.PrivilegeRoleModel.extend({
|
||||
privileges: ['X'],
|
||||
}), uniqueCol : ['grantee', 'grantor'], disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
canAdd: true, canDelete: true, control: 'unique-col-collection',
|
||||
},{
|
||||
id: 'seclabels', label: gettext('Security labels'), canEdit: true,
|
||||
model: pgBrowser.SecLabelModel, type: 'collection',
|
||||
min_version: 90100, group: 'security', mode: ['edit', 'create'],
|
||||
canDelete: true, control: 'unique-col-collection', canAdd: true,
|
||||
uniqueCol : ['provider'], disabled: 'isDisabled', readonly: 'isReadonly',
|
||||
}],
|
||||
validate: function(keys)
|
||||
{
|
||||
|
|
|
@ -118,10 +118,6 @@ export default class TriggerFunctionSchema extends BaseUISchema {
|
|||
id: 'sysfunc', label: gettext('System trigger function?'),
|
||||
cell:'boolean', type: 'switch',
|
||||
mode: ['properties'], visible: obj.isVisible
|
||||
},{
|
||||
id: 'sysproc', label: gettext('System procedure?'),
|
||||
cell:'boolean', type: 'switch',
|
||||
mode: ['properties'], visible: obj.isVisible
|
||||
},{
|
||||
id: 'description', label: gettext('Comment'), cell: 'string',
|
||||
type: 'multiline', disabled: obj.isDisabled, readonly: obj.isReadonly,
|
||||
|
|
|
@ -51,7 +51,7 @@ export class EventSchema extends BaseUISchema {
|
|||
id: 'evnt_insert', label: gettext('INSERT'),
|
||||
type: 'switch', mode: ['create','edit', 'properties'],
|
||||
group: gettext('Events'),
|
||||
disabled: (state) => {
|
||||
readonly: (state) => {
|
||||
var evn_insert = state.evnt_insert;
|
||||
if (!_.isUndefined(evn_insert) && obj.nodeInfo && obj.nodeInfo.server.server_type == 'ppas' && obj.isNew(state))
|
||||
return false;
|
||||
|
@ -61,7 +61,7 @@ export class EventSchema extends BaseUISchema {
|
|||
id: 'evnt_update', label: gettext('UPDATE'),
|
||||
type: 'switch', mode: ['create','edit', 'properties'],
|
||||
group: gettext('Events'),
|
||||
disabled: (state) => {
|
||||
readonly: (state) => {
|
||||
var evn_update = state.evnt_update;
|
||||
if (!_.isUndefined(evn_update) && obj.nodeInfo && obj.nodeInfo.server.server_type == 'ppas' && obj.isNew(state))
|
||||
return false;
|
||||
|
@ -71,7 +71,7 @@ export class EventSchema extends BaseUISchema {
|
|||
id: 'evnt_delete', label: gettext('DELETE'),
|
||||
type: 'switch', mode: ['create','edit', 'properties'],
|
||||
group: gettext('Events'),
|
||||
disabled: (state) => {
|
||||
readonly: (state) => {
|
||||
var evn_delete = state.evnt_delete;
|
||||
if (!_.isUndefined(evn_delete) && obj.nodeInfo && obj.nodeInfo.server.server_type == 'ppas' && obj.isNew(state))
|
||||
return false;
|
||||
|
@ -80,7 +80,7 @@ export class EventSchema extends BaseUISchema {
|
|||
},{
|
||||
id: 'evnt_truncate', label: gettext('TRUNCATE'),
|
||||
type: 'switch', group: gettext('Events'), deps: ['is_row_trigger', 'is_constraint_trigger'],
|
||||
disabled: (state) => {
|
||||
readonly: (state) => {
|
||||
var is_constraint_trigger = state.is_constraint_trigger,
|
||||
is_row_trigger = state.is_row_trigger,
|
||||
server_type = obj.nodeInfo ? obj.nodeInfo.server.server_type: null;
|
||||
|
@ -219,7 +219,7 @@ export default class TriggerSchema extends BaseUISchema {
|
|||
type: 'switch', group: gettext('Definition'),
|
||||
mode: ['create','edit', 'properties'],
|
||||
deps: ['is_constraint_trigger'],
|
||||
disabled: (state) => {
|
||||
readonly: (state) => {
|
||||
// Disabled if table is a partitioned table.
|
||||
if (!obj.isNew())
|
||||
return true;
|
||||
|
@ -475,3 +475,4 @@ export default class TriggerSchema extends BaseUISchema {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,462 @@
|
|||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import jasmineEnzyme from 'jasmine-enzyme';
|
||||
import React from 'react';
|
||||
import '../helper/enzyme.helper';
|
||||
import { createMount } from '@material-ui/core/test-utils';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import {messages} from '../fake_messages';
|
||||
import SchemaView from '../../../pgadmin/static/js/SchemaView';
|
||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||
import ForeignTableSchema, { ColumnSchema, CheckConstraintSchema } from '../../../pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/static/js/foreign_table.ui';
|
||||
|
||||
class MockSchema extends BaseUISchema {
|
||||
get baseFields() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
describe('ForeignTableSchema', ()=>{
|
||||
let mount;
|
||||
let schemaObj = new ForeignTableSchema(
|
||||
()=>new MockSchema(),
|
||||
()=>new MockSchema(),
|
||||
()=>new MockSchema(),
|
||||
{
|
||||
role: [],
|
||||
schema: [],
|
||||
foreignServers: [],
|
||||
tables: [],
|
||||
nodeData: {},
|
||||
pgBrowser: {},
|
||||
nodeInfo: {
|
||||
schema: {},
|
||||
server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 90400},
|
||||
table: {}
|
||||
}
|
||||
}
|
||||
);
|
||||
let getInitData = ()=>Promise.resolve({});
|
||||
|
||||
/* Use createMount so that material ui components gets the required context */
|
||||
/* https://material-ui.com/guides/testing/#api */
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
/* messages used by validators */
|
||||
pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
|
||||
pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
|
||||
});
|
||||
|
||||
it('create', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('edit', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'edit',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('properties', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='tab'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'properties',
|
||||
}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('validate', ()=>{
|
||||
let state = {};
|
||||
let setError = jasmine.createSpy('setError');
|
||||
|
||||
state.ftsrvname = null;
|
||||
schemaObj.validate(state, setError);
|
||||
expect(setError).toHaveBeenCalledWith('ftsrvname', 'Foreign server cannot be empty.');
|
||||
|
||||
state.ftsrvname = 'public';
|
||||
schemaObj.validate(state, setError);
|
||||
expect(setError).toHaveBeenCalledWith('ftsrvname', null);
|
||||
});
|
||||
|
||||
it('column canEditRow', ()=>{
|
||||
let state = {};
|
||||
let canEditRow = _.find(schemaObj.fields, (f)=>f.id=='columns').canEditRow;
|
||||
let status = canEditRow(state);
|
||||
expect(status).toBe(true);
|
||||
|
||||
let colstate = { inheritedfrom: ['public'] };
|
||||
status = canEditRow(colstate);
|
||||
expect(status).toBe(false);
|
||||
});
|
||||
|
||||
it('constraints canDeleteRow', ()=>{
|
||||
let state = {};
|
||||
let canEditRow = _.find(schemaObj.fields, (f)=>f.id=='constraints').canDeleteRow;
|
||||
let status = canEditRow(state);
|
||||
expect(status).toBe(true);
|
||||
|
||||
let colstate = { conislocal: true };
|
||||
status = canEditRow(colstate);
|
||||
expect(status).toBe(true);
|
||||
});
|
||||
|
||||
it('constraints canEditRow', ()=>{
|
||||
let state = {};
|
||||
let canEditRow = _.find(schemaObj.fields, (f)=>f.id=='constraints').canEditRow;
|
||||
let status = canEditRow(state);
|
||||
expect(status).toBe(true);
|
||||
});
|
||||
|
||||
/*it('inherits deferredDepChange', ()=>{
|
||||
let state = {columns: []};
|
||||
let deferredDepChange = _.find(schemaObj.fields, (f)=>f.id=='inherits').deferredDepChange;
|
||||
let status = deferredDepChange(state, {}, {}, {});
|
||||
expect(status).toEqual(Promise.reject());
|
||||
});*/
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('ForeignTableColumnSchema', ()=>{
|
||||
let mount;
|
||||
let schemaObj = new ColumnSchema(
|
||||
{},
|
||||
()=>new MockSchema(),
|
||||
{
|
||||
schema: {},
|
||||
server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 90400},
|
||||
table: {}
|
||||
},
|
||||
[{is_collatable: false, label: '"char"', length: true, max_val: 0, min_val: 0, precision: true, typval: ' '}],
|
||||
()=>[],
|
||||
);
|
||||
let getInitData = ()=>Promise.resolve({});
|
||||
|
||||
/* Use createMount so that material ui components gets the required context */
|
||||
/* https://material-ui.com/guides/testing/#api */
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
/* messages used by validators */
|
||||
pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
|
||||
pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
|
||||
});
|
||||
|
||||
it('create', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('properties', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='tab'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'properties',
|
||||
}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('edit', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'edit',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('column editable', ()=>{
|
||||
let state = {};
|
||||
let editable = _.find(schemaObj.fields, (f)=>f.id=='attname').editable;
|
||||
let status = editable(state);
|
||||
expect(status).toBe(true);
|
||||
});
|
||||
|
||||
it('typdefault editable', ()=>{
|
||||
let state = {};
|
||||
let editable = _.find(schemaObj.fields, (f)=>f.id=='typdefault').editable;
|
||||
let status = editable(state);
|
||||
expect(status).toBe(true);
|
||||
});
|
||||
|
||||
it('typdefault_edit', ()=>{
|
||||
let defaultSchemaObj = new ForeignTableSchema(
|
||||
()=>new MockSchema(),
|
||||
()=>new MockSchema(),
|
||||
()=>new MockSchema(),
|
||||
{
|
||||
role: [],
|
||||
schema: [],
|
||||
foreignServers: [],
|
||||
tables: [],
|
||||
nodeData: {},
|
||||
pgBrowser: {},
|
||||
nodeInfo: {
|
||||
schema: {},
|
||||
server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 90000},
|
||||
table: {}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let initData = ()=>Promise.resolve({typlen: 1, inheritedid: 1, inheritedfrom: 'public'});
|
||||
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={defaultSchemaObj}
|
||||
getInitData={initData}
|
||||
viewHelperProps={{
|
||||
mode: 'edit',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
|
||||
|
||||
it('attstattarget', ()=>{
|
||||
let defaultSchemaObj = new ForeignTableSchema(
|
||||
()=>new MockSchema(),
|
||||
()=>new MockSchema(),
|
||||
()=>new MockSchema(),
|
||||
{
|
||||
role: [],
|
||||
schema: [],
|
||||
foreignServers: [],
|
||||
tables: [],
|
||||
nodeData: {},
|
||||
pgBrowser: {},
|
||||
nodeInfo: {
|
||||
schema: {},
|
||||
server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 90000},
|
||||
table: {}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let initData = ()=>Promise.resolve({
|
||||
precision: null,
|
||||
typlen: 1,
|
||||
inheritedid: 1,
|
||||
inheritedfrom: 'public',
|
||||
|
||||
});
|
||||
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={defaultSchemaObj}
|
||||
getInitData={initData}
|
||||
viewHelperProps={{
|
||||
mode: 'edit',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('ForeignTableCheckConstraint', ()=>{
|
||||
let mount;
|
||||
let schemaObj = new CheckConstraintSchema();
|
||||
let getInitData = ()=>Promise.resolve({});
|
||||
|
||||
/* Use createMount so that material ui components gets the required context */
|
||||
/* https://material-ui.com/guides/testing/#api */
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
/* messages used by validators */
|
||||
pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
|
||||
pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
|
||||
});
|
||||
|
||||
it('create', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('properties', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='tab'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'properties',
|
||||
}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('edit', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={schemaObj}
|
||||
getInitData={getInitData}
|
||||
viewHelperProps={{
|
||||
mode: 'edit',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onEdit={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('conname editable', ()=>{
|
||||
let state = {};
|
||||
let editable = _.find(schemaObj.fields, (f)=>f.id=='conname').editable;
|
||||
let status = editable(state);
|
||||
expect(status).toBe(true);
|
||||
});
|
||||
|
||||
it('consrc editable', ()=>{
|
||||
let state = {};
|
||||
let editable = _.find(schemaObj.fields, (f)=>f.id=='consrc').editable;
|
||||
let status = editable(state);
|
||||
expect(status).toBe(true);
|
||||
});
|
||||
|
||||
it('connoinherit editable', ()=>{
|
||||
let state = {};
|
||||
let editable = _.find(schemaObj.fields, (f)=>f.id=='connoinherit').editable;
|
||||
let status = editable(state);
|
||||
expect(status).toBe(true);
|
||||
});
|
||||
|
||||
it('convalidated editable', ()=>{
|
||||
let state = {};
|
||||
let editable = _.find(schemaObj.fields, (f)=>f.id=='convalidated').editable;
|
||||
let status = editable(state);
|
||||
expect(status).toBe(true);
|
||||
|
||||
spyOn(schemaObj, 'isNew').and.returnValue(false);
|
||||
editable = _.find(schemaObj.fields, (f)=>f.id=='convalidated').editable;
|
||||
status = editable(state);
|
||||
expect(status).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -17,7 +17,7 @@ import SchemaView from '../../../pgadmin/static/js/SchemaView';
|
|||
import MembershipSchema, {getMembershipSchema} from '../../../pgadmin/browser/server_groups/servers/static/js/membership.ui';
|
||||
import * as nodeAjax from '../../../pgadmin/browser/static/js/node_ajax';
|
||||
|
||||
describe('PrivilegeSchema', ()=>{
|
||||
describe('MembershipSchema', ()=>{
|
||||
let mount;
|
||||
let schemaObj = new MembershipSchema(
|
||||
()=>[]);
|
||||
|
|
|
@ -351,28 +351,4 @@ describe('TriggerEventsSchema', ()=>{
|
|||
schemaObj.validate(state, setError);
|
||||
expect(setError).toHaveBeenCalledWith('evnt_insert', null);
|
||||
});
|
||||
|
||||
//spyOn(schemaObj, 'isNew’).and.returnValue(true);
|
||||
|
||||
/*it('evnt_insert disabled', ()=>{
|
||||
let disabled = _.find(schemaObj.fields, (f)=>f.id=='evnt_insert').disabled;
|
||||
disabled({evnt_insert : true});
|
||||
});
|
||||
|
||||
it('evnt_update disabled', ()=>{
|
||||
let disabled = _.find(schemaObj.fields, (f)=>f.id=='evnt_update').disabled;
|
||||
disabled({evnt_update : true});
|
||||
});
|
||||
|
||||
it('evnt_delete disabled', ()=>{
|
||||
let disabled = _.find(schemaObj.fields, (f)=>f.id=='evnt_delete').disabled;
|
||||
disabled({evnt_delete : true});
|
||||
});
|
||||
|
||||
it('evnt_truncate disabled', ()=>{
|
||||
getInitData = ()=>Promise.resolve({is_constraint_trigger: true});
|
||||
let disabled = _.find(schemaObj.fields, (f)=>f.id=='evnt_truncate').disabled;
|
||||
disabled({evnt_truncate : true});
|
||||
});*/
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue