Fixed some of the issues reported due to introduction of the custom hook 'useSchemaState'. #7776

This commit is contained in:
Ashesh Vashi 2024-08-19 09:53:00 +05:30 committed by GitHub
parent 55817f685f
commit 8cf316b853
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 88 additions and 36 deletions

View File

@ -207,7 +207,10 @@ export default class PublicationSchema extends BaseUISchema {
state.only_table = false; state.only_table = false;
return true; return true;
} }
if (!_.isUndefined(table) && table.length > 0 && !_.isEqual(this._origData.pubtable, state.pubtable)){ if (
!_.isUndefined(table) && table.length > 0 &&
!_.isEqual(this.origData.pubtable, state.pubtable)
){
return false; return false;
} }
state.only_table = false; state.only_table = false;

View File

@ -51,7 +51,7 @@ export default class DomainConstraintSchema extends BaseUISchema {
cell:'boolean', group: gettext('Definition'), min_version: 90200, cell:'boolean', group: gettext('Definition'), min_version: 90200,
mode: ['properties', 'create', 'edit'], mode: ['properties', 'create', 'edit'],
readonly: function(state) { readonly: function(state) {
return !obj.isNew(state) && obj._origData.convalidated; return !obj.isNew(state) && obj.origData.convalidated;
} }
} }
]; ];

View File

