diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.js index 409a01fcd..975239eb2 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.js @@ -7,6 +7,9 @@ // ////////////////////////////////////////////////////////////// +import CollationSchema from './collation.ui'; +import { getNodeAjaxOptions, getNodeListByName } from '../../../../../../../static/js/node_ajax'; + define('pgadmin.node.collation', [ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'sources/pgadmin', 'pgadmin.browser', @@ -68,14 +71,6 @@ define('pgadmin.node.collation', [ }, model: pgAdmin.Browser.Node.Model.extend({ idAttribute: 'oid', - defaults: { - name: undefined, - oid: undefined, - owner: undefined, - lc_type: undefined, - lc_collate: undefined, - description: undefined, - }, // Default values! initialize: function(attrs, args) { @@ -103,136 +98,29 @@ define('pgadmin.node.collation', [ type: 'text', mode: ['properties', 'create', 'edit'], disabled: 'inSchema', control: 'node-list-by-name', node: 'role', - },{ - id: 'schema', label: gettext('Schema'), cell: 'string', - type: 'text', mode: ['create', 'edit'], node: 'schema', - disabled: 'inSchema', filter: function(d) { - // If schema name start with pg_* then we need to exclude them - if(d && d.label.match(/^pg_/)) - { - return false; - } - return true; - }, control: 'node-list-by-name', - cache_node: 'database', cached_level: 'database', - },{ - id: 'copy_collation', label: gettext('Copy collation'), cell: 'string', - control: 'node-ajax-options', - type: 'text', mode: ['create', 'edit'], group: gettext('Definition'), - url: 'get_collations', disabled: 'inSchemaWithModelCheck', - readonly: function(m) {return !m.isNew;}, - deps: ['locale', 'lc_collate', 'lc_type'], - },{ - id: 'locale', label: gettext('Locale'), cell: 'string', - type: 'text', mode: ['create', 'edit'], group: gettext('Definition'), - disabled: 'inSchemaWithModelCheck', readonly: function(m) {return !m.isNew;}, - deps: ['lc_collate', 'lc_type', 'copy_collation'], - },{ - id: 'lc_collate', label: gettext('LC_COLLATE'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], group: gettext('Definition'), - deps: ['locale', 'copy_collation'], disabled: 'inSchemaWithModelCheck', - readonly: function(m) {return !m.isNew;}, - },{ - id: 'lc_type', label: gettext('LC_TYPE'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], group: gettext('Definition'), - disabled: 'inSchemaWithModelCheck', readonly: function(m) {return !m.isNew;}, - deps: ['locale', 'copy_collation'], - },{ - id: 'is_sys_obj', label: gettext('System collation?'), - cell:'boolean', type: 'switch', mode: ['properties'], },{ id: 'description', label: gettext('Comment'), cell: 'string', type: 'multiline', mode: ['properties', 'create', 'edit'], disabled: 'inSchema', - }, + } ], - validate: function() { - var err = {}, - msg = undefined, - changedAttrs = this.changed, - locale_flag = false, - lc_type_flag = false, - lc_coll_flag = false, - copy_coll_flag = false, - data = this.toJSON(); - - this.errorModel.clear(); - - if (_.has(changedAttrs,data.name) && _.isUndefined(this.get('name')) - || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Name cannot be empty.'); - this.errorModel.set('name', msg); - } - if (_.has(changedAttrs,data.locale) && (_.isUndefined(this.get('locale')) - || String(this.get('locale')).replace(/^\s+|\s+$/g, '') == '')) { - locale_flag = true; - } - if (_.has(changedAttrs,data.lc_collate) && (_.isUndefined(this.get('lc_collate')) - || String(this.get('lc_collate')).replace(/^\s+|\s+$/g, '') == '')) { - lc_coll_flag = true; - } - if (_.has(changedAttrs,data.lc_type) && (_.isUndefined(this.get('lc_type')) - || String(this.get('lc_type')).replace(/^\s+|\s+$/g, '') == '')) { - lc_type_flag = true; - } - if (_.has(changedAttrs,data.copy_collation) && (_.isUndefined(this.get('copy_collation')) - || String(this.get('copy_collation')).replace(/^\s+|\s+$/g, '') == '')) { - copy_coll_flag = true; - } - if (locale_flag && (lc_coll_flag || lc_type_flag) && copy_coll_flag) { - msg = gettext('Definition incomplete. Please provide Locale OR Copy Collation OR LC_TYPE/LC_COLLATE.'); - err['locale'] = msg; - } - return null; - }, - // We will disable everything if we are under catalog node - inSchema: function() { - if(this.node_info && 'catalog' in this.node_info) - { - return true; - } - return false; - }, - // We will check if we are under schema node & in 'create' mode - inSchemaWithModelCheck: function(m) { - if(this.node_info && 'schema' in this.node_info) - { - // Enable copy_collation only if locale & lc_* is not provided - if (m.isNew() && this.name == 'copy_collation') - { - if(m.get('locale')) - return true; - if(m.get('lc_collate') || m.get('lc_type')) - return true; - return false; - } - - // Enable lc_* only if copy_collation & locale is not provided - if (m.isNew() && (this.name == 'lc_collate' || this.name == 'lc_type')) - { - if(m.get('locale')) - return true; - if(m.get('copy_collation')) - return true; - return false; - } - - // Enable localy only if lc_* & copy_collation is not provided - if (m.isNew() && this.name == 'locale') - { - if(m.get('lc_collate') || m.get('lc_type')) - return true; - if(m.get('copy_collation')) - return true; - return false; - } - } - return true; - }, }), + getSchema: (treeNodeInfo, itemNodeData)=>{ + let nodeObj = pgAdmin.Browser.Nodes['collation']; + let schema = new CollationSchema( + { + rolesList: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData, {cacheLevel: 'server'}), + schemaList: ()=>getNodeListByName('schema', treeNodeInfo, itemNodeData, {cacheLevel: 'database'}), + collationsList: ()=>getNodeAjaxOptions('get_collations', nodeObj, treeNodeInfo, itemNodeData, {cacheLevel: 'server'}) + }, + { + owner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name, + schema: ('schema' in treeNodeInfo)? treeNodeInfo.schema.label : '' + } + ); + return schema; + } }); - } - return pgBrowser.Nodes['collation']; }); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.ui.js new file mode 100644 index 000000000..34ce98f74 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.ui.js @@ -0,0 +1,171 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2021, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// + +import BaseUISchema from 'sources/SchemaView/base_schema.ui'; +import gettext from 'sources/gettext'; +import { isEmptyString } from 'sources/validators'; + +export default class CollationSchema extends BaseUISchema { + constructor(fieldOptions = {},initValues) { + super({ + name: undefined, + oid: undefined, + owner: undefined, + copy_collation: null, + locale: undefined, + lc_type: undefined, + lc_collate: undefined, + description: undefined, + schema: null, + ...initValues + }); + this.schemaList = fieldOptions.schemaList; + this.ownerList = fieldOptions.rolesList; + this.collationsList = fieldOptions.collationsList; + } + + get idAttribute() { + return 'oid'; + } + + get baseFields() { + let obj = this; + return [ + { + id: 'name', label: gettext('Name'), + type: 'text', mode: ['properties', 'create', 'edit'], + }, + { + id: 'oid', label: gettext('OID'), + type: 'text', mode: ['properties'], + }, + { + id: 'owner', label: gettext('Owner'), + type: 'select', mode: ['properties', 'create', 'edit'], + options: obj.ownerList + }, + { + id: 'schema', label: gettext('Schema'), + mode: ['create', 'edit'], node: 'schema', + type: () => { + return { + type: 'select', + options: obj.schemaList, + controlProps: { + filter: (options) => { + let res = []; + options.forEach((d) => { + if (!(d && d.label.match(/^pg_/))) + res.push(d); + }); + return res; + } + } + }; + } + }, + { + id: 'copy_collation', label: gettext('Copy collation'), + type: 'select', mode: ['create', 'edit'], group: gettext('Definition'), + readonly: function (state) { return !obj.isNew(state); }, + options: obj.collationsList, + disabled: function (state) { + // Enable copy_collation only if locale & lc_* is not provided + if (state.locale) + return true; + if (state.lc_collate || state.lc_type) + return true; + return false; + }, + deps: ['locale', 'lc_collate', 'lc_type'], + }, + { + id: 'locale', label: gettext('Locale'), + type: 'text', mode: ['create', 'edit'], group: gettext('Definition'), + readonly: function (state) { return !obj.isNew(state); }, + deps: ['lc_collate', 'lc_type', 'copy_collation'], + disabled: function (state) { + // Enable localy only if lc_* & copy_collation is not provided + if (state.lc_collate || state.lc_type) + return true; + if (state.copy_collation) + return true; + return false; + } + }, + { + id: 'lc_collate', label: gettext('LC_COLLATE'), + type: 'text', mode: ['properties', 'create', 'edit'], group: gettext('Definition'), + readonly: function (state) { return !obj.isNew(state); }, + disabled: obj.disableFields, + deps: ['locale', 'copy_collation'], + }, + { + id: 'lc_type', label: gettext('LC_TYPE'), + type: 'text', mode: ['properties', 'create', 'edit'], group: gettext('Definition'), + readonly: function (state) { return !obj.isNew(state); }, + disabled: obj.disableFields, + deps: ['locale', 'copy_collation'], + }, + { + id: 'is_sys_obj', label: gettext('System collation?'), + cell: 'boolean', type: 'switch', mode: ['properties'], + }, + { + id: 'description', label: gettext('Comment'), + type: 'multiline', mode: ['properties', 'create', 'edit'], + } + ]; + } + + disableFields(state) { + // Enable lc_* only if copy_collation & locale is not provided + if (state.locale || state.copy_collation) { + if (state.locale) + return true; + if (state.copy_collation) + return true; + } + return false; + } + + validate(state, setError) { + let errmsg = null, + locale_flag = false, + lc_type_flag = false, + lc_coll_flag = false, + copy_coll_flag = false; + + if (isEmptyString(state.name)) { + errmsg = gettext('Name cannot be empty.'); + setError('name', errmsg); + return true; + } + if (isEmptyString(state.locale)) { + locale_flag = true; + } + if (isEmptyString(state.copy_collation)) { + copy_coll_flag = true; + } + if (isEmptyString(state.lc_collate)) { + lc_coll_flag = true; + } + if (isEmptyString(state.lc_type)) { + lc_type_flag = true; + } + if (locale_flag && (lc_coll_flag || lc_type_flag) && copy_coll_flag) { + errmsg = gettext('Definition incomplete. Please provide Locale OR Copy Collation OR LC_TYPE/LC_COLLATE.'); + setError('copy_collation', errmsg); + return true; + } + return null; + } + +} + diff --git a/web/regression/javascript/schema_ui_files/collation.ui.spec.js b/web/regression/javascript/schema_ui_files/collation.ui.spec.js new file mode 100644 index 000000000..3bec82d0c --- /dev/null +++ b/web/regression/javascript/schema_ui_files/collation.ui.spec.js @@ -0,0 +1,141 @@ +///////////////////////////////////////////////////////////// +// +// 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'; +// web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.ui.js +import CollationSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.ui'; + + +describe('CollationsSchema', () => { + let mount; + let schemaObj = new CollationSchema( + { + rolesList: () => [], + schemaList: () => [], + collationsList: () => [] + }, + { + owner: 'postgres', + schema: '' + } + ); + 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; + state.locale = 'locale'; + schemaObj.validate(state, setError); + expect(setError).toHaveBeenCalledWith('name', 'Name cannot be empty.'); + + state.name = 'test'; + state.copy_collation = null; + state.lc_type = null; + state.lc_collate = null; + state.locale = null; + schemaObj.validate(state, setError); + expect(setError).toHaveBeenCalledWith('copy_collation', 'Definition incomplete. Please provide Locale OR Copy Collation OR LC_TYPE/LC_COLLATE.'); + }); + + it('disableFields',() => { + let state = {}; + + state.name = 'test'; + state.locale = 'locale'; + expect(schemaObj.disableFields(state)).toBeTrue(); + + state.name = 'test'; + state.copy_collation = 'copy_collation'; + state.locale = null; + expect(schemaObj.disableFields(state)).toBeTrue(); + + state.name = 'test'; + state.copy_collation = null; + state.locale = null; + expect(schemaObj.disableFields(state)).toBeFalse(); + + }); +}); +