Fixed the dynamic column updation in the Unique & Primary Keys while creating a table.

* Updated the columns for the unique and primary keys while creating a table.
Use the 'editable' option for a Cell instead of 'disabled'.

* Don't need to define the hidden member as fields in GridHeaderSchema

* Updated the columns for the exclusion constraints while creating a
 table.

* Signaled the relevant field, when column options have changed, for all
the children of a table.

* Use current snapshot of data for the GrigFormHeadeer

* Fixed the styling for the search input box

* Don't check for the 'colOptions.editable' flag, as it could be
indirect call as well.
This commit is contained in:
Ashesh Vashi 2024-09-19 18:57:09 +05:30 committed by GitHub
parent 6a79d0a195
commit 1f53baee8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 100 additions and 147 deletions

View File

@ -43,14 +43,14 @@ export class DefaultWithSchema extends BaseUISchema {
}
export class PublicationTableSchema extends BaseUISchema {
constructor(allTables,getColumns) {
constructor(allTables, getColumns) {
super({
table_name: undefined,
where: undefined,
columns:undefined,
columns: [],
});
this.allTables = allTables;
this.getColumns=getColumns;
this.getColumns = getColumns;
this.allTablesOptions = [];
this.varTypes = {};
this.allReadOnly = false;
@ -104,7 +104,7 @@ export class PublicationTableSchema extends BaseUISchema {
cell: 'select',
options: this.allTables,
optionsLoaded: (options) => {
obj.allTablesOptions=options;
obj.allTablesOptions = options;
},
controlProps: { allowClear: false },
}),
@ -118,7 +118,7 @@ export class PublicationTableSchema extends BaseUISchema {
depChange: (state) => {
if(!state.table_name) {
return {
columns: null,
columns: [],
};
}
},
@ -127,9 +127,10 @@ export class PublicationTableSchema extends BaseUISchema {
},
cell: (state) => {
let tid = obj.getTableOid(state.table_name);
return{
return {
cell: 'select',
options: (state.table_name && tid) ? ()=>obj.getColumns({tid: tid}) : [],
options: (state.table_name && tid) ? () => obj.getColumns({tid: tid}) : [],
optionsReloadBasis: tid,
controlProps: { allowClear: true, multiple: true},
};

View File

@ -49,6 +49,7 @@ class ExclusionColHeaderSchema extends BaseUISchema {
is_exp: undefined,
column: undefined,
expression: undefined,
columns_updated_at: 0,
});
this.columns = columns;
@ -56,6 +57,8 @@ class ExclusionColHeaderSchema extends BaseUISchema {
changeColumnOptions(columns) {
this.columns = columns;
if (this.state)
this.state.data = {...this.state.data, columns_updated_at: Date.now()};
}
addDisabled(state) {
@ -76,10 +79,14 @@ class ExclusionColHeaderSchema extends BaseUISchema {
return [{
id: 'is_exp', label: gettext('Is expression'), type:'switch', editable: false,
},{
id: 'column', label: gettext('Column'), type: 'select', editable: false,
options: this.columns, deps: ['is_exp'],
optionsReloadBasis: this.columns?.map ? _.join(this.columns.map((c)=>c.label), ',') : null,
id: 'column', label: gettext('Column'), editable: false,
options: this.columns, deps: ['is_exp', 'columns_updated_at'],
type: () => ({
type: 'select',
optionsReloadBasis: this.columns?.map ?
_.join(this.columns.map((c)=>c.label), ',') : null,
optionsLoaded: (res)=>this.columnOptions=res,
}),
disabled: (state)=>state.is_exp,
},{
id: 'expression', label: gettext('Expression'), editable: false, deps: ['is_exp'],
@ -205,6 +212,7 @@ export default class ExclusionConstraintSchema extends BaseUISchema {
condeferred: undefined,
columns: [],
include: [],
columns_updated_at: 0,
});
this.nodeInfo = nodeInfo;
@ -233,6 +241,8 @@ export default class ExclusionConstraintSchema extends BaseUISchema {
changeColumnOptions(columns) {
this.exHeaderSchema.changeColumnOptions(columns);
this.fieldOptions.columns = columns;
if (this.state)
this.state.data = {...this.state.data, columns_updated_at: Date.now()};
}
isReadonly(state) {
@ -406,7 +416,7 @@ export default class ExclusionConstraintSchema extends BaseUISchema {
editable: false,
canDelete: true, canAdd: true,
mode: ['properties', 'create', 'edit'], min_version: 110000,
deps: ['index'],
deps: ['index', 'columns_updated_at'],
readonly: function() {
if(!obj.isNew()) {
return true;
@ -423,6 +433,9 @@ export default class ExclusionConstraintSchema extends BaseUISchema {
return {include: []};
}
}
}, {
// Don't include this in the data.
id: 'columns_updated_at', exclude: true, type: 'text', visible: false,
}];
}

View File

@ -48,6 +48,7 @@ class ForeignKeyHeaderSchema extends BaseUISchema {
references: undefined,
referenced: undefined,
_disable_references: false,
columns_updated_at: 0,
});
this.fieldOptions = fieldOptions;
@ -56,6 +57,8 @@ class ForeignKeyHeaderSchema extends BaseUISchema {
changeColumnOptions(columns) {
this.fieldOptions.local_column = columns;
if (this.state)
this.state.data = {...this.state.data, columns_updated_at: Date.now()};
}
addDisabled(state) {
@ -84,9 +87,15 @@ class ForeignKeyHeaderSchema extends BaseUISchema {
get baseFields() {
let obj = this;
return [{
id: 'local_column', label: gettext('Local column'), type:'select', editable: false,
id: 'local_column', label: gettext('Local column'), editable: false,
deps: ['columns_updated_at'],
type: () => ({
type: 'select',
options: this.fieldOptions.local_column,
optionsReloadBasis: this.fieldOptions.local_column?.map ? _.join(this.fieldOptions.local_column.map((c)=>c.label), ',') : null,
optionsReloadBasis: this.fieldOptions.local_column?.map ?
_.join(this.fieldOptions.local_column.map((c) => c.label), ',') :
null
}),
},{
id: 'references', label: gettext('References'), type: 'select', editable: false,
options: this.fieldOptions.references,

View File

@ -12,6 +12,8 @@ import _ from 'lodash';
import { isEmptyString } from 'sources/validators';
import { SCHEMA_STATE_ACTIONS } from '../../../../../../../../../../static/js/SchemaView';
import TableSchema from '../../../../static/js/table.ui';
export default class PrimaryKeySchema extends BaseUISchema {
constructor(fieldOptions={}, nodeInfo={}) {
super({
@ -26,6 +28,7 @@ export default class PrimaryKeySchema extends BaseUISchema {
condeferred: undefined,
columns: [],
include: [],
columns_updated_at: 0,
});
this.fieldOptions = fieldOptions;
@ -42,6 +45,8 @@ export default class PrimaryKeySchema extends BaseUISchema {
changeColumnOptions(columns) {
this.fieldOptions.columns = columns;
if (this.state)
this.state.data = {...this.state.data, columns_updated_at: Date.now()};
}
get baseFields() {
@ -69,14 +74,14 @@ export default class PrimaryKeySchema extends BaseUISchema {
}
},{
id: 'columns', label: gettext('Columns'),
deps: ()=>{
let ret = ['index'];
deps: () => {
let ret = ['index', 'columns_updated_at'];
if(obj.inTable) {
ret.push(['columns']);
}
return ret;
},
depChange: (state, source, topState, actionObj)=>{
depChange: (state, source, topState, actionObj) => {
/* If in table, sync up value with columns in table */
if(obj.inTable && !state) {
/* the FK is removed by some other dep, this can be a no-op */
@ -99,7 +104,8 @@ export default class PrimaryKeySchema extends BaseUISchema {
}
return {columns: currColumns};
},
cell: ()=>({
editable: false,
cell: () => ({
cell: '',
controlProps: {
formatter: {
@ -110,7 +116,7 @@ export default class PrimaryKeySchema extends BaseUISchema {
},
}
}),
type: ()=>({
type: () => ({
type: 'select',
optionsReloadBasis: obj.fieldOptions.columns?.map ? _.join(obj.fieldOptions.columns.map((c)=>c.label), ',') : null,
options: obj.fieldOptions.columns,
@ -130,16 +136,8 @@ export default class PrimaryKeySchema extends BaseUISchema {
},
},
}), group: gettext('Definition'),
editable: false,
readonly: function(state) {
if(!obj.isNew(state)) {
return true;
}
},
disabled: function(state) {
// Disable if index is selected.
return !(_.isUndefined(state.index) || state.index == '');
},
readonly: (state) => !obj.isNew(state),
disabled: (state) => !(_.isUndefined(state.index) || state.index == ''),
},{
id: 'include', label: gettext('Include columns'),
type: ()=>({

View File

@ -28,6 +28,7 @@ export default class UniqueConstraintSchema extends BaseUISchema {
indnullsnotdistinct: undefined,
columns: [],
include: [],
columns_updated_at: 0,
});
this.fieldOptions = fieldOptions;
@ -44,6 +45,8 @@ export default class UniqueConstraintSchema extends BaseUISchema {
changeColumnOptions(columns) {
this.fieldOptions.columns = columns;
if (this.state)
this.state.data = {...this.state.data, columns_updated_at: Date.now()};
}
get baseFields() {
@ -71,20 +74,21 @@ export default class UniqueConstraintSchema extends BaseUISchema {
}
},{
id: 'columns', label: gettext('Columns'),
deps: ()=>{
let ret = ['index'];
deps: () => {
let ret = ['index', 'columns_updated_at'];
if(obj.inTable) {
ret.push(['columns']);
}
return ret;
},
depChange: (state, source, topState, actionObj)=>{
depChange: (state, source, topState, actionObj) => {
/* If in table, sync up value with columns in table */
if(obj.inTable && !state) {
/* the FK is removed by some other dep, this can be a no-op */
return;
}
let currColumns = state.columns || [];
if(obj.inTable && source[0] == 'columns') {
if(actionObj.type == SCHEMA_STATE_ACTIONS.DELETE_ROW) {
let oldColumn = _.get(actionObj.oldState, actionObj.path.concat(actionObj.value));
@ -100,7 +104,8 @@ export default class UniqueConstraintSchema extends BaseUISchema {
}
return {columns: currColumns};
},
cell: ()=>({
editable: false,
cell: () => ({
cell: '',
controlProps: {
formatter: {
@ -111,7 +116,7 @@ export default class UniqueConstraintSchema extends BaseUISchema {
},
}
}),
type: ()=>({
type: () => ({
type: 'select',
optionsReloadBasis: obj.fieldOptions.columns?.map ? _.join(obj.fieldOptions.columns.map((c)=>c.label), ',') : null,
options: obj.fieldOptions.columns,
@ -119,26 +124,20 @@ export default class UniqueConstraintSchema extends BaseUISchema {
allowClear:false,
multiple: true,
formatter: {
fromRaw: (backendVal, allOptions)=>{
fromRaw: (backendVal, allOptions) => {
/* remove the column key and pass as array */
let optValues = (backendVal||[]).map((singleVal)=>singleVal.column);
return _.filter(allOptions, (opt)=>optValues.indexOf(opt.value)>-1);
let optValues = (backendVal||[]).map((singleVal) => singleVal.column);
return _.filter(allOptions, (opt) => optValues.indexOf(opt.value)>-1);
},
toRaw: (value)=>{
/* take the array and convert to column key collection */
return (value||[]).map((singleVal)=>({column: singleVal.value}));
return (value||[]).map((singleVal) => ({column: singleVal.value}));
},
},
},
}), group: gettext('Definition'),
editable: false,
readonly: function(state) {
return obj.isReadOnly(state);
},
disabled: function(state) {
// Disable if index is selected.
return !(_.isUndefined(state.index) || state.index == '');
},
readonly: (state) => obj.isReadOnly(state),
disabled: (state) => !(_.isUndefined(state.index) || state.index == ''),
},{
id: 'include', label: gettext('Include columns'),
type: ()=>({

View File

@ -26,6 +26,7 @@ class IndexColHeaderSchema extends BaseUISchema {
is_exp: true,
colname: '',
expression: '',
columns_updated_at: 0,
});
this.columns = columns;
@ -33,6 +34,8 @@ class IndexColHeaderSchema extends BaseUISchema {
changeColumnOptions(columns) {
this.columns = columns;
if (this.state)
this.state.data = {...this.state.data, columns_updated_at: Date.now()};
}
addDisabled(state) {
@ -51,14 +54,18 @@ class IndexColHeaderSchema extends BaseUISchema {
return [{
id: 'is_exp', label: gettext('Is expression'), type:'switch', editable: false,
},{
id: 'colname', label: gettext('Column'), type: 'select', editable: false,
options: this.columns, deps: ['is_exp'],
optionsReloadBasis: this.columns?.map ? _.join(this.columns.map((c)=>c.label), ',') : null,
optionsLoaded: (res)=>this.columnOptions=res,
disabled: (state)=>state.is_exp, node: 'column',
id: 'colname', label: gettext('Column'), editable: false,
deps: ['is_exp', 'columns_updated_at'],
type: () => ({
type: 'select', options: this.columns,
optionsReloadBasis: this.columns?.map ?
_.join(this.columns.map((c)=>c.label), ',') : null,
optionsLoaded: (res) => this.columnOptions = res,
}),
disabled: (state) => state.is_exp, node: 'column',
},{
id: 'expression', label: gettext('Expression'), editable: false, deps: ['is_exp'],
type: 'sql', disabled: (state)=>!state.is_exp,
id: 'expression', label: gettext('Expression'), editable: false,
deps: ['is_exp'], type: 'sql', disabled: (state)=>!state.is_exp,
}];
}
}

View File

@ -15,6 +15,7 @@ export class PartitionKeysSchema extends BaseUISchema {
constructor(columns=[], getCollations=[], getOperatorClass=[]) {
super({
key_type: 'column',
columns_updated_at: 0,
});
this.columns = columns;
this.columnsReloadBasis = false;
@ -24,6 +25,8 @@ export class PartitionKeysSchema extends BaseUISchema {
changeColumnOptions(columns) {
this.columns = columns;
if (this.state)
this.state.data = {...this.state.data, columns_updated_at: Date.now()};
}
isEditable(state) {
@ -40,9 +43,9 @@ export class PartitionKeysSchema extends BaseUISchema {
},{
label: gettext('Expression'), value: 'expression',
}],
},{
}, {
id: 'pt_column', label: gettext('Column'), type:'select',
deps: ['key_type', ['columns']],
deps: ['key_type', 'columns_updated_at'],
depChange: (state, source)=>{
if(state.key_type == 'expression' || source[0] == 'columns') {
return {
@ -50,9 +53,9 @@ export class PartitionKeysSchema extends BaseUISchema {
};
}
},
cell: ()=>({
cell: () => ({
cell: 'select',
optionsReloadBasis: _.join(obj.columns.map((c)=>c.label), ','),//obj.columnsReloadBasis,
optionsReloadBasis: _.join(obj.columns.map((c) => c.label), ','),
options: obj.columns,
controlProps: {
allowClear: false,

View File

@ -451,7 +451,9 @@ export default class TableSchema extends BaseUISchema {
}
changeColumnOptions(columns) {
let colOptions = (columns||[]).map((c)=>({label: c.name, value: c.name, image:'icon-column'}));
let colOptions = (columns||[]).map(
(c) => ({label: c.name, value: c.name, image:'icon-column'})
);
this.constraintsObj.changeColumnOptions(colOptions);
this.partitionKeysObj.changeColumnOptions(colOptions);
this.partitionsObj.changeColumnOptions(colOptions);
@ -749,7 +751,7 @@ export default class TableSchema extends BaseUISchema {
let typeTable = _.find(obj.ofTypeTables||[], (t)=>t.label==state.typname);
finalCols = typeTable.oftype_columns;
}
resolve(()=>{
resolve(() => {
obj.changeColumnOptions(finalCols);
return {
columns: finalCols,

View File

@ -84,7 +84,6 @@ export function DataGridFormHeader({tableEleRef}) {
const label = field.label || '';
const newRowIndex = useRef(-1);
const schemaState = useContext(SchemaStateContext);
const headerFormData = useRef({});
const [addDisabled, setAddDisabled] = useState(!canAdd || !canAddRow);
const {headerSchema} = field;
const disableAddButton = (flag) => {
@ -98,7 +97,7 @@ export function DataGridFormHeader({tableEleRef}) {
return;
}
let newRow = headerSchema.getNewData(headerFormData.current);
let newRow = headerSchema.getNewData(headerSchema.state.data);
newRowIndex.current = addOnTop ? 0 : rows.length;
@ -156,10 +155,9 @@ export function DataGridFormHeader({tableEleRef}) {
schema={headerSchema}
viewHelperProps={viewHelperProps}
showFooter={false}
onDataChange={(isDataChanged, dataChanged)=>{
headerFormData.current = dataChanged;
onDataChange={()=>{
disableAddButton(
headerSchema.addDisabled(headerFormData.current)
headerSchema.addDisabled(headerSchema.state.data)
);
}}
hasSQL={false}

View File

@ -43,8 +43,6 @@ export function getMappedCell({field}) {
subscriberManager.current?.signal(...args);
};
const depVals = listenDepChanges(
colAccessPath, field, schemaState, rerenderCellOnDepChange
);
@ -55,7 +53,7 @@ export function getMappedCell({field}) {
rowValue = row.original;
colOptions = { disabled: true, readonly: true };
} else {
colOptions['readonly'] = !colOptions['editable'];
colOptions = {...colOptions, readonly: !colOptions['editable']};
}
let cellProps = {};
@ -77,7 +75,6 @@ export function getMappedCell({field}) {
row,
dataDispatch,
onCellChange: (changeValue) => {
if (colOptions.disabled) return;
if(field.radioType) {
dataDispatch({
type: SCHEMA_STATE_ACTIONS.BULK_UPDATE,

View File

@ -7,8 +7,6 @@
//
//////////////////////////////////////////////////////////////
import { evalFunc } from 'sources/utils';
export function generateTimeBasedRandomNumberString() {
return new Date().getTime() + '' + Math.floor(Math.random() * 1000001);
@ -18,79 +16,6 @@ export const isModeSupportedByField = (field, helperProps) => (
!field.mode || field.mode.indexOf(helperProps.mode) > -1
);
export function getFieldMetaData(
field, schema, value, viewHelperProps
) {
let retData = {
readonly: false,
disabled: false,
visible: true,
editable: true,
canAdd: true,
canEdit: false,
canDelete: true,
modeSupported: isModeSupportedByField(field, viewHelperProps),
canAddRow: true,
};
if(!retData.modeSupported) {
return retData;
}
let {visible, disabled, readonly, editable} = field;
let verInLimit;
if (_.isUndefined(viewHelperProps.serverInfo)) {
verInLimit= true;
} else {
verInLimit = ((_.isUndefined(field.server_type) ? true :
(viewHelperProps.serverInfo.type in field.server_type)) &&
(_.isUndefined(field.min_version) ? true :
(viewHelperProps.serverInfo.version >= field.min_version)) &&
(_.isUndefined(field.max_version) ? true :
(viewHelperProps.serverInfo.version <= field.max_version)));
}
retData.readonly = viewHelperProps.inCatalog || (viewHelperProps.mode == 'properties');
if(!retData.readonly) {
retData.readonly = evalFunc(schema, readonly, value);
}
let _visible = verInLimit;
_visible = _visible && evalFunc(schema, _.isUndefined(visible) ? true : visible, value);
retData.visible = Boolean(_visible);
retData.disabled = Boolean(evalFunc(schema, disabled, value));
retData.editable = !(
viewHelperProps.inCatalog || (viewHelperProps.mode == 'properties')
);
if(retData.editable) {
retData.editable = evalFunc(
schema, (_.isUndefined(editable) ? true : editable), value
);
}
let {canAdd, canEdit, canDelete, canAddRow } = field;
retData.canAdd =
_.isUndefined(canAdd) ? retData.canAdd : evalFunc(schema, canAdd, value);
retData.canAdd = !retData.disabled && retData.canAdd;
retData.canEdit = _.isUndefined(canEdit) ? retData.canEdit : evalFunc(
schema, canEdit, value
);
retData.canEdit = !retData.disabled && retData.canEdit;
retData.canDelete = _.isUndefined(canDelete) ? retData.canDelete : evalFunc(
schema, canDelete, value
);
retData.canDelete = !retData.disabled && retData.canDelete;
retData.canAddRow =
_.isUndefined(canAddRow) ? retData.canAddRow : evalFunc(
schema, canAddRow, value
);
return retData;
}
/*
* Compare the sessData with schema.origData.

View File

@ -36,9 +36,9 @@ export const SearchInputText = ({
onChange,
};
if (alignment == SEARCH_INPUT_ALIGNMENT.RIGHT)
props.style['margin-left'] = 'auto';
props.style['marginLeft'] = 'auto';
else
props.style['margin-right'] = 'auto';
props.style['marginRight'] = 'auto';
return <InputText {...props}/>;
};

View File

@ -278,7 +278,8 @@ class UserManagementSchema extends BaseUISchema {
const api = getApiInstance();
return [
{
id: 'userManagement', label: '', type: 'collection', schema: obj.userManagementCollObj,
id: 'userManagement', label: '', type: 'collection',
schema: obj.userManagementCollObj,
canAdd: true, canDelete: true, isFullTab: true,
addOnTop: true,
canDeleteRow: (row)=>{