Web console: better detection for arrays containing objects (#13077)

* better detection for arrays containing objects

* include boolean also
This commit is contained in:
Vadim Ogievetsky 2022-09-12 18:50:29 -07:00 committed by GitHub
parent 77925cdcdd
commit 08d6aca528
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 3 deletions

View File

@ -49,6 +49,14 @@ exports[`TableCell matches snapshot array long 1`] = `
</div> </div>
`; `;
exports[`TableCell matches snapshot array mixed 1`] = `
<div
class="table-cell plain"
>
["a",{"v":"b"},"c"]
</div>
`;
exports[`TableCell matches snapshot array short 1`] = ` exports[`TableCell matches snapshot array short 1`] = `
<div <div
class="table-cell plain" class="table-cell plain"

View File

@ -64,6 +64,13 @@ describe('TableCell', () => {
expect(container.firstChild).toMatchSnapshot(); expect(container.firstChild).toMatchSnapshot();
}); });
it('matches snapshot array mixed', () => {
const tableCell = <TableCell value={['a', { v: 'b' }, 'c']} />;
const { container } = render(tableCell);
expect(container.firstChild).toMatchSnapshot();
});
it('matches snapshot object', () => { it('matches snapshot object', () => {
const tableCell = <TableCell value={{ hello: 'world' }} />; const tableCell = <TableCell value={{ hello: 'world' }} />;

View File

@ -21,6 +21,7 @@ import * as JSONBig from 'json-bigint-native';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { ShowValueDialog } from '../../dialogs/show-value-dialog/show-value-dialog'; import { ShowValueDialog } from '../../dialogs/show-value-dialog/show-value-dialog';
import { isSimpleArray } from '../../utils';
import { ActionIcon } from '../action-icon/action-icon'; import { ActionIcon } from '../action-icon/action-icon';
import './table-cell.scss'; import './table-cell.scss';
@ -97,7 +98,7 @@ export const TableCell = React.memo(function TableCell(props: TableCellProps) {
{isNaN(dateValue) ? 'Unusable date' : value.toISOString()} {isNaN(dateValue) ? 'Unusable date' : value.toISOString()}
</div> </div>
); );
} else if (Array.isArray(value)) { } else if (isSimpleArray(value)) {
return renderTruncated(`[${value.join(', ')}]`); return renderTruncated(`[${value.join(', ')}]`);
} else if (typeof value === 'object') { } else if (typeof value === 'object') {
return renderTruncated(JSONBig.stringify(value)); return renderTruncated(JSONBig.stringify(value));

View File

@ -725,6 +725,15 @@ describe('spec utils', () => {
it('works for multi-value', () => { it('works for multi-value', () => {
expect(guessColumnTypeFromInput(['a', ['b'], 'c'], false)).toEqual('string'); expect(guessColumnTypeFromInput(['a', ['b'], 'c'], false)).toEqual('string');
expect(guessColumnTypeFromInput([1, [2], 3], false)).toEqual('string'); expect(guessColumnTypeFromInput([1, [2], 3], false)).toEqual('string');
expect(guessColumnTypeFromInput([true, [true, 7, false], false, 'x'], false)).toEqual(
'string',
);
});
it('works for complex arrays', () => {
expect(guessColumnTypeFromInput([{ type: 'Dogs' }, { type: 'JavaScript' }], false)).toEqual(
'COMPLEX<json>',
);
}); });
it('works for strange json', () => { it('works for strange json', () => {

View File

@ -32,6 +32,7 @@ import {
EMPTY_ARRAY, EMPTY_ARRAY,
EMPTY_OBJECT, EMPTY_OBJECT,
filterMap, filterMap,
isSimpleArray,
oneOf, oneOf,
parseCsvLine, parseCsvLine,
typeIs, typeIs,
@ -2330,7 +2331,7 @@ export function guessIsArrayFromHeaderAndRows(
headerAndRows: SampleHeaderAndRows, headerAndRows: SampleHeaderAndRows,
column: string, column: string,
): boolean { ): boolean {
return headerAndRows.rows.some(r => Array.isArray(r.input?.[column])); return headerAndRows.rows.some(r => isSimpleArray(r.input?.[column]));
} }
export function guessColumnTypeFromInput( export function guessColumnTypeFromInput(
@ -2343,7 +2344,7 @@ export function guessColumnTypeFromInput(
if (!definedValues.length) return 'string'; if (!definedValues.length) return 'string';
// If we see any arrays in the input this is a multi-value dimension that must be a string // If we see any arrays in the input this is a multi-value dimension that must be a string
if (definedValues.some(v => Array.isArray(v))) return 'string'; if (definedValues.some(v => isSimpleArray(v))) return 'string';
// If we see any JSON objects in the input assume COMPLEX<json> // If we see any JSON objects in the input assume COMPLEX<json>
if (definedValues.some(v => v && typeof v === 'object')) return 'COMPLEX<json>'; if (definedValues.some(v => v && typeof v === 'object')) return 'COMPLEX<json>';

View File

@ -40,6 +40,16 @@ export function nonEmptyArray(a: any): a is unknown[] {
return Array.isArray(a) && Boolean(a.length); return Array.isArray(a) && Boolean(a.length);
} }
export function isSimpleArray(a: any): a is (string | number | boolean)[] {
return (
Array.isArray(a) &&
a.every(x => {
const t = typeof x;
return t === 'string' || t === 'number' || t === 'boolean';
})
);
}
export function wait(ms: number): Promise<void> { export function wait(ms: number): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
setTimeout(resolve, ms); setTimeout(resolve, ms);