From b7105093e2b0cef2d75ac183441d67b680004bc6 Mon Sep 17 00:00:00 2001 From: Akshay Joshi Date: Tue, 17 Aug 2021 16:47:05 +0530 Subject: [PATCH] 1) Port Compound Trigger node to react. Fixes #6674 2) Remove 'inSchema' method and create a generic method 'inCatalog'. --- .../schemas/synonyms/static/js/synonym.ui.js | 16 +- .../static/js/compound_trigger.js | 237 ++---------------- .../static/js/compound_trigger.ui.js | 208 +++++++++++++++ .../tables/triggers/static/js/trigger.ui.js | 19 +- .../schemas/types/static/js/type.ui.js | 95 ++++--- .../schemas/views/static/js/mview.js | 1 + .../schemas/views/static/js/mview.ui.js | 15 +- .../static/js/SchemaView/base_schema.ui.js | 8 + .../compound_trigger.ui.spec.js | 116 +++++++++ .../schema_ui_files/pga_job.ui.spec.js | 14 +- 10 files changed, 414 insertions(+), 315 deletions(-) create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.ui.js create mode 100644 web/regression/javascript/schema_ui_files/compound_trigger.ui.spec.js diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.ui.js index cd54bfd16..ac7b08fc2 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.ui.js @@ -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; - } } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js index e46f53a25..783af99d0 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.ui.js new file mode 100644 index 000000000..98e231d8f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.ui.js @@ -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;'); + } +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.ui.js index 974142f7e..7ab1f1bfb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.ui.js @@ -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(), }]; } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js index 50c6d0a5f..16d13816b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js @@ -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', @@ -1637,4 +1630,4 @@ export { getRangeSchema, getExternalSchema, getDataTypeSchema -}; \ No newline at end of file +}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js index ce36dde36..da3911dfb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js @@ -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, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.ui.js index e8cbd8d52..6d98a7d13 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.ui.js @@ -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 diff --git a/web/pgadmin/static/js/SchemaView/base_schema.ui.js b/web/pgadmin/static/js/SchemaView/base_schema.ui.js index 48a905156..e759e1fcb 100644 --- a/web/pgadmin/static/js/SchemaView/base_schema.ui.js +++ b/web/pgadmin/static/js/SchemaView/base_schema.ui.js @@ -136,4 +136,12 @@ export default class BaseUISchema { addDisabled() { return false; } + + /* Check */ + inCatalog() { + if(this.nodeInfo && 'catalog' in this.nodeInfo) { + return true; + } + return false; + } } diff --git a/web/regression/javascript/schema_ui_files/compound_trigger.ui.spec.js b/web/regression/javascript/schema_ui_files/compound_trigger.ui.spec.js new file mode 100644 index 000000000..e0e84c6a0 --- /dev/null +++ b/web/regression/javascript/schema_ui_files/compound_trigger.ui.spec.js @@ -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({}} + onClose={()=>{}} + onHelp={()=>{}} + onEdit={()=>{}} + onDataChange={()=>{}} + confirmOnCloseReset={false} + hasSQL={false} + disableSqlHelp={false} + />); + }); + + it('edit', ()=>{ + mount({}} + onClose={()=>{}} + onHelp={()=>{}} + onEdit={()=>{}} + onDataChange={()=>{}} + confirmOnCloseReset={false} + hasSQL={false} + disableSqlHelp={false} + />); + }); + + it('properties', ()=>{ + mount({}} + 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); + }); +}); diff --git a/web/regression/javascript/schema_ui_files/pga_job.ui.spec.js b/web/regression/javascript/schema_ui_files/pga_job.ui.spec.js index 1aad80da5..178004c69 100644 --- a/web/regression/javascript/schema_ui_files/pga_job.ui.spec.js +++ b/web/regression/javascript/schema_ui_files/pga_job.ui.spec.js @@ -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 */