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;
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;
}
state.only_table = false;
@ -304,4 +307,4 @@ export default class PublicationSchema extends BaseUISchema {
},
];
}
}
}

View File

@ -51,7 +51,7 @@ export default class DomainConstraintSchema extends BaseUISchema {
cell:'boolean', group: gettext('Definition'), min_version: 90200,
mode: ['properties', 'create', 'edit'],
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'),
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(
'Updating the package header definition may remove its existing body.'
) + '<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'),
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(
'Updating the package header definition may remove its existing body.'
) + '<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
* 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))
return options;

View File

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

View File

@ -38,11 +38,11 @@ export default class BaseUISchema {
/* The original data before any changes */
set origData(val) {
this._origData = val;
throw new Error('Property \'origData\' is readonly.');
}
get origData() {
return this._origData || {};
return this.state?.initData || {};
}
set state(state) {
@ -53,6 +53,14 @@ export default class BaseUISchema {
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.
* this._sessData is set by SchemaView directly. set sessData should not be

View File

@ -179,7 +179,7 @@ const LOADING_STATE = {
ERROR: 'Error'
};
class SchemaState extends DepListener {
export class SchemaState extends DepListener {
constructor(
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'
// callback, there is no need to validate the current data.
if(!state.isReady || !state.onDataChange) return;
if(!state.isReady) return;
if(
!validateSchema(schema, sessData, (path, message) => {
@ -317,12 +317,22 @@ class SchemaState extends DepListener {
})
) 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.
let dataDiff = getSchemaDataDiff(
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.
if(state.mode !== 'edit') {
@ -331,21 +341,19 @@ class SchemaState extends DepListener {
// Remove internal '__changeId' attribute.
delete dataDiff.__changeId;
// In case of 'non-edit' mode, changes are always there.
state.changes = dataDiff;
} else if (hasDataChanged) {
return dataDiff;
} else if (state.hasChanges) {
const idAttr = schema.idAttribute;
const idVal = state.initData[idAttr];
// Append 'idAttr' only if it actually exists
if (idVal) dataDiff[idAttr] = idVal;
state.changes = dataDiff;
} else {
state.changes = null;
return dataDiff;
}
state.data = sessData;
state.onDataChange(hasDataChanged, dataDiff);
return {};
}
get isNew() {
@ -467,7 +475,7 @@ export const useSchemaState = ({
});
});
});
}, [schemaState.__deferred__?.length]);
}, [sessData.__deferred__?.length]);
schemaState.reload = reload;
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 _ from 'lodash';
import {addNewDatagridRow, genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions';
import { initializeSchemaWithData } from './utils';
class MockSchema extends BaseUISchema {
get baseFields() {
@ -188,7 +189,7 @@ describe('ColumnSchema', ()=>{
state.attnum = 1;
state.attidentity = 'a';
state.colconstype = 'i';
schemaObj.origData = {attidentity:'a'};
initializeSchemaWithData(schemaObj, {attidentity:'a'});
schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('seqincrement', 'Increment value cannot be empty.');
@ -208,7 +209,7 @@ describe('ColumnSchema', ()=>{
state.attnum = null;
state.seqmin = null;
state.seqmax = null;
schemaObj.origData.attidentity = undefined;
initializeSchemaWithData(schemaObj, {attidentity: undefined});
expect(schemaObj.validate(state, setError)).toBe(false);
state.seqmin = 3;

View File

@ -11,6 +11,7 @@
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 {genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions';
import { initializeSchemaWithData } from './utils';
describe('PackageSchema', ()=>{
@ -49,9 +50,9 @@ describe('PackageSchema', ()=>{
pkgheadsrc: 'changed text'
};
packageSchemaObj.warningText = null;
packageSchemaObj._origData = {
oid: '123'
};
initializeSchemaWithData(packageSchemaObj, { oid: '123' });
let actionObj = {
oldState: {
pkgheadsrc: 'original text'
@ -69,9 +70,7 @@ describe('PackageSchema', ()=>{
pkgheadsrc: 'changed text'
};
packageSchemaObj.warningText = null;
packageSchemaObj._origData = {
oid: '123'
};
initializeSchemaWithData(packageSchemaObj, { oid: '123' });
let actionObj = {
oldState: {
pkgbodysrc: 'original text'

View File

@ -13,6 +13,7 @@ import _ from 'lodash';
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 {addNewDatagridRow, genericBeforeEach, getCreateView, getEditView, getPropertiesView} from '../genericFunctions';
import { initializeSchemaWithData } from './utils';
function getFieldDepChange(schema, id) {
return _.find(schema.fields, (f)=>f.id==id)?.depChange;
@ -160,9 +161,8 @@ describe('PartitionsSchema', ()=>{
state.is_sub_partitioned = false;
state.is_default = false;
schemaObj.top._sessData = {
partition_type: 'range',
};
initializeSchemaWithData(schemaObj.top, {partition_type: 'range'});
schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('values_from', 'For range partition From field cannot be empty.');
@ -170,11 +170,11 @@ describe('PartitionsSchema', ()=>{
schemaObj.validate(state, setError);
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);
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);
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;
}