Browse Source

Improve setValue for nested values

data-source-schema
Artur Arseniev 5 months ago
parent
commit
4855f6686b
  1. 36
      packages/core/src/utils/mixins.ts
  2. 25
      packages/core/test/specs/data_sources/index.ts

36
packages/core/src/utils/mixins.ts

@ -25,7 +25,7 @@ function castPath(value: string | string[], object: ObjectAny) {
return object.hasOwnProperty(value) ? [value] : stringToPath(value);
}
export const get = (object: ObjectAny, path: string | string[], def: any) => {
export const get = (object: ObjectAny, path: string | string[], def?: any) => {
const paths = castPath(path, object);
const length = paths.length;
let index = 0;
@ -40,22 +40,32 @@ export const set = (object: ObjectAny, path: string | string[], value: any): boo
if (!isObject(object)) return false;
const paths = castPath(path, object);
const length = paths.length;
const lastIndex = length - 1;
let index = -1;
let nested = object;
while (nested != null && ++index < length) {
const key = paths[index];
let newValue = value;
if (length === 0) return false;
if (index != lastIndex) {
const objValue = nested[key];
newValue = isObject(objValue) ? objValue : !isNaN(+paths[index + 1]) ? [] : {};
if (length === 1) {
object[paths[0]] = value;
return true;
}
const parentPath = paths.slice(0, -1);
const lastKey = paths[length - 1];
const parent = get(object, parentPath);
if (parent) {
if (Array.isArray(parent)) {
const index = +lastKey;
if (!isNaN(index)) {
parent[index] = value;
return true;
}
} else if (isObject(parent)) {
(parent as ObjectAny)[lastKey] = value;
return true;
}
nested[key] = newValue;
nested = nested[key];
}
return true;
return false;
};
export const serialize = (obj: ObjectAny) => JSON.parse(JSON.stringify(obj));

25
packages/core/test/specs/data_sources/index.ts

@ -93,6 +93,7 @@ describe('DataSourceManager', () => {
expect(dsm.setValue('ds1.id1.newField', 'new field value')).toBe(true);
expect(dsm.getValue('ds1.id1.newField')).toBe('new field value');
expect(dsm.setValue('non-existing-ds.id1.name', 'New Name')).toBe(false);
expect(dsm.setValue('non-existing-ds.none.name', 'New Name')).toBe(false);
expect(dsm.setValue('invalid-path', 'New Name')).toBe(false);
});
@ -100,22 +101,26 @@ describe('DataSourceManager', () => {
test('set nested values', () => {
const ds = addDataSource();
const address = { city: 'CityName' };
const roles = ['admin', 'user'];
const roles = ['admin', 'user', 'member'];
const newObj = { newValue: '1' };
ds.addRecord({
id: 'id4',
name: 'Name4',
metadata: { address, roles },
});
// Update nested object property
// Check object updates
expect(dsm.setValue('ds1.id4.metadata.address.city', 'NewCity')).toBe(true);
expect(dsm.getValue('ds1.id4.metadata.address.city')).toBe('NewCity');
expect(dsm.setValue('ds1.id4.metadata.newObj', newObj)).toBe(true);
expect(dsm.getValue('ds1.id4.metadata.newObj')).toEqual(newObj);
// Update array item
// Check array updates
expect(dsm.setValue('ds1.id4.metadata.roles[1]', 'editor')).toBe(true);
expect(dsm.getValue('ds1.id4.metadata')).toEqual({
newObj: { newValue: '1' },
address: { city: 'NewCity' },
roles: ['admin', 'editor'],
roles: ['admin', 'editor', 'member'],
});
// Set entirely new nested object
@ -123,16 +128,26 @@ describe('DataSourceManager', () => {
expect(dsm.setValue('ds1.id4.metadata.address', newAddress)).toBe(true);
expect(dsm.getValue('ds1.id4.metadata.address')).toEqual(newAddress);
// Set new array
const newRoles = ['editor', 'viewer'];
expect(dsm.setValue('ds1.id4.metadata.roles', newRoles)).toBe(true);
expect(dsm.getValue('ds1.id4.metadata.roles')).toEqual(newRoles);
expect(dsm.getValue('ds1.id4.metadata')).toEqual({
newObj: { newValue: '1' },
address: { city: 'AnotherCity', country: 'SomeCountry' },
roles: ['editor', 'viewer'],
});
// Set completely new nested structure
const newMetadata = { tags: ['tag1', 'tag2'], settings: { theme: 'dark' } };
expect(dsm.setValue('ds1.id4.metadata', newMetadata)).toBe(true);
expect(dsm.getValue('ds1.id4.metadata')).toEqual(newMetadata);
expect(dsm.getValue('ds1.id4.metadata.settings.theme')).toBe('dark');
expect(dsm.getValue('ds1.id4.metadata')).toEqual({
tags: ['tag1', 'tag2'],
settings: { theme: 'dark' },
});
});
});
});

Loading…
Cancel
Save