1) Port Compound Trigger node to react. Fixes #6674 2) Remove 'inSchema' method and create a generic method 'inCatalog'.

This commit is contained in:
Akshay Joshi 2021-08-17 16:47:05 +05:30
parent 9274df0f11
commit b7105093e2
10 changed files with 414 additions and 315 deletions

View File

@ -49,7 +49,7 @@ export default class SynonymSchema extends BaseUISchema {
readonly: function(state) { return !obj.isNew(state); },
}, {
id: 'targettype', label: gettext('Target type'),
readonly: this.inSchema, group: gettext('Definition'),
readonly: obj.inCatalog(), group: gettext('Definition'),
controlProps: { allowClear: false },
type: 'select',
options: [
@ -69,7 +69,7 @@ export default class SynonymSchema extends BaseUISchema {
options: this.fieldOptions.synobjschema,
readonly: function(state) {
// If tagetType is synonym then disable it
if(!obj.inSchema()) {
if(!obj.inCatalog()) {
if(state.targettype == 's') {
return true;
} else {
@ -79,7 +79,7 @@ export default class SynonymSchema extends BaseUISchema {
return true;
},
depChange: function(state) {
if(!obj.inSchema() && state.targettype == 's') {
if(!obj.inCatalog() && state.targettype == 's') {
return { synobjschema: 'public'};
}
}
@ -96,7 +96,7 @@ export default class SynonymSchema extends BaseUISchema {
};
},
readonly: function() {
if(!obj.inSchema()) {
if(!obj.inCatalog()) {
return false;
}
return true;
@ -135,12 +135,4 @@ export default class SynonymSchema extends BaseUISchema {
setError('synobjname', errmsg);
}
}
inSchema() {
if(this.nodeInfo && 'catalog' in this.nodeInfo)
{
return true;
}
return false;
}
}

View File

@ -7,6 +7,9 @@
//
//////////////////////////////////////////////////////////////
import { getNodeListByName } from '../../../../../../../../static/js/node_ajax';
import CompoundTriggerSchema from './compound_trigger.ui';
define('pgadmin.node.compound_trigger', [
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
'sources/pgadmin', 'pgadmin.browser',
@ -178,235 +181,25 @@ define('pgadmin.node.compound_trigger', [
},
canDrop: SchemaChildTreeNode.isTreeItemOfChildOfSchema,
canDropCascade: SchemaChildTreeNode.isTreeItemOfChildOfSchema,
getSchema: function(treeNodeInfo, itemNodeData) {
return new CompoundTriggerSchema(
{
columns: ()=>getNodeListByName('column', treeNodeInfo, itemNodeData, { cacheLevel: 'column'}),
},
treeNodeInfo,
);
},
model: pgAdmin.Browser.Node.Model.extend({
idAttribute: 'oid',
defaults: {
name: undefined,
},
schema: [{
id: 'name', label: gettext('Name'), cell: 'string',
type: 'text', disabled: 'inSchema',
},{
id: 'oid', label: gettext('OID'), cell: 'string',
type: 'int', mode: ['properties'],
},{
id: 'is_enable_trigger', label: gettext('Trigger enabled?'),
mode: ['edit', 'properties'],
disabled: function() {
if(this.node_info && ('catalog' in this.node_info || 'view' in this.node_info)) {
return true;
}
return false;
},
options: [
{label: gettext('Enable'), value: 'O'},
{label: gettext('Enable Replica'), value: 'R'},
{label: gettext('Enable Always'), value: 'A'},
{label: gettext('Disable'), value: 'D'},
],
control: 'select2', select2: { allowClear: false, width: '100%' },
},{
type: 'nested', control: 'fieldset', mode: ['create','edit', 'properties'],
label: gettext('FOR Events'), group: gettext('Events'), contentClass: 'row',
schema:[{
id: 'evnt_insert', label: gettext('INSERT'),
type: 'switch', mode: ['create','edit', 'properties'],
group: gettext('FOR Events'),
extraToggleClasses: 'pg-el-sm-6',
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
disabled: function(m) {
var evn_insert = m.get('evnt_insert');
if (!_.isUndefined(evn_insert) && m.node_info['server']['server_type'] == 'ppas')
return false;
return m.inSchema.apply(this, [m]);
},
readonly: 'inEditMode',
},{
id: 'evnt_update', label: gettext('UPDATE'),
type: 'switch', mode: ['create','edit', 'properties'],
group: gettext('FOR Events'),
extraToggleClasses: 'pg-el-sm-6',
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
disabled: function(m) {
var evn_update = m.get('evnt_update');
if (!_.isUndefined(evn_update) && m.node_info['server']['server_type'] == 'ppas')
return false;
return m.inSchema.apply(this, [m]);
},
readonly: 'inEditMode',
},{
id: 'evnt_delete', label: gettext('DELETE'),
type: 'switch', mode: ['create','edit', 'properties'],
group: gettext('FOR Events'),
extraToggleClasses: 'pg-el-sm-6',
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
disabled: function(m) {
var evn_delete = m.get('evnt_delete');
if (!_.isUndefined(evn_delete) && m.node_info['server']['server_type'] == 'ppas')
return false;
return m.inSchema.apply(this, [m]);
},
readonly: 'inEditMode',
},{
id: 'evnt_truncate', label: gettext('TRUNCATE'),
type: 'switch', mode: ['create','edit', 'properties'],
group: gettext('FOR Events'),
extraToggleClasses: 'pg-el-sm-6',
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
disabled: function(m) {
var evn_truncate = m.get('evnt_truncate');
// Views cannot have TRUNCATE triggers.
if ('view' in m.node_info)
return true;
if (!_.isUndefined(evn_truncate) && m.node_info['server']['server_type'] == 'ppas')
return false;
return m.inSchema.apply(this, [m]);
},
}],
readonly: 'inEditMode',
},{
id: 'whenclause', label: gettext('When'),
type: 'text', disabled: 'inSchema', readonly: 'inEditMode',
mode: ['create', 'edit', 'properties'],
control: 'sql-field', visible: true, group: gettext('Events'),
},{
id: 'columns', label: gettext('Columns'), url: 'nodes',
control: 'node-list-by-name', cache_node: 'column', type: 'array',
select2: {'multiple': true},
deps: ['evnt_update'], node: 'column', group: gettext('Events'),
disabled: function(m) {
if(this.node_info && 'catalog' in this.node_info) {
return true;
}
// Enable column only if update event is set true
var isUpdate = m.get('evnt_update');
if(!_.isUndefined(isUpdate) && isUpdate) {
return false;
}
return true;
},
readonly: 'inEditMode',
},{
id: 'prosrc', label: gettext('Code'), group: gettext('Code'),
type: 'text', mode: ['create', 'edit'],
tabPanelCodeClass: 'sql-code-control',
control: Backform.SqlCodeControl,
disabled: function(m) {
if(m.isNew()) {
var code = m.getCodeTemplate();
setTimeout(function() {
m.set('prosrc', code);
}, 10);
}
return false;
},
},{
id: 'is_sys_trigger', label: gettext('System trigger?'), cell: 'string',
type: 'switch', disabled: 'inSchema', mode: ['properties'],
readonly: 'inEditMode',
type: 'text',
}, {
id: 'description', label: gettext('Comment'), cell: 'string',
type: 'multiline', mode: ['properties', 'create', 'edit'],
disabled: 'inSchema',
}],
validate: function(keys) {
var msg;
this.errorModel.clear();
// If nothing to validate
if (keys && keys.length == 0) {
return null;
}
if(_.isUndefined(this.get('name'))
|| String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('Name cannot be empty.');
this.errorModel.set('name', msg);
return msg;
}
if(!this.get('evnt_truncate') && !this.get('evnt_delete') &&
!this.get('evnt_update') && !this.get('evnt_insert')) {
msg = gettext('Specify at least one event.');
this.errorModel.set('evnt_truncate', ' ');
this.errorModel.set('evnt_delete', ' ');
this.errorModel.set('evnt_update', ' ');
this.errorModel.set('evnt_insert', msg);
return msg;
}
if(_.isUndefined(this.get('prosrc'))
|| String(this.get('prosrc')).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('Code cannot be empty.');
this.errorModel.set('prosrc', msg);
return msg;
}
return null;
},
// This function returns the code template for compound trigger
getCodeTemplate: function () {
return gettext('-- Enter any global declarations below:\n\n' +
'-- BEFORE STATEMENT block. Delete if not required.\n' +
'BEFORE STATEMENT IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;\n\n' +
'-- AFTER STATEMENT block. Delete if not required.\n' +
'AFTER STATEMENT IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;\n\n' +
'-- BEFORE EACH ROW block. Delete if not required.\n' +
'BEFORE EACH ROW IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;\n\n' +
'-- AFTER EACH ROW block. Delete if not required.\n' +
'AFTER EACH ROW IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;\n\n' +
'-- INSTEAD OF EACH ROW block. Delete if not required.\n' +
'INSTEAD OF EACH ROW IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;');
},
// We will check if we are under schema node & in 'create' mode
inSchema: function() {
if(this.node_info && 'catalog' in this.node_info) {
return true;
}
return false;
},
inEditMode: function(m) {
return !m.isNew();
},
// Checks weather to enable/disable control
inSchemaWithColumnCheck: function(m) {
if(this.node_info && 'schema' in this.node_info) {
// We will disable control if it's system columns
// ie: it's position is less then 1
if (m.isNew()) {
return false;
} else {
// if we are in edit mode
return !(!_.isUndefined(m.get('attnum')) && m.get('attnum') >= 1 );
}
}
return true;
},
}),
canCreate: function(itemData, item, data) {
//If check is false then , we will allow create menu

View File

@ -0,0 +1,208 @@
/////////////////////////////////////////////////////////////
//
// 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 BaseUISchema from 'sources/SchemaView/base_schema.ui';
import { isEmptyString } from 'sources/validators';
export class ForEventsSchema extends BaseUISchema {
constructor(fieldOptions={}, nodeInfo, initValues) {
super({
...initValues,
});
this.fieldOptions = {
...fieldOptions,
};
this.nodeInfo = nodeInfo;
}
get baseFields() {
let obj = this;
return [
{
id: 'evnt_insert', label: gettext('INSERT'),
type: 'switch',
readonly: function(state) {
var evn_insert = state.evnt_insert;
if (!_.isUndefined(evn_insert) && obj.nodeInfo.server.server_type == 'ppas')
return false;
return obj.inCatalog();
},
},{
id: 'evnt_update', label: gettext('UPDATE'),
type: 'switch',
readonly: function(state) {
var evn_update = state.evnt_update;
if (!_.isUndefined(evn_update) && obj.nodeInfo.server.server_type == 'ppas')
return false;
return obj.inCatalog();
},
},{
id: 'evnt_delete', label: gettext('DELETE'),
type: 'switch',
readonly: function(state) {
var evn_delete = state.evnt_delete;
if (!_.isUndefined(evn_delete) && obj.nodeInfo.server.server_type == 'ppas')
return false;
return obj.inCatalog();
},
},{
id: 'evnt_truncate', label: gettext('TRUNCATE'),
type: 'switch',
readonly: function(state) {
var evn_truncate = state.evnt_truncate;
// Views cannot have TRUNCATE triggers.
if ('view' in obj.nodeInfo)
return true;
if (!_.isUndefined(evn_truncate) && obj.nodeInfo.server.server_type == 'ppas')
return false;
return obj.inCatalog();
},
}
];
}
}
export default class CompoundTriggerSchema extends BaseUISchema {
constructor(fieldOptions={}, nodeInfo, initValues) {
super({
name: undefined,
...initValues,
});
this.fieldOptions = {
columns: [],
...fieldOptions,
};
this.nodeInfo = nodeInfo;
}
get idAttribute() {
return 'oid';
}
get baseFields() {
let obj = this;
return [
{
id: 'name', label: gettext('Name'), cell: 'text',
type: 'text', noEmpty: true,
disabled: obj.inCatalog(),
},{
id: 'oid', label: gettext('OID'), cell: 'text',
type: 'int', mode: ['properties'],
},{
id: 'is_enable_trigger', label: gettext('Trigger enabled?'),
mode: ['edit', 'properties'],
disabled: obj.inCatalog(),
type: 'select', controlProps: { allowClear: false },
options: [
{label: gettext('Enable'), value: 'O'},
{label: gettext('Enable Replica'), value: 'R'},
{label: gettext('Enable Always'), value: 'A'},
{label: gettext('Disable'), value: 'D'},
],
},{
type: 'nested-fieldset', label: gettext('FOR Events'), group: gettext('Events'),
schema: new ForEventsSchema({}, this.nodeInfo),
},{
id: 'whenclause', label: gettext('When'), group: gettext('Events'),
type: 'sql', disabled: obj.inCatalog(),
readonly: function(state) { return !obj.isNew(state); },
},{
id: 'columns', label: gettext('Columns'), group: gettext('Events'),
editable: false, type: 'select', options: this.fieldOptions.columns,
controlProps: { allowClear: false, multiple: true }, deps: ['evnt_update'],
disabled: function(state) {
if(obj.inCatalog()) {
return true;
}
// Enable column only if update event is set true
var isUpdate = state.evnt_update;
if(!_.isUndefined(isUpdate) && isUpdate) {
return false;
}
return true;
},
readonly: function(state) { return !obj.isNew(state); },
},{
id: 'prosrc', label: gettext('Code'), group: gettext('Code'),
type: 'sql', mode: ['create', 'edit'],
isFullTab: true,
disabled: function(state) {
if(obj.isNew(state) && _.isUndefined(state.prosrc)) {
state.prosrc = obj.getCodeTemplate();
}
return false;
},
},{
id: 'is_sys_trigger', label: gettext('System trigger?'),
type: 'switch', disabled: obj.inCatalog(), mode: ['properties'],
readonly: function(state) { return !obj.isNew(state); },
},{
id: 'description', label: gettext('Comment'), type: 'multiline',
disabled: obj.inCatalog(),
}
];
}
validate(state, setError) {
if(!state.evnt_truncate && !state.evnt_delete && !state.evnt_update && !state.evnt_insert) {
setError('evnt_insert', gettext('Specify at least one event.'));
return true;
} else {
setError('evnt_insert', null);
}
if(isEmptyString(state.prosrc)) {
setError(state.prosrc, gettext('Code cannot be empty.'));
return true;
} else {
setError(state.prosrc, null);
}
}
// This function returns the code template for compound trigger
getCodeTemplate() {
return gettext('-- Enter any global declarations below:\n\n' +
'-- BEFORE STATEMENT block. Delete if not required.\n' +
'BEFORE STATEMENT IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;\n\n' +
'-- AFTER STATEMENT block. Delete if not required.\n' +
'AFTER STATEMENT IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;\n\n' +
'-- BEFORE EACH ROW block. Delete if not required.\n' +
'BEFORE EACH ROW IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;\n\n' +
'-- AFTER EACH ROW block. Delete if not required.\n' +
'AFTER EACH ROW IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;\n\n' +
'-- INSTEAD OF EACH ROW block. Delete if not required.\n' +
'INSTEAD OF EACH ROW IS\n' +
' -- Enter any local declarations here\n' +
'BEGIN\n' +
' -- Enter any required code here\n' +
'END;');
}
}

View File

@ -106,17 +106,10 @@ export class EventSchema extends BaseUISchema {
/* events validation*/
if (state.tfunction && !state.evnt_truncate && !state.evnt_delete && !state.evnt_update && !state.evnt_insert) {
errmsg = gettext('Specify at least one event.');
//setError('evnt_truncate', errmsg);
//setError('evnt_delete', errmsg);
//setError('evnt_update', errmsg);
setError('evnt_insert', errmsg);
//setError('evnt_update', errmsg);
return true;
} else {
errmsg = null;
//setError('evnt_truncate', errmsg);
//setError('evnt_delete', errmsg);
//setError('evnt_update', errmsg);
setError('evnt_insert', errmsg);
}
}
@ -147,14 +140,6 @@ export default class TriggerSchema extends BaseUISchema {
return 'oid';
}
inSchema() {
// Check if under schema node & in 'create' mode
if('catalog' in this.nodeInfo) {
return true;
}
return false;
}
inSchemaWithModelCheck(state) {
// Check if we are under schema node & in 'create' mode
if('schema' in this.nodeInfo) {
@ -208,7 +193,7 @@ export default class TriggerSchema extends BaseUISchema {
let obj = this;
return [{
id: 'name', label: gettext('Name'), cell: 'text',
type: 'text', disabled: obj.inSchema, noEmpty: true
type: 'text', disabled: obj.inCatalog(), noEmpty: true
},{
id: 'oid', label: gettext('OID'), cell: 'text',
type: 'int', mode: ['properties'],
@ -469,7 +454,7 @@ export default class TriggerSchema extends BaseUISchema {
},{
id: 'description', label: gettext('Comment'), cell: 'string',
type: 'multiline', mode: ['properties', 'create', 'edit'],
disabled: obj.inSchema,
disabled: obj.inCatalog(),
}];
}

View File

@ -180,7 +180,7 @@ class RangeSchema extends BaseUISchema {
collationsList: [],
...fieldOptions
};
this.node_info = {
this.nodeInfo = {
...node_info.node_info
};
}
@ -224,14 +224,14 @@ class RangeSchema extends BaseUISchema {
controlProps: { allowClear: true, placeholder: '', width: '100%' },
mode: ['properties', 'create', 'edit'],
group: gettext('Range Type'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
}, {
id: 'opcname', label: gettext('Subtype operator class'), cell: 'string',
mode: ['properties', 'create', 'edit'], group: gettext('Range Type'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function(state) {
return !obj.isNew(state);
},
@ -293,7 +293,7 @@ class RangeSchema extends BaseUISchema {
deps: ['typname'],
controlProps: { allowClear: true, placeholder: '', width: '100%' },
disabled: (state) => {
let disableCollNameControl = inSchema(obj.node_info);
let disableCollNameControl = obj.inCatalog();
if (disableCollNameControl)
return disableCollNameControl;
@ -349,7 +349,7 @@ class RangeSchema extends BaseUISchema {
},
mode: ['properties', 'create', 'edit'],
group: gettext('Range Type'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function(state) {
return !obj.isNew(state);
},
@ -358,7 +358,7 @@ class RangeSchema extends BaseUISchema {
id: 'rngsubdiff', label: gettext('Subtype diff function'), cell: 'string',
mode: ['properties', 'create', 'edit'],
group: gettext('Range Type'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function(state) {
return !obj.isNew(state);
},
@ -449,7 +449,7 @@ class ExternalSchema extends BaseUISchema {
{label: 'MAIN', value: 'm'},
{label: 'EXTENDED', value: 'x'},
];
this.node_info = {
this.nodeInfo = {
...node_info.node_info
};
}
@ -481,7 +481,7 @@ class ExternalSchema extends BaseUISchema {
},{
id: 'typinput', label: gettext('Input function'),
mode: ['properties', 'create', 'edit'], group: gettext('Required'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -534,7 +534,7 @@ class ExternalSchema extends BaseUISchema {
readonly: function (state) {
return !obj.isNew(state);
},
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
controlProps: { allowClear: true, placeholder: '', width: '100%' },
},{
id: 'spacer_ctrl_optional_1', group: gettext('Optional-1'), mode: ['edit', 'create'], type: 'spacer',
@ -563,7 +563,7 @@ class ExternalSchema extends BaseUISchema {
},
group: gettext('Optional-1'),
mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -593,7 +593,7 @@ class ExternalSchema extends BaseUISchema {
};
},
mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -630,7 +630,7 @@ class ExternalSchema extends BaseUISchema {
};
},
mode: ['properties', 'create', 'edit'], group: gettext('Optional-1'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -668,7 +668,7 @@ class ExternalSchema extends BaseUISchema {
};
},
mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -676,7 +676,7 @@ class ExternalSchema extends BaseUISchema {
id: 'typlen', label: gettext('Internal length'),
cell: 'integer', group: gettext('Optional-1'),
type: 'int', mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -684,7 +684,7 @@ class ExternalSchema extends BaseUISchema {
id: 'variable', label: gettext('Variable?'), cell: 'switch',
group: gettext('Optional-1'), type: 'switch',
mode: ['create','edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -692,7 +692,7 @@ class ExternalSchema extends BaseUISchema {
id: 'typdefault', label: gettext('Default?'),
cell: 'string', group: gettext('Optional-1'),
type: 'text', mode: ['properties', 'create','edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -721,7 +721,7 @@ class ExternalSchema extends BaseUISchema {
};
},
mode: ['properties', 'create','edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -743,7 +743,7 @@ class ExternalSchema extends BaseUISchema {
};
},
mode: ['properties', 'create','edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -751,7 +751,7 @@ class ExternalSchema extends BaseUISchema {
},{
id: 'typispreferred', label: gettext('Preferred?'),
type: 'switch', mode: ['properties', 'create','edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -788,7 +788,7 @@ class ExternalSchema extends BaseUISchema {
};
},
mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -798,7 +798,7 @@ class ExternalSchema extends BaseUISchema {
type: 'text',
mode: ['properties', 'create', 'edit'],
group: gettext('Optional-2'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -808,7 +808,7 @@ class ExternalSchema extends BaseUISchema {
type: 'select',
options: obj.fieldOptions.typeAlignOptions,
mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -817,7 +817,7 @@ class ExternalSchema extends BaseUISchema {
id: 'typstorage', label: gettext('Storage type'),
type: 'select', mode: ['properties', 'create', 'edit'],
group: gettext('Optional-2'), cell: 'string',
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -827,7 +827,7 @@ class ExternalSchema extends BaseUISchema {
id: 'typbyval', label: gettext('Passed by value?'),
cell: 'switch',
type: 'switch', mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -836,7 +836,7 @@ class ExternalSchema extends BaseUISchema {
id: 'is_collatable', label: gettext('Collatable?'),
cell: 'switch', min_version: 90100, group: gettext('Optional-2'),
type: 'switch', mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -1287,14 +1287,6 @@ class DataTypeSchema extends BaseUISchema {
}
}
function inSchema(node_info) {
if(node_info && 'catalog' in node_info)
{
return true;
}
return false;
}
export default class TypeSchema extends BaseUISchema {
constructor(getPrivilegeRoleSchema, getCompositeSchema, getRangeSchema, getExternalSchema, getDataTypeSchema, fieldOptions = {}, initValues) {
super({
@ -1318,6 +1310,7 @@ export default class TypeSchema extends BaseUISchema {
this.getRangeSchema = getRangeSchema;
this.getExternalSchema = getExternalSchema;
this.getDataTypeSchema = getDataTypeSchema;
this.nodeInfo = this.fieldOptions.node_info;
}
schemaCheck(state) {
@ -1353,7 +1346,7 @@ export default class TypeSchema extends BaseUISchema {
mode: ['properties', 'create', 'edit'], noEmpty: true,
type: 'select', options: this.fieldOptions.roles,
controlProps: { allowClear: false },
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
},{
id: 'schema', label: gettext('Schema'), cell: 'string',
mode: ['create', 'edit'], noEmpty: true,
@ -1388,7 +1381,7 @@ export default class TypeSchema extends BaseUISchema {
id: 'typtype', label: gettext('Type'),
mode: ['create','edit'], group: gettext('Definition'),
type: 'select',
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
readonly: function (state) {
return !obj.isNew(state);
},
@ -1417,7 +1410,7 @@ export default class TypeSchema extends BaseUISchema {
group: gettext('Definition'), mode: ['edit', 'create'],
uniqueCol : ['member_name'],
canAdd: true, canEdit: false, canDelete: true,
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
schema: obj.getCompositeSchema(),
deps: ['typtype'],
visible: (state) => {
@ -1435,7 +1428,7 @@ export default class TypeSchema extends BaseUISchema {
// We will disable it if it's in 'edit' mode
return !obj.isNew(state);
},
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
deps: ['typtype'],
uniqueCol : ['label'],
visible: function(state) {
@ -1475,12 +1468,12 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'alias', label: gettext('Alias'), cell: 'string',
type: 'text', mode: ['properties'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
},
{
id: 'member_list', label: gettext('Members'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'c') {
return true;
@ -1490,7 +1483,7 @@ export default class TypeSchema extends BaseUISchema {
},{
id: 'enum_list', label: gettext('Labels'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'e') {
return true;
@ -1501,7 +1494,7 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'typname', label: gettext('SubType'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'r') {
return true;
@ -1512,7 +1505,7 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'opcname', label: gettext('Subtype operator class'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'r') {
return true;
@ -1523,7 +1516,7 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'collname', label: gettext('Collation'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'r') {
return true;
@ -1534,7 +1527,7 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'rngcanonical', label: gettext('Canonical function'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'r') {
return true;
@ -1545,7 +1538,7 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'rngsubdiff', label: gettext('Subtype diff function'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'r') {
return true;
@ -1556,7 +1549,7 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'typinput', label: gettext('Input function'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'b') {
return true;
@ -1567,7 +1560,7 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'typoutput', label: gettext('Output function'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Definition'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
visible: function(state) {
if(state.typtype === 'b') {
return true;
@ -1578,17 +1571,17 @@ export default class TypeSchema extends BaseUISchema {
{
id: 'type_acl', label: gettext('Privileges'), cell: 'string',
type: 'text', mode: ['properties'], group: gettext('Security'),
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
},
{
id: 'is_sys_type', label: gettext('System type?'), cell: 'switch',
type: 'switch', mode: ['properties'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
},
{
id: 'description', label: gettext('Comment'), cell: 'string',
type: 'multiline', mode: ['properties', 'create', 'edit'],
disabled: () => inSchema(obj.node_info),
disabled: () => obj.inCatalog(),
},
{
id: 'typacl', label: gettext('Privileges'), type: 'collection',

View File

@ -137,6 +137,7 @@ define('pgadmin.node.mview', [
spcname: ()=>getNodeListByName('tablespace', treeNodeInfo, itemNodeData, {}, (m)=> {
return (m.label != 'pg_global');
}),
nodeInfo: treeNodeInfo,
},
{
owner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name,

View File

@ -39,21 +39,12 @@ export default class MViewSchema extends BaseUISchema {
return 'oid';
}
inSchema() {
if(this.nodeInfo && 'catalog' in this.nodeInfo)
{
return true;
}
return false;
}
get baseFields() {
let obj = this;
return [
{
id: 'name', label: gettext('Name'), cell: 'text',
type: 'text', disabled: obj.inSchema, noEmpty: true,
type: 'text', disabled: obj.inCatalog(), noEmpty: true,
},{
id: 'oid', label: gettext('OID'), cell: 'text',
type: 'text', mode: ['properties'],
@ -61,11 +52,11 @@ export default class MViewSchema extends BaseUISchema {
id: 'owner', label: gettext('Owner'),
type: 'select', cell: 'text',
options: obj.fieldOptions.role, controlProps: { allowClear: false },
disabled: obj.inSchema,
disabled: obj.inCatalog(),
},{
id: 'schema', label: gettext('Schema'), cell: 'text',
type: 'select', options: obj.fieldOptions.schema, mode: ['create', 'edit'],
cache_node: 'database', disabled: obj.inSchema,
cache_node: 'database', disabled: obj.inCatalog(),
controlProps: {
allowClear: false,
first_empty: false

View File

@ -136,4 +136,12 @@ export default class BaseUISchema {
addDisabled() {
return false;
}
/* Check */
inCatalog() {
if(this.nodeInfo && 'catalog' in this.nodeInfo) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,116 @@
/////////////////////////////////////////////////////////////
//
// 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 CompoundTriggerSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.ui';
describe('CompoundTriggerSchema', ()=>{
let mount;
let schemaObj = new CompoundTriggerSchema(
{
columns: [],
},
{
schema: {},
server: {user: {name:'enterprisedb', id:0}, server_type: 'ppas', version: 120000},
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.evnt_truncate = false;
state.evnt_delete = false;
state.evnt_update = false;
state.evnt_insert = false;
schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('evnt_insert', 'Specify at least one event.');
state.evnt_insert = true;
schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('evnt_insert', null);
});
});

View File

@ -14,11 +14,23 @@ 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 PgaJobSchema from '../../../pgadmin/browser/server_groups/servers/pgagent/static/js/pga_job.ui';
class MockSchema extends BaseUISchema {
get baseFields() {
return [];
}
}
describe('PgaJobSchema', ()=>{
let mount;
let schemaObj = new PgaJobSchema();
let schemaObj = new PgaJobSchema(
{
jobjclid:()=>[],
},
()=>new MockSchema(),
);
let getInitData = ()=>Promise.resolve({});
/* Use createMount so that material ui components gets the required context */