Skip to content

Add selection by array #417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions __tests__/selectByObject.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { selectFromObject, setObjectByKey } from '../src/utils/';

describe('selectFromObject', () => {
describe('by string', () => {
test('Select valid value', () => {
const obj = { a: { b: { c: 'value' } } };
const res = selectFromObject(obj, 'a.b.c');
expect(res).toEqual('value');
});
test('Return undefined when path does not exist', () => {
const obj = { a: { b: { c: 'value' } } };
const res = selectFromObject(obj, 'b.a.c');
expect(res).toEqual(undefined);
});
test('Allow selecting by number index', () => {
const obj = { a: [{ b: { c: 'value' } }] };
const res = selectFromObject(obj, 'a[0].b.c');
expect(res).toEqual(obj.a[0].b.c);
});
});

describe('by array', () => {
test('Select valid value', () => {
const obj = { a: { b: { c: 'value' } } };
const res = selectFromObject(obj, ['a', 'b', 'c']);
expect(res).toEqual('value');
});
test('Select valid value with number', () => {
const obj = { a: [{ b: { c: 'value' } }] };
const res = selectFromObject(obj, ['a', 0, 'b', 'c']);
expect(res).toEqual('value');
});
test('Return undefined when path does not exist', () => {
const obj = { a: { b: { c: 'value' } } };
const res = selectFromObject(obj, ['x', 'y', 'z']);
expect(res).toEqual(undefined);
});
test('Select root with empty array', () => {
const obj = { a: { b: { c: 'value' } } };
const res = selectFromObject(obj, []);
expect(res).toEqual(obj);
});
});
});

describe('setObjectByKey', () => {
describe('by string', () => {
test('Select valid value', () => {
const obj = { a: { b: { c: 'value' } } };
setObjectByKey(obj, 'a.b.c', 'newValue');
expect(obj).toEqual({ a: { b: { c: 'newValue' } } });
});
});

describe('by array', () => {
test('Select valid value', () => {
const obj = { a: { b: { c: 'value' } } };
setObjectByKey(obj, ['a', 'b', 'c'], 'newValue');
expect(obj).toEqual({ a: { b: { c: 'newValue' } } });
});
});
});
6 changes: 3 additions & 3 deletions src/components/MTableEditRow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import TableCell from '@material-ui/core/TableCell';
import TableRow from '@material-ui/core/TableRow';
import Typography from '@material-ui/core/Typography';
import PropTypes from 'prop-types';
import { setByString } from '@utils';
import { setObjectByKey } from '@utils';
import * as CommonValues from '@utils/common-values';
import { validateInput } from '@utils/validate';

Expand All @@ -13,7 +13,7 @@ function MTableEditRow(props) {
return props.columns
.filter((column) => 'initialEditValue' in column && column.field)
.reduce((prev, column) => {
setByString(prev, column.field, column.initialEditValue);
setObjectByKey(prev, column.field, column.initialEditValue);
return prev;
}, {});
}
Expand Down Expand Up @@ -115,7 +115,7 @@ function MTableEditRow(props) {
rowData={state.data}
onChange={(value) => {
const data = { ...state.data };
setByString(data, columnDef.field, value);
setObjectByKey(data, columnDef.field, value);
// data[columnDef.field] = value;
setState({ data });
if (props.onBulkEditRowChanged) {
Expand Down
6 changes: 3 additions & 3 deletions src/components/MTableEditRow/m-table-edit-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import TableRow from '@material-ui/core/TableRow';
import Typography from '@material-ui/core/Typography';
import PropTypes from 'prop-types';
import React from 'react';
import { byString, setByString } from '../../utils';
import { selectFromObject, setObjectByKey } from '../../utils';
import * as CommonValues from '../../utils/common-values';
import { validateInput } from '../../utils/validate';
/* eslint-enable no-unused-vars */
Expand Down Expand Up @@ -67,7 +67,7 @@ export default class MTableEditRow extends React.Component {
const value =
typeof this.state.data[columnDef.field] !== 'undefined'
? this.state.data[columnDef.field]
: byString(this.state.data, columnDef.field);
: selectFromObject(this.state.data, columnDef.field);
const getCellStyle = (columnDef, value) => {
let cellStyle = {
color: 'inherit'
Expand Down Expand Up @@ -149,7 +149,7 @@ export default class MTableEditRow extends React.Component {
rowData={this.state.data}
onChange={(value) => {
const data = { ...this.state.data };
setByString(data, columnDef.field, value);
setObjectByKey(data, columnDef.field, value);
// data[columnDef.field] = value;
this.setState({ data }, () => {
if (this.props.onBulkEditRowChanged) {
Expand Down
7 changes: 4 additions & 3 deletions src/utils/data-manager.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import formatDate from 'date-fns/format';
import uuid from 'uuid';
import { byString } from './';
import { selectFromObject } from './';

export default class DataManager {
checkForId = false;
Expand Down Expand Up @@ -601,7 +601,7 @@ export default class DataManager {
let value =
typeof rowData[columnDef.field] !== 'undefined'
? rowData[columnDef.field]
: byString(rowData, columnDef.field);
: selectFromObject(rowData, columnDef.field);
if (columnDef.lookup && lookup) {
value = columnDef.lookup[value];
}
Expand Down Expand Up @@ -884,7 +884,8 @@ export default class DataManager {
let object = result;
object = groups.reduce((o, colDef) => {
const value =
currentRow[colDef.field] || byString(currentRow, colDef.field);
currentRow[colDef.field] ||
selectFromObject(currentRow, colDef.field);

let group;
if (o.groupsIndex[value] !== undefined) {
Expand Down
26 changes: 18 additions & 8 deletions src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import * as CommonValues from '@utils/common-values';

export const byString = (o, s) => {
export const selectFromObject = (o, s) => {
if (!s) {
return;
}
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
const a = s.split('.');
let a;
if (!Array.isArray(s)) {
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
a = s.split('.');
} else {
a = s;
}
for (let i = 0, n = a.length; i < n; ++i) {
const x = a[i];
if (o && x in o) {
Expand All @@ -18,11 +23,16 @@ export const byString = (o, s) => {
return o;
};

export const setByString = (obj, path, value) => {
export const setObjectByKey = (obj, path, value) => {
let schema = obj; // a moving reference to internal objects within obj
path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
path = path.replace(/^\./, ''); // strip a leading dot
const pList = path.split('.');
let pList;
if (!Array.isArray(path)) {
path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
path = path.replace(/^\./, ''); // strip a leading dot
pList = path.split('.');
} else {
pList = path;
}
const len = pList.length;
for (let i = 0; i < len - 1; i++) {
const elem = pList[i];
Expand Down
4 changes: 2 additions & 2 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export interface EditComponentProps<RowData extends object> {
}

export interface EditCellColumnDef {
field: string;
field: string | string[];
title: string;
tableData: {
columnOrder: number;
Expand Down Expand Up @@ -203,7 +203,7 @@ export interface Column<RowData extends object> {
| React.ReactElement<any>
| ((data: any) => React.ReactElement<any> | string);
export?: boolean;
field?: keyof RowData | string;
field?: keyof RowData | string | Array<keyof RowData | string>;
filtering?: boolean;
filterComponent?: (props: {
columnDef: Column<RowData>;
Expand Down