mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
return table directly, not the debug info
This commit is contained in:
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import TableInputCSV from './TableInputCSV';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { ParseResults } from '../../utils/processTableData';
|
||||
import { TableData } from '../../types/data';
|
||||
|
||||
const TableInputStories = storiesOf('UI/Table/Input', module);
|
||||
|
||||
@@ -11,11 +11,12 @@ TableInputStories.add('default', () => {
|
||||
return (
|
||||
<div>
|
||||
<TableInputCSV
|
||||
text="a,b,c\n1,2,3"
|
||||
width={'90%'}
|
||||
height={'90vh'}
|
||||
onTableParsed={(results: ParseResults) => {
|
||||
console.log('Table Results', results);
|
||||
action('Parsed')(results);
|
||||
onTableParsed={(table: TableData, text: string) => {
|
||||
console.log('Table', table, text);
|
||||
action('Table')(table, text);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -2,17 +2,18 @@ import React from 'react';
|
||||
|
||||
import renderer from 'react-test-renderer';
|
||||
import TableInputCSV from './TableInputCSV';
|
||||
import { ParseResults } from '../../utils/processTableData';
|
||||
import { TableData } from '../../types/data';
|
||||
|
||||
describe('TableInputCSV', () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = renderer
|
||||
.create(
|
||||
<TableInputCSV
|
||||
text="a,b,c\n1,2,3"
|
||||
width={100}
|
||||
height={100}
|
||||
onTableParsed={(results: ParseResults) => {
|
||||
console.log('GOT', results);
|
||||
onTableParsed={(table: TableData, text: string) => {
|
||||
console.log('Table:', table, 'from:', text);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -1,39 +1,56 @@
|
||||
import React from 'react';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { ParseConfig, ParseResults, parseCSV } from '../../utils/processTableData';
|
||||
import { ParseConfig, parseCSV, ParseDetails } from '../../utils/processTableData';
|
||||
import { TableData } from '../../types/data';
|
||||
|
||||
interface Props {
|
||||
config?: ParseConfig;
|
||||
width: number | string;
|
||||
height: number | string;
|
||||
onTableParsed: (results: ParseResults) => void;
|
||||
text: string;
|
||||
onTableParsed: (table: TableData, text: string) => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
text: string;
|
||||
results: ParseResults;
|
||||
table: TableData;
|
||||
details: ParseDetails;
|
||||
}
|
||||
|
||||
class TableInputCSV extends React.PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Shoud this happen in onComponentMounted?
|
||||
const { text, config, onTableParsed } = props;
|
||||
const details = {};
|
||||
const table = parseCSV(text, config, details);
|
||||
this.state = {
|
||||
text: '',
|
||||
results: parseCSV('', this.props.config),
|
||||
text,
|
||||
table,
|
||||
details,
|
||||
};
|
||||
onTableParsed(table, text);
|
||||
}
|
||||
|
||||
readCSV = debounce(() => {
|
||||
const results = parseCSV(this.state.text, this.props.config);
|
||||
this.setState({ results });
|
||||
const details = {};
|
||||
const table = parseCSV(this.state.text, this.props.config, details);
|
||||
this.setState({ table, details });
|
||||
}, 150);
|
||||
|
||||
componentDidUpdate(prevProps: Props, prevState: State) {
|
||||
if (this.state.text !== prevState.text || this.props.config !== prevProps.config) {
|
||||
const { text } = this.state;
|
||||
if (text !== prevState.text || this.props.config !== prevProps.config) {
|
||||
this.readCSV();
|
||||
}
|
||||
if (this.state.results !== prevState.results) {
|
||||
this.props.onTableParsed(this.state.results);
|
||||
// If the props text has changed, replace our local version
|
||||
if (this.props.text !== prevProps.text && this.props.text !== text) {
|
||||
this.setState({ text: this.props.text });
|
||||
}
|
||||
|
||||
if (this.state.table !== prevState.table) {
|
||||
this.props.onTableParsed(this.state.table, this.state.text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +60,9 @@ class TableInputCSV extends React.PureComponent<Props, State> {
|
||||
|
||||
render() {
|
||||
const { width, height } = this.props;
|
||||
const { table, errors } = this.state.results;
|
||||
const { table, details } = this.state;
|
||||
|
||||
const hasErrors = errors.length > 0;
|
||||
const hasErrors = details.errors && details.errors.length > 0;
|
||||
|
||||
return (
|
||||
<div className="gf-table-input-csv" style={{ width, height }}>
|
||||
|
||||
@@ -1,42 +1,66 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`processTableData basic processing should generate a header and fix widths 1`] = `
|
||||
Object {
|
||||
"columnMap": Object {},
|
||||
"columns": Array [
|
||||
Object {
|
||||
"text": "Column 1",
|
||||
},
|
||||
Object {
|
||||
"text": "Column 2",
|
||||
},
|
||||
Object {
|
||||
"text": "Column 3",
|
||||
},
|
||||
],
|
||||
"rows": Array [
|
||||
Array [
|
||||
1,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
Array [
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
],
|
||||
Array [
|
||||
5,
|
||||
6,
|
||||
null,
|
||||
],
|
||||
],
|
||||
"type": "table",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`processTableData basic processing should read header and two rows 1`] = `
|
||||
Object {
|
||||
"errors": Array [],
|
||||
"meta": Object {
|
||||
"aborted": false,
|
||||
"cursor": 17,
|
||||
"delimiter": ",",
|
||||
"linebreak": "
|
||||
",
|
||||
"truncated": false,
|
||||
},
|
||||
"table": Object {
|
||||
"columnMap": Object {},
|
||||
"columns": Array [
|
||||
Object {
|
||||
"text": "a",
|
||||
},
|
||||
Object {
|
||||
"text": "b",
|
||||
},
|
||||
Object {
|
||||
"text": "c",
|
||||
},
|
||||
"columnMap": Object {},
|
||||
"columns": Array [
|
||||
Object {
|
||||
"text": "a",
|
||||
},
|
||||
Object {
|
||||
"text": "b",
|
||||
},
|
||||
Object {
|
||||
"text": "c",
|
||||
},
|
||||
],
|
||||
"rows": Array [
|
||||
Array [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
],
|
||||
"rows": Array [
|
||||
Array [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
],
|
||||
Array [
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
],
|
||||
Array [
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
],
|
||||
"type": "table",
|
||||
},
|
||||
],
|
||||
"type": "table",
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -3,8 +3,18 @@ import { parseCSV } from './processTableData';
|
||||
describe('processTableData', () => {
|
||||
describe('basic processing', () => {
|
||||
it('should read header and two rows', () => {
|
||||
const simpleCSV = 'a,b,c\n1,2,3\n4,5,6';
|
||||
expect(parseCSV(simpleCSV)).toMatchSnapshot();
|
||||
const text = 'a,b,c\n1,2,3\n4,5,6';
|
||||
expect(parseCSV(text)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should generate a header and fix widths', () => {
|
||||
const text = '1\n2,3,4\n5,6';
|
||||
const table = parseCSV(text, {
|
||||
headerIsFirstLine: false,
|
||||
});
|
||||
expect(table.rows.length).toBe(3);
|
||||
|
||||
expect(table).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,10 +12,9 @@ export interface ParseConfig {
|
||||
comments?: boolean | string; // default: false
|
||||
}
|
||||
|
||||
export interface ParseResults {
|
||||
table: TableData;
|
||||
meta: ParseMeta;
|
||||
errors: ParseError[];
|
||||
export interface ParseDetails {
|
||||
meta?: ParseMeta;
|
||||
errors?: ParseError[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,12 +83,26 @@ function makeColumns(values: any[]): Column[] {
|
||||
});
|
||||
}
|
||||
|
||||
export function parseCSV(text: string, config?: ParseConfig): ParseResults {
|
||||
/**
|
||||
* Convert text into a valid TableData object
|
||||
*
|
||||
* @param text
|
||||
* @param config
|
||||
* @param details, if exists the result will be filled with parse details
|
||||
*/
|
||||
export function parseCSV(text: string, config?: ParseConfig, details?: ParseDetails): TableData {
|
||||
const results = Papa.parse(text, { ...config, dynamicTyping: true, skipEmptyLines: true });
|
||||
const { data, meta, errors } = results;
|
||||
|
||||
// Fill the parse details fro debugging
|
||||
if (details) {
|
||||
details.errors = errors;
|
||||
details.meta = meta;
|
||||
}
|
||||
|
||||
if (!data || data.length < 1) {
|
||||
if (!text) {
|
||||
// Show a more reasonable warning on empty input text
|
||||
// Show a more reasonable warning on empty input text
|
||||
if (details && !text) {
|
||||
errors.length = 0;
|
||||
errors.push({
|
||||
code: 'empty',
|
||||
@@ -97,16 +110,13 @@ export function parseCSV(text: string, config?: ParseConfig): ParseResults {
|
||||
type: 'warning',
|
||||
row: 0,
|
||||
});
|
||||
details.errors = errors;
|
||||
}
|
||||
return {
|
||||
table: {
|
||||
columns: [],
|
||||
rows: [],
|
||||
type: 'table',
|
||||
columnMap: {},
|
||||
},
|
||||
meta,
|
||||
errors,
|
||||
columns: [],
|
||||
rows: [],
|
||||
type: 'table',
|
||||
columnMap: {},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -114,14 +124,10 @@ export function parseCSV(text: string, config?: ParseConfig): ParseResults {
|
||||
const headerIsNotFirstLine = config && config.headerIsFirstLine === false;
|
||||
const header = headerIsNotFirstLine ? [] : results.data.shift();
|
||||
|
||||
return {
|
||||
table: matchRowSizes({
|
||||
columns: makeColumns(header),
|
||||
rows: results.data,
|
||||
type: 'table',
|
||||
columnMap: {},
|
||||
}),
|
||||
meta,
|
||||
errors,
|
||||
};
|
||||
return matchRowSizes({
|
||||
columns: makeColumns(header),
|
||||
rows: results.data,
|
||||
type: 'table',
|
||||
columnMap: {},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user