@ -100,7 +100,10 @@ export default class PackageSchema extends BaseUISchema {
group: gettext('Header'), group: gettext('Header'),
depChange: (state, source, topState, actionObj) => { depChange: (state, source, topState, actionObj) => {
if(packageSchemaObj._origData.oid && state.pkgheadsrc != actionObj.oldState.pkgheadsrc) { if(
packageSchemaObj.origData.oid &&
state.pkgheadsrc != actionObj.oldState.pkgheadsrc
) {
packageSchemaObj.warningText = gettext( packageSchemaObj.warningText = gettext(
'Updating the package header definition may remove its existing body.' 'Updating the package header definition may remove its existing body.'
) + '<br><br><b>' + gettext('Do you want to continue?') + ) + '<br><br><b>' + gettext('Do you want to continue?') +
@ -116,7 +119,10 @@ export default class PackageSchema extends BaseUISchema {
mode: ['properties', 'create', 'edit'], group: gettext('Body'), mode: ['properties', 'create', 'edit'], group: gettext('Body'),
depChange: (state, source, topState, actionObj) => { depChange: (state, source, topState, actionObj) => {
if(packageSchemaObj._origData.oid && state.pkgbodysrc != actionObj.oldState.pkgbodysrc) { if(
packageSchemaObj.origData.oid &&
state.pkgbodysrc != actionObj.oldState.pkgbodysrc
) {
packageSchemaObj.warningText = gettext( packageSchemaObj.warningText = gettext(
'Updating the package header definition may remove its existing body.' 'Updating the package header definition may remove its existing body.'
) + '<br><br><b>' + gettext('Do you want to continue?') + ) + '<br><br><b>' + gettext('Do you want to continue?') +

View File

@ -155,7 +155,9 @@ class IndexColumnSchema extends BaseUISchema {
* to access method selected by user if not selected * to access method selected by user if not selected
* send btree related op_class options * send btree related op_class options
*/ */
let amname = obj._top?._sessData ? obj._top?._sessData.amname : obj._top?._origData.amname; let amname = obj._top?._sessData ?
obj._top?._sessData.amname :
obj._top?.origData.amname;
if(_.isUndefined(amname)) if(_.isUndefined(amname))
return options; return options;

View File

@ -102,6 +102,12 @@ export default function SchemaDialogView({
updateSchemaState(schemaState); updateSchemaState(schemaState);
}, [sessData.__changeId]); }, [sessData.__changeId]);
useEffect(()=>{
if (!props.resetKey) return;
reset();
}, [props.resetKey]);
const onResetClick = () => { const onResetClick = () => {
const resetIt = () => { const resetIt = () => {
firstEleRef.current?.focus(); firstEleRef.current?.focus();
@ -151,14 +157,14 @@ export default function SchemaDialogView({
setLoaderText('Saving...'); setLoaderText('Saving...');
if (!schema.warningText) { if (!schema.warningText) {
save(schemaState.changes); save(schemaState.Changes(true));
return; return;
} }
Notifier.confirm( Notifier.confirm(
gettext('Warning'), gettext('Warning'),
schema.warningText, schema.warningText,
()=> { save(schemaState.changes); }, ()=> { save(schemaState.Changes(true)); },
() => { () => {
setSaving(false); setSaving(false);
setLoaderText(''); setLoaderText('');

View File

@ -38,11 +38,11 @@ export default class BaseUISchema {
/* The original data before any changes */ /* The original data before any changes */
set origData(val) { set origData(val) {
this._origData = val; throw new Error('Property \'origData\' is readonly.');
} }
get origData() { get origData() {
return this._origData || {}; return this.state?.initData || {};
} }
set state(state) { set state(state) {
@ -53,6 +53,14 @@ export default class BaseUISchema {
return this._state; return this._state;
} }
get _sessData() {
return this._state?.data;
}
set _sessData(val) {
throw new Error('Property _sessData is readonly.', val);
}
/* /*
* The session data, can be useful but setting this will not affect UI. * The session data, can be useful but setting this will not affect UI.
* this._sessData is set by SchemaView directly. set sessData should not be * this._sessData is set by SchemaView directly. set sessData should not be

View File

@ -179,7 +179,7 @@ const LOADING_STATE = {
ERROR: 'Error' ERROR: 'Error'
}; };
class SchemaState extends DepListener { export class SchemaState extends DepListener {
constructor( constructor(
schema, getInitData, immutableData, mode, keepCid, onDataChange schema, getInitData, immutableData, mode, keepCid, onDataChange
@ -309,7 +309,7 @@ class SchemaState extends DepListener {
// If schema does not have the data or does not have any 'onDataChange' // If schema does not have the data or does not have any 'onDataChange'
// callback, there is no need to validate the current data. // callback, there is no need to validate the current data.
if(!state.isReady || !state.onDataChange) return; if(!state.isReady) return;
if( if(
!validateSchema(schema, sessData, (path, message) => { !validateSchema(schema, sessData, (path, message) => {
@ -317,12 +317,22 @@ class SchemaState extends DepListener {
}) })
) state.setError({}); ) state.setError({});
state.data = sessData;
state.changes = state.Changes();
state.onDataChange && state.onDataChange(state.hasChanges, state.changes);
}
Changes(includeSkipChange=false) {
const state = this;
const sessData = this.data;
const schema = state.schema;
// Check if anything changed. // Check if anything changed.
let dataDiff = getSchemaDataDiff( let dataDiff = getSchemaDataDiff(
schema, state.initData, sessData, schema, state.initData, sessData,
state.mode, state.keepCid, false, false state.mode, state.keepCid, false, includeSkipChange
); );
const hasDataChanged = state.hasChanges = Object.keys(dataDiff).length > 0; state.hasChanges = Object.keys(dataDiff).length > 0;
// Inform the callbacks about change in the data. // Inform the callbacks about change in the data.
if(state.mode !== 'edit') { if(state.mode !== 'edit') {
@ -331,21 +341,19 @@ class SchemaState extends DepListener {
// Remove internal '__changeId' attribute. // Remove internal '__changeId' attribute.
delete dataDiff.__changeId; delete dataDiff.__changeId;
// In case of 'non-edit' mode, changes are always there. // In case of 'non-edit' mode, changes are always there.
state.changes = dataDiff; return dataDiff;
} else if (hasDataChanged) { } else if (state.hasChanges) {
const idAttr = schema.idAttribute; const idAttr = schema.idAttribute;
const idVal = state.initData[idAttr]; const idVal = state.initData[idAttr];
// Append 'idAttr' only if it actually exists // Append 'idAttr' only if it actually exists
if (idVal) dataDiff[idAttr] = idVal; if (idVal) dataDiff[idAttr] = idVal;
state.changes = dataDiff;
} else { return dataDiff;
state.changes = null;
} }
state.data = sessData; return {};
state.onDataChange(hasDataChanged, dataDiff);
} }
get isNew() { get isNew() {
@ -467,7 +475,7 @@ export const useSchemaState = ({
}); });
}); });
}); });
}, [schemaState.__deferred__?.length]); }, [sessData.__deferred__?.length]);
schemaState.reload = reload; schemaState.reload = reload;
schemaState.reset = resetData; schemaState.reset = resetData;

View File

@ -12,6 +12,7 @@ import ColumnSchema from '../../../pgadmin/browser/server_groups/servers/databas
import BaseUISchema from '../../../pgadmin/static/js/SchemaView/base_schema.ui'; import BaseUISchema from '../../../pgadmin/static/js/SchemaView/base_schema.ui';
import _ from 'lodash'; import _ from 'lodash';
import {addNewDatagridRow, genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions'; import {addNewDatagridRow, genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions';
import { initializeSchemaWithData } from './utils';
class MockSchema extends BaseUISchema { class MockSchema extends BaseUISchema {
get baseFields() { get baseFields() {
@ -188,7 +189,7 @@ describe('ColumnSchema', ()=>{
state.attnum = 1; state.attnum = 1;
state.attidentity = 'a'; state.attidentity = 'a';
state.colconstype = 'i'; state.colconstype = 'i';
schemaObj.origData = {attidentity:'a'}; initializeSchemaWithData(schemaObj, {attidentity:'a'});
schemaObj.validate(state, setError); schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('seqincrement', 'Increment value cannot be empty.'); expect(setError).toHaveBeenCalledWith('seqincrement', 'Increment value cannot be empty.');
@ -208,7 +209,7 @@ describe('ColumnSchema', ()=>{
state.attnum = null; state.attnum = null;
state.seqmin = null; state.seqmin = null;
state.seqmax = null; state.seqmax = null;
schemaObj.origData.attidentity = undefined; initializeSchemaWithData(schemaObj, {attidentity: undefined});
expect(schemaObj.validate(state, setError)).toBe(false); expect(schemaObj.validate(state, setError)).toBe(false);
state.seqmin = 3; state.seqmin = 3;

View File

@ -11,6 +11,7 @@
import { getNodePrivilegeRoleSchema } from '../../../pgadmin/browser/server_groups/servers/static/js/privilege.ui'; import { getNodePrivilegeRoleSchema } from '../../../pgadmin/browser/server_groups/servers/static/js/privilege.ui';
import PackageSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.ui'; import PackageSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.ui';
import {genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions'; import {genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions';
import { initializeSchemaWithData } from './utils';
describe('PackageSchema', ()=>{ describe('PackageSchema', ()=>{
@ -49,9 +50,9 @@ describe('PackageSchema', ()=>{
pkgheadsrc: 'changed text' pkgheadsrc: 'changed text'
}; };
packageSchemaObj.warningText = null; packageSchemaObj.warningText = null;
packageSchemaObj._origData = {
oid: '123' initializeSchemaWithData(packageSchemaObj, { oid: '123' });
};
let actionObj = { let actionObj = {
oldState: { oldState: {
pkgheadsrc: 'original text' pkgheadsrc: 'original text'
@ -69,9 +70,7 @@ describe('PackageSchema', ()=>{
pkgheadsrc: 'changed text' pkgheadsrc: 'changed text'
}; };
packageSchemaObj.warningText = null; packageSchemaObj.warningText = null;
packageSchemaObj._origData = { initializeSchemaWithData(packageSchemaObj, { oid: '123' });
oid: '123'
};
let actionObj = { let actionObj = {
oldState: { oldState: {
pkgbodysrc: 'original text' pkgbodysrc: 'original text'

View File

@ -13,6 +13,7 @@ import _ from 'lodash';
import * as nodeAjax from '../../../pgadmin/browser/static/js/node_ajax'; import * as nodeAjax from '../../../pgadmin/browser/static/js/node_ajax';
import { PartitionKeysSchema, PartitionsSchema } from '../../../pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/partition.utils.ui'; import { PartitionKeysSchema, PartitionsSchema } from '../../../pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/partition.utils.ui';
import {addNewDatagridRow, genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions'; import {addNewDatagridRow, genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions';
import { initializeSchemaWithData } from './utils';
function getFieldDepChange(schema, id) { function getFieldDepChange(schema, id) {
return _.find(schema.fields, (f)=>f.id==id)?.depChange; return _.find(schema.fields, (f)=>f.id==id)?.depChange;
@ -160,9 +161,8 @@ describe('PartitionsSchema', ()=>{
state.is_sub_partitioned = false; state.is_sub_partitioned = false;
state.is_default = false; state.is_default = false;
schemaObj.top._sessData = { initializeSchemaWithData(schemaObj.top, {partition_type: 'range'});
partition_type: 'range',
};
schemaObj.validate(state, setError); schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('values_from', 'For range partition From field cannot be empty.'); expect(setError).toHaveBeenCalledWith('values_from', 'For range partition From field cannot be empty.');
@ -170,11 +170,11 @@ describe('PartitionsSchema', ()=>{
schemaObj.validate(state, setError); schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('values_to', 'For range partition To field cannot be empty.'); expect(setError).toHaveBeenCalledWith('values_to', 'For range partition To field cannot be empty.');
schemaObj.top._sessData.partition_type = 'list'; initializeSchemaWithData(schemaObj.top, {partition_type: 'list'});
schemaObj.validate(state, setError); schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('values_in', 'For list partition In field cannot be empty.'); expect(setError).toHaveBeenCalledWith('values_in', 'For list partition In field cannot be empty.');
schemaObj.top._sessData.partition_type = 'hash'; initializeSchemaWithData(schemaObj.top, {partition_type: 'hash'});
schemaObj.validate(state, setError); schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('values_modulus', 'For hash partition Modulus field cannot be empty.'); expect(setError).toHaveBeenCalledWith('values_modulus', 'For hash partition Modulus field cannot be empty.');

View File

@ -0,0 +1,19 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import { SchemaState } from '../../../pgadmin/static/js/SchemaView/useSchemaState';
export function initializeSchemaWithData(schema, data) {
const state = schema.state = new SchemaState(
schema, null, null, 'create', false, null
);
state.initData = data;
state.data = data;
}