From 5a279611025087f28913d18ea8cec31e47d02816 Mon Sep 17 00:00:00 2001 From: Yogesh Mahajan Date: Tue, 6 Jul 2021 14:37:51 +0530 Subject: [PATCH] Port Extension node to react. Fixes #6582 --- .../extensions/static/js/extension.js | 24 ++- .../extensions/static/js/extension.ui.js | 174 ++++++++++++++++++ .../schema_ui_files/extension.ui.spec.js | 107 +++++++++++ 3 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui.js create mode 100644 web/regression/javascript/schema_ui_files/extension.ui.spec.js diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js index df58cbc86..07f8ea2f6 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js +++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js @@ -7,6 +7,10 @@ // ////////////////////////////////////////////////////////////// + +import { getNodeAjaxOptions,getNodeListByName } from '../../../../../../static/js/node_ajax'; +import ExtensionsSchema from './extension.ui'; + define('pgadmin.node.extension', [ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'sources/pgadmin', 'pgadmin.browser', @@ -216,7 +220,6 @@ define('pgadmin.node.extension', [ var res = [], control = cell || this, extension = control.model.get('name'); - _.each(data, function(dt) { if(dt.name == extension) { if(dt.version && _.isArray(dt.version)) { @@ -258,6 +261,25 @@ define('pgadmin.node.extension', [ return null; }, }), + getSchema: (treeNodeInfo, itemNodeData)=>{ + let nodeObj = pgAdmin.Browser.Nodes['extension']; + let schema = new ExtensionsSchema( + { + extensionsList:()=>getNodeAjaxOptions('avails', nodeObj, treeNodeInfo, itemNodeData, { cacheLevel: 'server'}, + (data)=>{ + let res = []; + if (data && _.isArray(data)) { + _.each(data, function(d) { + res.push({label: d.name, value: d.name, data:d}); + }); + } + return res; + }), + schemaList:()=>getNodeListByName('schema', treeNodeInfo, itemNodeData) + } + ); + return schema; + } }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui.js b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui.js new file mode 100644 index 000000000..e42f622d9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui.js @@ -0,0 +1,174 @@ +///////////////////////////////////////////////////////////// +// +// 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 default class ExtensionsSchema extends BaseUISchema { + constructor(fieldOptions = {}) { + super({ + name: null, + oid: undefined, + version: '', + schema: '', + relocatable: false, + is_sys_obj: false, + comment: null, + }); + fieldOptions = { + extensionsList: [], + schemaList: [], + ...fieldOptions, + }; + this.extensionsList = fieldOptions.extensionsList; + this.schemaList = fieldOptions.schemaList; + } + + get idAttribute() { + return 'oid'; + } + + get baseFields() { + let obj = this; + return [ + { + id: 'name', label: gettext('Name'), + mode: ['properties', 'create', 'edit'], + editable: false, + readonly: function (state) { + return !obj.isNew(state); + }, + type: (state) => { + return { + type: 'select', + options: obj.extensionsList, + optionsLoaded: (options) => { obj.extensionData = options; }, + controlProps: { + allowClear: false, + filter: (options) => { + let res = []; + if (state && obj.isNew(state)) { + options.forEach((option) => { + if (option.data['installed_version'] === null) { + res.push({ label: option.label, value: option.value }); + } + }); + } else { + res = options; + } + return res; + } + } + }; + }, + depChange: (state) => { + let extensionData = obj.extensionData; + if (state && obj.isNew(state)) { + extensionData.forEach((option) => { + if (state.name == option.data['name']) { + let dt = option.data; + state.version = ''; + state.relocatable = ( + (!_.isNull(dt.relocatable[0]) && + !_.isUndefined(dt.relocatable[0])) ? dt.relocatable[0] : '' + ); + } + }); + } + } + }, + { + id: 'oid', label: gettext('OID'), type: 'text', + mode: ['properties'], + }, + { + id: 'schema', label: gettext('Schema'), type: 'select', + mode: ['properties', 'create', 'edit'], group: gettext('Definition'), + first_empty: true, deps: ['name'], + controlProps: { allowClear: false }, editable: false, + options: this.schemaList, + disabled: function (state) { + /* + * enable or disable schema field if model's relocatable + * attribute is True or False + */ + return (!state.relocatable); + }, + }, + { + id: 'relocatable', label: gettext('Relocatable?'), cell: 'switch', + group: gettext('Definition'), type: 'switch', mode: ['properties'], + deps: ['name'], + }, + { + id: 'version', label: gettext('Version'), + mode: ['properties', 'create', 'edit'], group: gettext('Definition'), + first_empty: true, + deps: ['name'], + type: (state) => { + return { + type: 'select', + options: this.extensionsList, + controlProps: { + allowClear: false, + filter: (options) => { + let res = []; + if (state) { + if (state.name) { + options.forEach((option) => { + if (state.name == option.data['name']) { + let dt = option.data; + if (dt.version && _.isArray(dt.version)) { + _.each(dt.version, function (v) { + res.push({ label: v, value: v }); + }); + } + } + }); + } + } else { + options.forEach((option) => { + let dt = option.data; + if (dt.version && _.isArray(dt.version)) { + _.each(dt.version, function (v) { + res.push({ label: v, value: v }); + }); + } + }); + } + return res; + } + } + }; + }, + }, { + id: 'is_sys_obj', label: gettext('System extension?'), + cell: 'boolean', type: 'switch', mode: ['properties'], + }, { + id: 'comment', label: gettext('Comment'), cell: 'string', + type: 'multiline', readonly: true, + }, + ]; + } + + validate(state, setError) { + let errmsg = null; + if (isEmptyString(state.name)) { + errmsg = gettext('Name cannot be empty.'); + setError('name', errmsg); + return true; + } else { + errmsg = null; + setError('name', errmsg); + } + return false; + } + +} \ No newline at end of file diff --git a/web/regression/javascript/schema_ui_files/extension.ui.spec.js b/web/regression/javascript/schema_ui_files/extension.ui.spec.js new file mode 100644 index 000000000..07bed7dd7 --- /dev/null +++ b/web/regression/javascript/schema_ui_files/extension.ui.spec.js @@ -0,0 +1,107 @@ +///////////////////////////////////////////////////////////// +// +// 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 ExtensionsSchema from '../../../pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.ui'; + + +describe('ExtensionSchema', ()=>{ + let mount; + let schemaObj = new ExtensionsSchema( + { + extensionsList: ()=>[], + schemaList: ()=>[], + } + ); + 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.name = null; + schemaObj.validate(state, setError); + expect(setError).toHaveBeenCalledWith('name', 'Name cannot be empty.'); + }); +}); +