mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-25 18:20:20 -06:00
Fixed some of the issues reported due to introduction of the custom hook 'useSchemaState'. #7776
This commit is contained in:
parent
55817f685f
commit
8cf316b853
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -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?') +
|
||||||
|
@ -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;
|
||||||
|
@ -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('');
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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'
|
||||||
|
@ -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.');
|
||||||
|
|
||||||
|
19
web/regression/javascript/schema_ui_files/utils.js
Normal file
19
web/regression/javascript/schema_ui_files/utils.js
Normal 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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user