Fix column ordering in unique/primary key constraint properties

The fromRaw formatter for the Columns field in unique constraint and
primary key properties used _.filter(allOptions, ...), which preserved
the order of allOptions (table column position) rather than the
constraint-defined column order from backendVal. Replaced with _.find
mapped over backendVal to preserve the correct constraint column order.

Added unit tests for cell and type formatter functions to verify
column ordering is preserved.
This commit is contained in:
balodis authored and GitHub committed 2026-02-23 17:11:38 +05:30
1 parent 93e2f23a48
commit 080fcc1cfb
4 files changed
+102 -6

No files matched your search

@@ -125,9 +125,10 @@ export default class PrimaryKeySchema extends BaseUISchema {
multiple: true,
formatter: {
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);
/* remove the column key and pass as array preserving constraint column order */
return (backendVal||[]).map((singleVal)=>
_.find(allOptions, (opt)=>opt.value === singleVal.column)
).filter(Boolean);
},
toRaw: (value)=>{
/* take the array and convert to column key collection */
@@ -125,9 +125,10 @@ export default class UniqueConstraintSchema extends BaseUISchema {
multiple: true,
formatter: {
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);
/* remove the column key and pass as array preserving constraint column order */
return (backendVal||[]).map((singleVal) =>
_.find(allOptions, (opt) => opt.value === singleVal.column)
).filter(Boolean);
},
toRaw: (value)=>{
/* take the array and convert to column key collection */
@@ -138,6 +138,53 @@ describe('PrimaryKeySchema', ()=>{
});
it('columns cell formatter', ()=>{
let cellFormatter = _.find(schemaObj.fields, (f)=>f.id=='columns').cell().controlProps.formatter;
expect(cellFormatter.fromRaw([{
column: 'user_id',
},{
column: 'client_order_id',
}])).toBe('user_id,client_order_id');
expect(cellFormatter.fromRaw([])).toBe('');
});
it('columns type formatter preserves constraint column order', ()=>{
let typeFormatter = _.find(schemaObj.fields, (f)=>f.id=='columns').type().controlProps.formatter;
/* allOptions are in table column position order (alphabetical here) */
let allOptions = [
{value: 'alpha', label: 'alpha'},
{value: 'beta', label: 'beta'},
{value: 'gamma', label: 'gamma'},
];
/* backendVal comes from the constraint definition in a different order */
let backendVal = [{column: 'gamma'}, {column: 'alpha'}];
let result = typeFormatter.fromRaw(backendVal, allOptions);
/* result must preserve backendVal order, not allOptions order */
expect(result).toEqual([
{value: 'gamma', label: 'gamma'},
{value: 'alpha', label: 'alpha'},
]);
/* empty and null values should be handled gracefully */
expect(typeFormatter.fromRaw([], allOptions)).toEqual([]);
expect(typeFormatter.fromRaw(null, allOptions)).toEqual([]);
});
it('columns type formatter toRaw', ()=>{
let typeFormatter = _.find(schemaObj.fields, (f)=>f.id=='columns').type().controlProps.formatter;
expect(typeFormatter.toRaw([{value: 'user_id'}, {value: 'client_order_id'}])).toEqual([
{column: 'user_id'},
{column: 'client_order_id'},
]);
expect(typeFormatter.toRaw([])).toEqual([]);
expect(typeFormatter.toRaw(null)).toEqual([]);
});
it('validate', ()=>{
let state = {};
let setError = jest.fn();
@@ -137,6 +137,53 @@ describe('UniqueConstraintSchema', ()=>{
});
it('columns cell formatter', ()=>{
let cellFormatter = _.find(schemaObj.fields, (f)=>f.id=='columns').cell().controlProps.formatter;
expect(cellFormatter.fromRaw([{
column: 'user_id',
},{
column: 'client_order_id',
}])).toBe('user_id,client_order_id');
expect(cellFormatter.fromRaw([])).toBe('');
});
it('columns type formatter preserves constraint column order', ()=>{
let typeFormatter = _.find(schemaObj.fields, (f)=>f.id=='columns').type().controlProps.formatter;
/* allOptions are in table column position order (alphabetical here) */
let allOptions = [
{value: 'alpha', label: 'alpha'},
{value: 'beta', label: 'beta'},
{value: 'gamma', label: 'gamma'},
];
/* backendVal comes from the constraint definition in a different order */
let backendVal = [{column: 'gamma'}, {column: 'alpha'}];
let result = typeFormatter.fromRaw(backendVal, allOptions);
/* result must preserve backendVal order, not allOptions order */
expect(result).toEqual([
{value: 'gamma', label: 'gamma'},
{value: 'alpha', label: 'alpha'},
]);
/* empty and null values should be handled gracefully */
expect(typeFormatter.fromRaw([], allOptions)).toEqual([]);
expect(typeFormatter.fromRaw(null, allOptions)).toEqual([]);
});
it('columns type formatter toRaw', ()=>{
let typeFormatter = _.find(schemaObj.fields, (f)=>f.id=='columns').type().controlProps.formatter;
expect(typeFormatter.toRaw([{value: 'user_id'}, {value: 'client_order_id'}])).toEqual([
{column: 'user_id'},
{column: 'client_order_id'},
]);
expect(typeFormatter.toRaw([])).toEqual([]);
expect(typeFormatter.toRaw(null)).toEqual([]);
});
it('validate', ()=>{
let state = {};
let setError = jest.fn();