Fixed following issues after React Porting:

1. Unique constraint should not allow changing values for deferrable, deferred, included columns.
2. Primary keys should not allow changing values for deferrable, deferred, included columns.
3. Foreign keys should not allow changing match type. The referenced table name is empty.
4. Exclude - Column/Expression has incorrect values.
5. Save should not be enabled when Custom auto-vacuum is enabled but none of the parameters are edited.

Fixes #6777
This commit is contained in:
Aditya Toshniwal 2021-09-23 14:46:10 +05:30 committed by Akshay Joshi
parent 15a494c189
commit 9179b7464b
13 changed files with 79 additions and 61 deletions

View File

@ -154,12 +154,12 @@ export default class ColumnSchema extends BaseUISchema {
id: 'name', label: gettext('Name'), cell: 'text',
type: 'text', readonly: obj.inSchemaWithColumnCheck,
editable: this.editableCheckForTable, noEmpty: true,
minWidth: 115,
width: 115,
},{
// Need to show this field only when creating new table
// [in SubNode control]
id: 'is_primary_key', label: gettext('Primary key?'),
cell: 'switch', type: 'switch', minWidth: 100, deps:['name'],
cell: 'switch', type: 'switch', width: 100, disableResizing: true, deps:['name'],
visible: ()=>{
return obj.top?.nodeInfo && _.isUndefined(
obj.top.nodeInfo['table'] || obj.top.nodeInfo['view'] ||
@ -226,7 +226,7 @@ export default class ColumnSchema extends BaseUISchema {
type: 'text', disabled: this.inCatalog, mode: ['properties'],
},{
id: 'cltype', label: gettext('Data type'),
readonly: obj.inSchemaWithColumnCheck, minWidth: 150,
readonly: obj.inSchemaWithColumnCheck, width: 150,
group: gettext('Definition'), noEmpty: true,
editable: this.editableCheckForTable,
options: this.cltypeOptions, optionsLoaded: (options)=>{obj.datatypes = options;},
@ -276,7 +276,7 @@ export default class ColumnSchema extends BaseUISchema {
},
},{
id: 'attlen', label: gettext('Length/Precision'), cell: 'int',
deps: ['cltype'], type: 'int', group: gettext('Definition'), width: 120, minWidth: 120,
deps: ['cltype'], type: 'int', group: gettext('Definition'), width: 120, disableResizing: true,
depChange: (state)=>{
let range = this.attlenRange(state);
if(range) {
@ -300,7 +300,7 @@ export default class ColumnSchema extends BaseUISchema {
return Boolean(obj.attlenRange(state));
},
},{
id: 'attprecision', label: gettext('Scale'), cell: 'int', minWidth: 60,
id: 'attprecision', label: gettext('Scale'), cell: 'int', width: 60, disableResizing: true,
deps: ['cltype'], type: 'int', group: gettext('Definition'),
depChange: (state)=>{
let range = this.attprecisionRange(state);
@ -386,7 +386,7 @@ export default class ColumnSchema extends BaseUISchema {
},
},{
id: 'attnotnull', label: gettext('Not NULL?'), cell: 'switch',
type: 'switch', minWidth: 80,
type: 'switch', width: 80, disableResizing: true,
group: gettext('Constraints'), editable: this.editableCheckForTable,
deps: ['colconstype'],
readonly: (state) => {

View File

@ -128,7 +128,8 @@ class ExclusionColumnSchema extends BaseUISchema {
get baseFields() {
let obj = this;
return [{
id: 'is_exp', label: '', type:'', editable: false, minWidth: 20,
id: 'is_exp', label: '', type:'', editable: false, width: 20,
disableResizing: true,
controlProps: {
formatter: {
fromRaw: function (rawValue) {
@ -138,11 +139,11 @@ class ExclusionColumnSchema extends BaseUISchema {
}, visible: false,
},{
id: 'column', label: gettext('Col/Exp'), type:'', editable: false,
cell:'', minWidth: 125,
cell:'', width: 125,
},{
id: 'oper_class', label: gettext('Operator class'), cell:'select',
options: this.operClassOptions,
minWidth: 185,
width: 185,
editable: obj.isEditable,
controlProps: {
allowClear: true, placeholder: gettext('Select the operator class'),
@ -153,7 +154,7 @@ class ExclusionColumnSchema extends BaseUISchema {
{label: 'ASC', value: true},
{label: 'DESC', value: false},
],
editable: obj.isEditable, minWidth: 110,
editable: obj.isEditable, width: 110, disableResizing: true,
controlProps: {
allowClear: false,
},
@ -163,10 +164,10 @@ class ExclusionColumnSchema extends BaseUISchema {
{label: 'FIRST', value: true},
{label: 'LAST', value: false},
], controlProps: {allowClear: false},
editable: obj.isEditable, minWidth: 110,
editable: obj.isEditable, width: 110, disableResizing: true,
},{
id: 'operator', label: gettext('Operator'), type: 'select',
minWidth: 95,
width: 95,
editable: function() {
return obj.isNewExCons;
},
@ -353,20 +354,11 @@ export default class ExclusionConstraintSchema extends BaseUISchema {
controlProps: {
formatter: {
fromRaw: (rawValue)=>{
var cols = [],
remoteCols = [];
if (rawValue?.length > 0) {
rawValue.forEach((col)=>{
cols.push(col.local_column);
remoteCols.push(col.referenced);
});
return '('+cols.join(', ')+') -> ('+ remoteCols.join(', ')+')';
}
return '';
return _.map(rawValue || [], 'column').join(', ');
},
}
},
minWidth: 245,
width: 245,
}),
deps: ()=>{
let ret = [];

View File

@ -282,14 +282,20 @@ export default class ForeignKeySchema extends BaseUISchema {
readonly: this.isReadonly,
},{
id: 'references_table_name', label: gettext('Referenced Table'),
type: 'text', group: gettext('Columns'), editable: false, visible:false,
cell: '', deps: ['columns'],
depChange: (state)=>{
if(state.columns?.length > 0) {
return {references_table_name: _.join(_.map(state.columns, 'references_table_name'), ',')};
type: 'text', group: gettext('Columns'), editable: false, visible:false, deps: ['columns'],
cell: (state)=>({
cell: '',
controlProps: {
formatter: {
fromRaw: ()=>{
if(state.columns?.length > 0) {
return _.join(_.map(state.columns, 'references_table_name'), ',');
}
return '';
}
}
}
return {references_table_name: undefined};
}
}),
},{
id: 'columns', label: gettext('Columns'),
group: gettext('Columns'), type: 'collection',

View File

@ -156,8 +156,8 @@ export default class PrimaryKeySchema extends BaseUISchema {
return false;
},
deps: ['index'],
readonly: function() {
if(!obj.isNew()) {
readonly: function(state) {
if(!obj.isNew(state)) {
return true;
}
},
@ -223,8 +223,8 @@ export default class PrimaryKeySchema extends BaseUISchema {
},{
id: 'condeferrable', label: gettext('Deferrable?'),
type: 'switch', group: gettext('Definition'), deps: ['index'],
readonly: function() {
if(!obj.isNew()) {
readonly: function(state) {
if(!obj.isNew(state)) {
return true;
}
return false;
@ -244,18 +244,20 @@ export default class PrimaryKeySchema extends BaseUISchema {
id: 'condeferred', label: gettext('Deferred?'),
type: 'switch', group: gettext('Definition'),
deps: ['condeferrable'],
readonly: function() {
if(!obj.isNew()) {
readonly: function(state) {
if(!obj.isNew(state)) {
return true;
}
return false;
},
disabled: function(state) {
// Disable if index is selected.
return !(_.isUndefined(state.index) || state.index == '');
return !(_.isUndefined(state.index) || state.index == '') || !state.condeferrable;
},
depChange: (state)=>{
if(_.isUndefined(state.index) || state.index == '') {
if(!state.condeferrable) {
return {condeferred: false};
} else if(_.isUndefined(state.index) || state.index == '') {
return {};
} else {
return {condeferred: false};

View File

@ -158,8 +158,8 @@ export default class UniqueConstraintSchema extends BaseUISchema {
return false;
},
deps: ['index'],
readonly: function() {
if(!obj.isNew()) {
readonly: function(state) {
if(!obj.isNew(state)) {
return true;
}
},
@ -225,8 +225,8 @@ export default class UniqueConstraintSchema extends BaseUISchema {
},{
id: 'condeferrable', label: gettext('Deferrable?'),
type: 'switch', group: gettext('Definition'), deps: ['index'],
readonly: function() {
if(!obj.isNew()) {
readonly: function(state) {
if(!obj.isNew(state)) {
return true;
}
return false;
@ -246,18 +246,20 @@ export default class UniqueConstraintSchema extends BaseUISchema {
id: 'condeferred', label: gettext('Deferred?'),
type: 'switch', group: gettext('Definition'),
deps: ['condeferrable'],
readonly: function() {
if(!obj.isNew()) {
readonly: function(state) {
if(!obj.isNew(state)) {
return true;
}
return false;
},
disabled: function(state) {
// Disable if index is selected.
return !(_.isUndefined(state.index) || state.index == '');
return !(_.isUndefined(state.index) || state.index == '') || !state.condeferrable;
},
depChange: (state)=>{
if(_.isUndefined(state.index) || state.index == '') {
if(!state.condeferrable) {
return {condeferred: false};
} else if(_.isUndefined(state.index) || state.index == '') {
return {};
} else {
return {condeferred: false};

View File

@ -64,7 +64,7 @@ export default class VacuumSettingsSchema extends BaseUISchema {
var obj = this;
return [{
id: 'autovacuum_custom', label: gettext('Custom auto-vacuum?'),
group: gettext('Table'), mode: ['edit', 'create'],
group: gettext('Table'), mode: ['edit', 'create'], skipChange: true,
type: 'switch', disabled: function(state) {
if(state.is_partitioned) {
return true;

View File

@ -134,7 +134,7 @@ function DataTableHeader({headerGroups}) {
: ''}
</span>
</div>
{column.resizable &&
{!column.disableResizing &&
<div
{...column.getResizerProps()}
className={classes.resizer}
@ -328,16 +328,26 @@ export default function DataGridView({
}
return 0;
}).map((field)=>{
let widthParms = {};
if(field.width) {
widthParms.width = field.width;
widthParms.minWidth = field.width;
}
if(field.minWidth) {
widthParms.minWidth = field.minWidth;
}
if(field.maxWidth) {
widthParms.maxWidth = field.maxWidth;
}
widthParms.disableResizing = Boolean(field.disableResizing);
let colInfo = {
Header: field.label||<>&nbsp;</>,
accessor: field.id,
field: field,
resizable: true,
disableResizing: false,
sortable: true,
...(field.minWidth ? {minWidth: field.minWidth} : {}),
...(field.width ? {width: field.width} : {}),
...(field.maxWidth ? {maxWidth: field.maxWidth} : {}),
...(field.disableResizing ? {disableResizing: field.disableResizing} : {}),
...widthParms,
Cell: ({value, row, ...other}) => {
/* Make sure to take the latest field info from schema */
field = _.find(schemaRef.current.fields, (f)=>f.id==field.id) || field;

View File

@ -125,11 +125,11 @@ export function getFieldMetaData(field, schema, value, viewHelperProps, onlyMode
let {canAdd, canEdit, canDelete, canAddRow } = field;
retData.canAdd = _.isUndefined(canAdd) ? retData.canAdd : evalFunc(schema, canAdd, value);
retData.canAdd = !disabled && retData.canAdd;
retData.canAdd = !retData.disabled && retData.canAdd;
retData.canEdit = _.isUndefined(canEdit) ? retData.canEdit : evalFunc(schema, canEdit, value);
retData.canEdit = !disabled && retData.canEdit;
retData.canEdit = !retData.disabled && retData.canEdit;
retData.canDelete = _.isUndefined(canDelete) ? retData.canDelete : evalFunc(schema, canDelete, value);
retData.canDelete = !disabled && retData.canDelete;
retData.canDelete = !retData.disabled && retData.canDelete;
retData.canAddRow = _.isUndefined(canAddRow) ? retData.canAddRow : evalFunc(schema, canAddRow, value);
return retData;
}

View File

@ -138,7 +138,10 @@ function getChangedData(topSchema, viewHelperProps, sessData, stringify=false) {
/* At this point the schema assignments like top may not have been done
So, only check the mode by passing true to getFieldMetaData */
let {modeSupported} = getFieldMetaData(field, schema, {}, viewHelperProps, true);
if(!modeSupported) {
/* If skipChange is true, then field will not be considered for changed data,
No change in other behaviour */
if(!modeSupported || field.skipChange) {
return;
}
if(typeof(field.type) == 'string' && field.type.startsWith('nested-')) {

View File

@ -511,7 +511,7 @@ export function InputToggle({cid, value, onChange, options, disabled, readonly,
{
(options||[]).map((option)=>{
const isSelected = option.value === value;
const isDisabled = disabled || option.disabled || (readonly && isSelected);
const isDisabled = disabled || option.disabled || (readonly && !isSelected);
return (
<ToggleButton key={option.label} value={option.value} component={isSelected ? PrimaryButton : DefaultButton}
disabled={isDisabled} aria-label={option.label}>

View File

@ -239,9 +239,10 @@ describe('ExclusionConstraintSchema', ()=>{
it('columns formatter', ()=>{
let formatter = _.find(schemaObj.fields, (f)=>f.id=='columns').cell().controlProps.formatter;
expect(formatter.fromRaw([{
local_column: 'lid',
referenced: 'rid',
}])).toBe('(lid) -> (rid)');
column: 'lid',
},{
column: 'rid',
}])).toBe('lid, rid');
expect(formatter.fromRaw([])).toBe('');
});

View File

@ -165,6 +165,7 @@ describe('PrimaryKeySchema', ()=>{
});
state.index = undefined;
state.condeferrable = true;
expect(getFieldDepChange(schemaObj, 'spcname')(state)).toEqual({});
expect(getFieldDepChange(schemaObj, 'include')(state)).toEqual({});
expect(getFieldDepChange(schemaObj, 'fillfactor')(state)).toEqual({});

View File

@ -164,6 +164,7 @@ describe('UniqueConstraintSchema', ()=>{
});
state.index = undefined;
state.condeferrable = true;
expect(getFieldDepChange(schemaObj, 'spcname')(state)).toEqual({});
expect(getFieldDepChange(schemaObj, 'include')(state)).toEqual({});
expect(getFieldDepChange(schemaObj, 'fillfactor')(state)).toEqual({});