Hi Hackers,
Please find the attached patch for RM-6672:
<https://redmine.postgresql.org/issues/6672> [React] Port Triggers node to
react.
Also, resolved the issue in the trigger function node, the schema is not
getting selected in the edit mode.
--
*Thanks & Regards,*
*Nikhil Mohite*
*Software Engineer.*
*EDB Postgres* <https://www.enterprisedb.com/>
*Mob.No: +91-7798364578.*
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
index 154a17bb8..c4b023eea 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
@@ -1480,8 +1480,7 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
parallel_dict = {'u': 'UNSAFE', 's': 'SAFE', 'r': 'RESTRICTED'}
# Get Schema Name from its OID.
- if self.node_type != 'trigger_function':
- self._get_schema_name_from_oid(data)
+ self._get_schema_name_from_oid(data)
if fnid is not None:
# Edit Mode
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
index 83ed9c6e3..84e1b03aa 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
@@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import TriggerFunctionSchema from './trigger_function.ui';
-import { getNodeListByName, getNodeAjaxOptions } from '../../../../../../../static/js/node_ajax';
+import { getNodeListByName, getNodeListById, getNodeAjaxOptions } from '../../../../../../../static/js/node_ajax';
import { getNodeVariableSchema } from '../../../../../static/js/variable.ui';
import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
@@ -91,7 +91,9 @@ define('pgadmin.node.trigger_function', [
()=>getNodeVariableSchema(this, treeNodeInfo, itemNodeData, false, false),
{
role: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData),
- schema: ()=>getNodeListByName('schema', treeNodeInfo, itemNodeData, {cacheLevel: 'database'}),
+ schema: ()=>getNodeListById(pgBrowser.Nodes['schema'], treeNodeInfo, itemNodeData, {
+ cacheLevel: 'database'
+ }),
language: ()=>getNodeAjaxOptions('get_languages', this, treeNodeInfo, itemNodeData, {noCache: true}, (res) => {
return _.reject(res, function(o) {
return o.label == 'sql' || o.label == 'edbspl';
@@ -101,7 +103,7 @@ define('pgadmin.node.trigger_function', [
},
{
funcowner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name,
- pronamespace: treeNodeInfo.schema ? treeNodeInfo.schema.label : ''
+ pronamespace: treeNodeInfo.schema ? treeNodeInfo.schema._id : null
}
);
},
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js
index 22e20fa92..2b9904e0d 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js
@@ -6,6 +6,8 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
+import { getNodeListByName, getNodeAjaxOptions } from '../../../../../../../../static/js/node_ajax';
+import TriggerSchema from './trigger.ui';
define('pgadmin.node.trigger', [
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
@@ -173,6 +175,19 @@ define('pgadmin.node.trigger', [
},
canDrop: SchemaChildTreeNode.isTreeItemOfChildOfSchema,
canDropCascade: SchemaChildTreeNode.isTreeItemOfChildOfSchema,
+ getSchema: function(treeNodeInfo, itemNodeData) {
+ return new TriggerSchema(
+ {
+ triggerFunction: ()=>getNodeAjaxOptions('get_triggerfunctions', this, treeNodeInfo, itemNodeData, {cacheLevel: 'trigger_function'}, (data) => {
+ return _.reject(data, function(option) {
+ return option.label == '';
+ });
+ }),
+ columns: ()=> getNodeListByName('column', treeNodeInfo, itemNodeData, { cacheLevel: 'column'}),
+ nodeInfo: treeNodeInfo
+ },
+ );
+ },
model: pgAdmin.Browser.Node.Model.extend({
idAttribute: 'oid',
defaults: {
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
new file mode 100644
index 000000000..974142f7e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.ui.js
@@ -0,0 +1,492 @@
+/////////////////////////////////////////////////////////////
+//
+// 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 EventSchema extends BaseUISchema {
+ constructor(fieldOptions={}, initValues) {
+ super({
+ evnt_update: false,
+ evnt_insert: false,
+ evnt_delete: false,
+ evnt_truncate: false,
+ is_row_trigger: false,
+ is_constraint_trigger: false,
+ ...initValues,
+ });
+
+ this.fieldOptions = {
+ nodeInfo: null,
+ ...fieldOptions,
+ };
+
+ this.nodeInfo = this.fieldOptions.nodeInfo;
+
+ }
+
+ get idAttribute() {
+ return 'oid';
+ }
+
+ inSchemaWithModelCheck(state) {
+ // Check if we are under schema node & in 'create' mode
+ if(this.nodeInfo && 'schema' in this.nodeInfo) {
+ // We will disable control if it's in 'edit' mode
+ return !this.isNew(state);
+ }
+ return true;
+ }
+
+ get baseFields() {
+ let obj = this;
+ return [{
+ id: 'evnt_insert', label: gettext('INSERT'),
+ type: 'switch', mode: ['create','edit', 'properties'],
+ group: gettext('Events'),
+ disabled: (state) => {
+ var evn_insert = state.evnt_insert;
+ if (!_.isUndefined(evn_insert) && obj.nodeInfo && obj.nodeInfo.server.server_type == 'ppas' && obj.isNew(state))
+ return false;
+ return obj.inSchemaWithModelCheck(state);
+ },
+ },{
+ id: 'evnt_update', label: gettext('UPDATE'),
+ type: 'switch', mode: ['create','edit', 'properties'],
+ group: gettext('Events'),
+ disabled: (state) => {
+ var evn_update = state.evnt_update;
+ if (!_.isUndefined(evn_update) && obj.nodeInfo && obj.nodeInfo.server.server_type == 'ppas' && obj.isNew(state))
+ return false;
+ return obj.inSchemaWithModelCheck(state);
+ },
+ },{
+ id: 'evnt_delete', label: gettext('DELETE'),
+ type: 'switch', mode: ['create','edit', 'properties'],
+ group: gettext('Events'),
+ disabled: (state) => {
+ var evn_delete = state.evnt_delete;
+ if (!_.isUndefined(evn_delete) && obj.nodeInfo && obj.nodeInfo.server.server_type == 'ppas' && obj.isNew(state))
+ return false;
+ return obj.inSchemaWithModelCheck(state);
+ },
+ },{
+ id: 'evnt_truncate', label: gettext('TRUNCATE'),
+ type: 'switch', group: gettext('Events'), deps: ['is_row_trigger', 'is_constraint_trigger'],
+ disabled: (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;
+ if (is_row_trigger == true){
+ state.evnt_truncate = false;
+ return true;
+ }
+
+ if (server_type === 'ppas' && !_.isUndefined(is_constraint_trigger) &&
+ !_.isUndefined(is_row_trigger) &&
+ is_constraint_trigger === false && obj.isNew(state))
+ return false;
+
+ return obj.inSchemaWithModelCheck(state);
+ },
+ }];
+ }
+
+ validate(state, setError) {
+
+ if (isEmptyString(state.service)) {
+ let errmsg = null;
+ /* 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);
+ }
+ }
+ }
+
+}
+
+
+export default class TriggerSchema extends BaseUISchema {
+ constructor(fieldOptions={}, initValues) {
+ super({
+ name: undefined,
+ is_row_trigger: true,
+ fires: 'BEFORE',
+ ...initValues
+ });
+
+ this.fieldOptions = {
+ triggerFunction: [],
+ //columns: [],
+ ...fieldOptions,
+ };
+ this.nodeInfo = this.fieldOptions.nodeInfo;
+
+ }
+
+ get idAttribute() {
+ 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) {
+ // We will disable control if it's in 'edit' mode
+ return !this.isNew(state);
+ }
+ return true;
+ }
+
+ disableTransition(state) {
+ if (!this.isNew())
+ return true;
+ var flag = false,
+ evnt = null,
+ name = state.name,
+ evnt_count = 0;
+
+ // Disable transition tables for view trigger and PG version < 100000
+ if(_.indexOf(Object.keys(this.nodeInfo), 'table') == -1 ||
+ this.nodeInfo.server.version < 100000) return true;
+
+ if (name == 'tgoldtable') evnt = 'evnt_delete';
+ else if (name == 'tgnewtable') evnt = 'evnt_insert';
+
+ if(state.evnt_insert) evnt_count++;
+ if(state.evnt_update) evnt_count++;
+ if(state.evnt_delete) evnt_count++;
+
+
+ // Disable transition tables if
+ // - It is a constraint trigger
+ // - Fires other than AFTER
+ // - More than one events enabled
+ // - Update event with the column list
+
+ // Disable Old transition table if both UPDATE and DELETE events are disabled
+ // Disable New transition table if both UPDATE and INSERT events are disabled
+ if(!state.is_constraint_trigger && state.fires == 'AFTER' &&
+ (state.evnt_update || state[evnt]) && evnt_count == 1) {
+ flag = (state.evnt_update && (_.size(state.columns) >= 1 && state.columns[0] != ''));
+ }
+
+ if(flag && state.name) {
+ state.name = null;
+ }
+
+ return flag;
+ }
+
+ get baseFields() {
+ let obj = this;
+ return [{
+ id: 'name', label: gettext('Name'), cell: 'text',
+ type: 'text', disabled: obj.inSchema, noEmpty: true
+ },{
+ id: 'oid', label: gettext('OID'), cell: 'text',
+ type: 'int', mode: ['properties'],
+ },{
+ id: 'is_enable_trigger', label: gettext('Trigger enabled?'),
+ mode: ['edit', 'properties'], group: gettext('Definition'),
+ type: 'select',
+ disabled: () => {
+ if('catalog' in obj.nodeInfo || 'view' in obj.nodeInfo) {
+ 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'},
+ ],
+ controlProps: { allowClear: false },
+ },{
+ id: 'is_row_trigger', label: gettext('Row trigger?'),
+ type: 'switch', group: gettext('Definition'),
+ mode: ['create','edit', 'properties'],
+ deps: ['is_constraint_trigger'],
+ disabled: (state) => {
+ // Disabled if table is a partitioned table.
+ if (!obj.isNew())
+ return true;
+
+ if (obj.nodeInfo.table.is_partitioned && obj.nodeInfo.server.version < 110000)
+ {
+ state.is_row_trigger = false;
+ return true;
+ }
+
+ // If constraint trigger is set to True then row trigger will
+ // automatically set to True and becomes disable
+ var is_constraint_trigger = state.is_constraint_trigger;
+ if(!obj.inSchemaWithModelCheck(state)) {
+ if(!_.isUndefined(is_constraint_trigger) &&
+ is_constraint_trigger === true) {
+ // change it's model value
+ state.is_row_trigger = true;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ // Check if it is row trigger then enabled it.
+ var is_row_trigger = state.is_row_trigger;
+ if (!_.isUndefined(is_row_trigger) && obj.nodeInfo.server.server_type == 'ppas') {
+ return false;
+ }
+ // Disable it
+ return true;
+ }
+ },
+ },{
+ id: 'is_constraint_trigger', label: gettext('Constraint trigger?'),
+ type: 'switch',
+ mode: ['create','edit', 'properties'],
+ group: gettext('Definition'),
+ deps: ['tfunction'],
+ disabled: (state) => {
+ // Disabled if table is a partitioned table.
+ var tfunction = state.tfunction;
+ if (( _.has(obj.nodeInfo, 'table') && _.has(obj.nodeInfo.table, 'is_partitioned') &&
+ obj.nodeInfo.table.is_partitioned) || ( _.has(obj.nodeInfo, 'view')) ||
+ (obj.nodeInfo.server.server_type === 'ppas' && !_.isUndefined(tfunction) &&
+ tfunction === 'Inline EDB-SPL')) {
+ state.is_constraint_trigger = false;
+ return true;
+ }
+ return obj.inSchemaWithModelCheck(state);
+ },
+ },{
+ id: 'tgdeferrable', label: gettext('Deferrable?'),
+ type: 'switch', group: gettext('Definition'),
+ mode: ['create','edit', 'properties'],
+ deps: ['is_constraint_trigger'],
+ disabled: (state) => {
+ // If constraint trigger is set to True then only enable it
+ var is_constraint_trigger = state.is_constraint_trigger;
+ if(!obj.inSchemaWithModelCheck(state)) {
+ if(!_.isUndefined(is_constraint_trigger) &&
+ is_constraint_trigger === true) {
+ return false;
+ } else {
+ // If value is already set then reset it to false
+ if(state.tgdeferrable) {
+ state.tgdeferrable = false;
+ }
+ return true;
+ }
+ } else {
+ // Disable it
+ return true;
+ }
+ },
+ },{
+ id: 'tginitdeferred', label: gettext('Deferred?'),
+ type: 'switch', group: gettext('Definition'),
+ mode: ['create','edit', 'properties'],
+ deps: ['tgdeferrable', 'is_constraint_trigger'],
+ disabled: (state) => {
+ // If Deferrable is set to True then only enable it
+ var tgdeferrable = state.tgdeferrable;
+ if(!obj.inSchemaWithModelCheck(state)) {
+ if(!_.isUndefined(tgdeferrable) && tgdeferrable) {
+ return false;
+ } else {
+ // If value is already set then reset it to false
+ if(obj.tginitdeferred) {
+ state.tginitdeferred = false;
+ }
+ // If constraint trigger is set then do not disable
+ return state.is_constraint_trigger ? false : true;
+ }
+ } else {
+ // Disable it
+ return true;
+ }
+ },
+ },{
+ id: 'tfunction', label: gettext('Trigger function'),
+ type: 'select', disabled: obj.inSchemaWithModelCheck,
+ mode: ['create','edit', 'properties'], group: gettext('Definition'),
+ control: 'node-ajax-options', url: 'get_triggerfunctions', url_jump_after_node: 'schema',
+ options: obj.fieldOptions.triggerFunction,
+ cache_node: 'trigger_function',
+ },{
+ id: 'tgargs', label: gettext('Arguments'), cell: 'text',
+ group: gettext('Definition'),
+ type: 'text',mode: ['create','edit', 'properties'], deps: ['tfunction'],
+ disabled: (state) => {
+ // We will disable it when EDB PPAS and trigger function is
+ // set to Inline EDB-SPL
+ var tfunction = state.tfunction,
+ server_type = obj.nodeInfo.server.server_type;
+ if(!obj.inSchemaWithModelCheck(state)) {
+ if(server_type === 'ppas' &&
+ !_.isUndefined(tfunction) &&
+ tfunction === 'Inline EDB-SPL') {
+ // Disable and clear its value
+ state.tgargs = undefined;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ // Disable it
+ return true;
+ }
+ },
+ },{
+ id: 'fires', label: gettext('Fires'), deps: ['is_constraint_trigger'],
+ mode: ['create','edit', 'properties'], group: gettext('Events'),
+ options: () => {
+ var table_options = [
+ {label: 'BEFORE', value: 'BEFORE'},
+ {label: 'AFTER', value: 'AFTER'}],
+ view_options = [
+ {label: 'BEFORE', value: 'BEFORE'},
+ {label: 'AFTER', value: 'AFTER'},
+ {label: 'INSTEAD OF', value: 'INSTEAD OF'}];
+ // If we are under table then show table specific options
+ if(_.indexOf(Object.keys(obj.nodeInfo), 'table') != -1) {
+ return table_options;
+ } else {
+ return view_options;
+ }
+ },
+ type: 'select', controlProps: { allowClear: false },
+ disabled: (state) => {
+ if (!obj.isNew())
+ return true;
+ // If contraint trigger is set to True then only enable it
+ var is_constraint_trigger = obj.is_constraint_trigger;
+ if(!obj.inSchemaWithModelCheck(state)) {
+ if(!_.isUndefined(is_constraint_trigger) &&
+ is_constraint_trigger === true) {
+ state.fires = 'AFTER';
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ // Check if it is row trigger then enabled it.
+ var fires_ = state.fires;
+ if (!_.isUndefined(fires_) && obj.nodeInfo.server.server_type == 'ppas') {
+ return false;
+ }
+ // Disable it
+ return true;
+ }
+ },
+ },{
+ type: 'nested-fieldset', mode: ['create','edit', 'properties'],
+ label: gettext('Events'), group: gettext('Events'),
+ schema: new EventSchema({nodeInfo: obj.nodeInfo}),
+ },{
+ id: 'whenclause', label: gettext('When'),
+ type: 'sql',
+ readonly: obj.inSchemaWithModelCheck,
+ mode: ['create', 'edit', 'properties'], visible: true,
+ group: gettext('Events'),
+ },{
+ id: 'columns', label: gettext('Columns'),
+ type: 'select', controlProps: { multiple: true },
+ deps: ['evnt_update'], group: gettext('Events'),
+ options: obj.fieldOptions.columns,
+ disabled: (state) => {
+ if(obj.nodeInfo && 'catalog' in obj.nodeInfo) {
+ return true;
+ }
+ //Disable in edit mode
+ if (!obj.isNew()) {
+ return true;
+ }
+ // Enable column only if update event is set true
+ var isUpdate = state.evnt_update;
+ if(!_.isUndefined(isUpdate) && isUpdate) {
+ return false;
+ }
+ return true;
+ },
+ },{
+ id: 'tgoldtable', label: gettext('Old table'),
+ type: 'text', group: gettext('Transition'),
+ cell: 'text', mode: ['create', 'edit', 'properties'],
+ deps: ['fires', 'is_constraint_trigger', 'evnt_insert', 'evnt_update', 'evnt_delete', 'columns'],
+ disabled: obj.disableTransition,
+ },{
+ id: 'tgnewtable', label: gettext('New table'),
+ type: 'text', group: gettext('Transition'),
+ cell: 'string', mode: ['create', 'edit', 'properties'],
+ deps: ['fires', 'is_constraint_trigger', 'evnt_insert', 'evnt_update', 'evnt_delete', 'columns'],
+ disabled: obj.disableTransition,
+ },{
+ id: 'prosrc', label: gettext('Code'), group: gettext('Code'),
+ type: 'sql', mode: ['create', 'edit'], deps: ['tfunction'],
+ isFullTab: true,
+ visible: true,
+ readonly: (state) => {
+ // We will enable it only when EDB PPAS and trigger function is
+ // set to Inline EDB-SPL
+ var tfunction = state.tfunction,
+ server_type = obj.nodeInfo.server.server_type;
+
+ return (server_type !== 'ppas' ||
+ _.isUndefined(tfunction) ||
+ tfunction !== 'Inline EDB-SPL');
+ },
+ },{
+ id: 'is_sys_trigger', label: gettext('System trigger?'), cell: 'text',
+ type: 'switch', disabled: obj.inSchemaWithModelCheck, mode: ['properties'],
+ },{
+ id: 'description', label: gettext('Comment'), cell: 'string',
+ type: 'multiline', mode: ['properties', 'create', 'edit'],
+ disabled: obj.inSchema,
+ }];
+ }
+
+ validate(state, setError) {
+ let errmsg = null;
+
+ if (isEmptyString(state.service)) {
+
+ /* trigger function validation*/
+ if (isEmptyString(state.tfunction)) {
+ errmsg = gettext('Trigger function cannot be empty.');
+ setError('tfunction', errmsg);
+ return true;
+ } else {
+ errmsg = null;
+ setError('tfunction', errmsg);
+ }
+ }
+ }
+}
diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/static/js/pga_schedule.ui.js b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/static/js/pga_schedule.ui.js
index 16bb02201..7320238d1 100644
--- a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/static/js/pga_schedule.ui.js
+++ b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/static/js/pga_schedule.ui.js
@@ -405,6 +405,7 @@ export default class PgaJobScheduleSchema extends BaseUISchema {
}
];
}
+
validate(state, setError) {
if (isEmptyString(state.jscstart)) {
setError('jscstart', gettext('Please enter the start time.'));
diff --git a/web/pgadmin/static/js/SchemaView/FormView.jsx b/web/pgadmin/static/js/SchemaView/FormView.jsx
index d00ac6240..9b8bb05aa 100644
--- a/web/pgadmin/static/js/SchemaView/FormView.jsx
+++ b/web/pgadmin/static/js/SchemaView/FormView.jsx
@@ -63,6 +63,7 @@ function SQLTab({active, getSQLValue}) {
readOnly: true,
}}
isAsync={true}
+ readonly={true}
/>;
}
diff --git a/web/pgadmin/static/js/components/CodeMirror.jsx b/web/pgadmin/static/js/components/CodeMirror.jsx
index cb03ab18f..4745fda9f 100644
--- a/web/pgadmin/static/js/components/CodeMirror.jsx
+++ b/web/pgadmin/static/js/components/CodeMirror.jsx
@@ -13,7 +13,7 @@ import {useOnScreen} from 'sources/custom_hooks';
import PropTypes from 'prop-types';
/* React wrapper for CodeMirror */
-export default function CodeMirror({name, value, options, events, ...props}) {
+export default function CodeMirror({currObj, name, value, options, events, ...props}) {
const taRef = useRef();
const cmObj = useRef();
const cmWrapper = useRef();
@@ -24,6 +24,8 @@ export default function CodeMirror({name, value, options, events, ...props}) {
cmObj.current = new OrigCodeMirror.fromTextArea(
taRef.current, options);
+ currObj && currObj(cmObj.current);
+
if(cmObj.current) {
try {
cmWrapper.current = cmObj.current.getWrapperElement();
@@ -65,6 +67,7 @@ export default function CodeMirror({name, value, options, events, ...props}) {
}
CodeMirror.propTypes = {
+ currObj: PropTypes.func,
name: PropTypes.string,
value: PropTypes.string,
options: PropTypes.object,
diff --git a/web/pgadmin/static/js/components/FormComponents.jsx b/web/pgadmin/static/js/components/FormComponents.jsx
index 43a80bef5..7505ad044 100644
--- a/web/pgadmin/static/js/components/FormComponents.jsx
+++ b/web/pgadmin/static/js/components/FormComponents.jsx
@@ -137,11 +137,19 @@ FormInput.propTypes = {
testcid: PropTypes.any,
};
-export function InputSQL({value, options, onChange, ...props}) {
+export function InputSQL({value, options, onChange, readonly, ...props}) {
const classes = useStyles();
+ const cmObj = useRef();
+
+ useEffect(()=>{
+ if(cmObj.current) {
+ cmObj.current.setOption('readOnly', readonly);
+ }
+ }, [readonly]);
return (
<CodeMirror
+ currObj={(obj)=>cmObj.current=obj}
value={value||''}
options={{
lineNumbers: true,
@@ -161,8 +169,8 @@ export function InputSQL({value, options, onChange, ...props}) {
InputSQL.propTypes = {
value: PropTypes.string,
options: PropTypes.object,
- onChange: PropTypes.func
-
+ onChange: PropTypes.func,
+ readonly: PropTypes.bool
};
export function FormInputSQL({hasError, required, label, className, helpMessage, testcid, value, controlProps, noLabel, ...props}) {
diff --git a/web/regression/javascript/schema_ui_files/trigger.ui.spec.js b/web/regression/javascript/schema_ui_files/trigger.ui.spec.js
new file mode 100644
index 000000000..c437b33ff
--- /dev/null
+++ b/web/regression/javascript/schema_ui_files/trigger.ui.spec.js
@@ -0,0 +1,378 @@
+/////////////////////////////////////////////////////////////
+//
+// 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 TriggerSchema, { EventSchema } from '../../../pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.ui';
+
+describe('TriggerSchema', ()=>{
+ let mount;
+ let schemaObj = new TriggerSchema(
+ {
+ triggerFunction: [],
+ columns: [],
+ nodeInfo: {
+ schema: {},
+ server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 90400},
+ table: {is_partitioned: false}
+ }
+ }
+ );
+ 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.tfunction = null;
+ schemaObj.validate(state, setError);
+ expect(setError).toHaveBeenCalledWith('tfunction', 'Trigger function cannot be empty.');
+
+ state.tfunction = 'public';
+ schemaObj.validate(state, setError);
+ expect(setError).toHaveBeenCalledWith('tfunction', null);
+ });
+
+ it('catalog create', ()=>{
+ let catalogSchemaObj = new TriggerSchema(
+ {
+ triggerFunction: [],
+ columns: [],
+ nodeInfo: {
+ catalog: {},
+ server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 90400},
+ table: {is_partitioned: false}
+ }
+ }
+ );
+
+ mount(<SchemaView
+ formType='dialog'
+ schema={catalogSchemaObj}
+ viewHelperProps={{
+ mode: 'create',
+ }}
+ onSave={()=>{}}
+ onClose={()=>{}}
+ onHelp={()=>{}}
+ onEdit={()=>{}}
+ onDataChange={()=>{}}
+ confirmOnCloseReset={false}
+ hasSQL={false}
+ disableSqlHelp={false}
+ />);
+ });
+
+ it('catalog properties', ()=>{
+ let catalogPropertiesSchemaObj = new TriggerSchema(
+ {
+ triggerFunction: [],
+ columns: [],
+ nodeInfo: {
+ catalog: {},
+ server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 90400},
+ table: {is_partitioned: false}
+ }
+ }
+ );
+
+ mount(<SchemaView
+ formType='tab'
+ schema={catalogPropertiesSchemaObj}
+ getInitData={getInitData}
+ viewHelperProps={{
+ mode: 'properties',
+ }}
+ onHelp={()=>{}}
+ onEdit={()=>{}}
+ />);
+ });
+
+ it('edit disableTransition', ()=>{
+ let editSchemaObj = new TriggerSchema(
+ {
+ triggerFunction: [],
+ columns: [],
+ nodeInfo: {
+ catalog: {},
+ server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 100000},
+ table: {is_partitioned: false}
+ }
+ }
+ );
+
+ let initData = ()=>Promise.resolve({
+ tgoldtable: 'tgoldtable',
+ evnt_insert: true,
+ evnt_update: true,
+ evnt_delete: true,
+ is_constraint_trigger: true,
+ name: 'tgoldtable',
+ fires: 'AFTER'
+ });
+
+ mount(<SchemaView
+ formType='dialog'
+ schema={editSchemaObj}
+ getInitData={initData}
+ viewHelperProps={{
+ mode: 'edit',
+ }}
+ onSave={()=>{}}
+ onClose={()=>{}}
+ onHelp={()=>{}}
+ onEdit={()=>{}}
+ onDataChange={()=>{}}
+ confirmOnCloseReset={false}
+ hasSQL={false}
+ disableSqlHelp={false}
+ />);
+ });
+
+ it('edit disableTransition tgnewtable', ()=>{
+ let editSchemaObj = new TriggerSchema(
+ {
+ triggerFunction: [],
+ columns: [],
+ nodeInfo: {
+ catalog: {},
+ server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 100000},
+ table: {is_partitioned: false}
+ }
+ }
+ );
+
+ let initData = ()=>Promise.resolve({
+ tgoldtable: 'tgnewtable',
+ evnt_insert: true,
+ evnt_update: true,
+ evnt_delete: true,
+ is_constraint_trigger: false,
+ name: 'tgnewtable',
+ fires: 'AFTER'
+ });
+
+ mount(<SchemaView
+ formType='dialog'
+ schema={editSchemaObj}
+ getInitData={initData}
+ viewHelperProps={{
+ mode: 'edit',
+ }}
+ onSave={()=>{}}
+ onClose={()=>{}}
+ onHelp={()=>{}}
+ onEdit={()=>{}}
+ onDataChange={()=>{}}
+ confirmOnCloseReset={false}
+ hasSQL={false}
+ disableSqlHelp={false}
+ />);
+ });
+
+});
+
+
+describe('TriggerEventsSchema', ()=>{
+ let mount;
+ let schemaObj = new EventSchema(
+ {
+ nodeInfo: {
+ server: {user: {name:'postgres', id:0}, server_type: 'pg', version: 90400},
+ table: {is_partitioned: false}
+ }
+ }
+ );
+ 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('validate', ()=>{
+ let state = {};
+ let setError = jasmine.createSpy('setError');
+
+
+ state.tfunction = 'public';
+ 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.tfunction = 'public';
+ state.evnt_insert = true;
+ 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});
+ });*/
+
+});