Commit 40d7ba1e by ryan

adding toolbar

parent 9df47391
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
import TableInputCSV from './TableInputCSV'; import TableInputCSV from './TableInputCSV';
import { withFullSizeStory } from '../../utils/storybook/withFullSizeStory';
const TableInputStories = storiesOf('UI/Table/Input', module); const TableInputStories = storiesOf('UI/Table/Input', module);
TableInputStories.addDecorator(withCenteredStory);
TableInputStories.add('default', () => { TableInputStories.add('default', () => {
return renderComponentWithTheme(TableInputCSV, {}); return withFullSizeStory(TableInputCSV, {});
}); });
...@@ -5,7 +5,7 @@ import TableInputCSV from './TableInputCSV'; ...@@ -5,7 +5,7 @@ import TableInputCSV from './TableInputCSV';
describe('TableInputCSV', () => { describe('TableInputCSV', () => {
it('renders correctly', () => { it('renders correctly', () => {
const tree = renderer.create(<TableInputCSV />).toJSON(); const tree = renderer.create(<TableInputCSV width={100} height={100} />).toJSON();
//expect(tree).toMatchSnapshot(); //expect(tree).toMatchSnapshot();
expect(tree).toBeDefined(); expect(tree).toBeDefined();
}); });
......
...@@ -18,6 +18,35 @@ interface ParseResults { ...@@ -18,6 +18,35 @@ interface ParseResults {
errors: ParseError[]; errors: ParseError[];
} }
// This mutates the table structure!
export function checkAndFix(table: TableData): number {
let cols = table.columns.length;
let different = 0;
table.rows.forEach(row => {
if (cols !== row.length) {
different++;
cols = Math.max(cols, row.length);
}
});
if (different > 0) {
if (cols !== table.columns.length) {
const diff = cols - table.columns.length;
for (let i = 0; i < diff; i++) {
table.columns.push({
text: 'Column ' + table.columns.length,
});
}
}
table.rows.forEach(row => {
const diff = cols - row.length;
for (let i = 0; i < diff; i++) {
row.push(null);
}
});
}
return different;
}
export function parseCSV(text: string, config?: ParseConfig): ParseResults { export function parseCSV(text: string, config?: ParseConfig): ParseResults {
const results = Papa.parse(text, { ...config, dynamicTyping: true, skipEmptyLines: true }); const results = Papa.parse(text, { ...config, dynamicTyping: true, skipEmptyLines: true });
...@@ -44,47 +73,32 @@ export function parseCSV(text: string, config?: ParseConfig): ParseResults { ...@@ -44,47 +73,32 @@ export function parseCSV(text: string, config?: ParseConfig): ParseResults {
}; };
} }
let same = true; const first = results.data.shift();
let cols = data[0].length; const table = {
data.forEach(row => { columns: first.map((v: any, index: number) => {
if (cols !== row.length) { if (!v) {
same = false; v = 'Column ' + (index + 1);
cols = Math.max(cols, row.length); }
} return {
}); text: v.toString().trim(),
} as Column;
// Use a second pass to update the sizes }),
if (!same) { rows: results.data,
type: 'table',
columnMap: {},
} as TableData;
const changed = checkAndFix(table);
if (changed > 0) {
errors.push({ errors.push({
type: 'warning', // A generalization of the error type: 'warning', // A generalization of the error
message: 'not all rows have the same width', message: 'not all rows have the same width. Changed:' + changed,
code: 'width', code: 'width',
row: 0, row: 0,
}); });
// Add null values to the end of all short arrays
data.forEach(row => {
const diff = cols - row.length;
for (let i = 0; i < diff; i++) {
row.push(null);
}
});
} }
const first = results.data.shift();
return { return {
table: { table,
columns: first.map((v: any, index: number) => {
if (!v) {
v = 'Column ' + (index + 1);
}
return {
text: v.toString().trim(),
} as Column;
}),
rows: results.data,
type: 'table',
columnMap: {},
} as TableData,
meta, meta,
errors, errors,
}; };
...@@ -92,6 +106,8 @@ export function parseCSV(text: string, config?: ParseConfig): ParseResults { ...@@ -92,6 +106,8 @@ export function parseCSV(text: string, config?: ParseConfig): ParseResults {
interface Props { interface Props {
config?: ParseConfig; config?: ParseConfig;
width: number;
height: number;
} }
interface State { interface State {
...@@ -128,14 +144,21 @@ class TableInputCSV extends React.PureComponent<Props, State> { ...@@ -128,14 +144,21 @@ class TableInputCSV extends React.PureComponent<Props, State> {
}; };
render() { render() {
const { width, height } = this.props;
const { table, errors } = this.state.results; const { table, errors } = this.state.results;
return ( return (
<div> <div
className={'gf-table-input-wrap'}
style={{
width: `${width}px`,
height: `${height}px`,
}}
>
<textarea value={this.state.text} onChange={this.handleChange} onBlur={this.handleBlur} /> <textarea value={this.state.text} onChange={this.handleChange} onBlur={this.handleBlur} />
<div> <footer>
BAR: / ROWS:{table.rows.length} / COLS:{table.columns.length} / {JSON.stringify(errors)} BAR: / ROWS:{table.rows.length} / COLS:{table.columns.length} / {JSON.stringify(errors)}
</div> </footer>
</div> </div>
); );
} }
......
.gf-table-input-wrap {
width: 100%;
}
.gf-table-input-wrap textarea {
height: 100%;
width: 100%;
resize: none;
}
.gf-table-input-wrap footer {
position: absolute;
bottom: 20px;
right: 20px;
border: 2px solid #222;
background: #ccc;
}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TableInputCSV renders correctly 1`] = `
<div>
<textarea
onBlur={[Function]}
onChange={[Function]}
value=""
/>
</div>
`;
@import 'CustomScrollbar/CustomScrollbar'; @import 'CustomScrollbar/CustomScrollbar';
@import 'DeleteButton/DeleteButton'; @import 'DeleteButton/DeleteButton';
@import 'ThresholdsEditor/ThresholdsEditor'; @import 'ThresholdsEditor/ThresholdsEditor';
@import 'Table/TableInputCSV';
@import 'Tooltip/Tooltip'; @import 'Tooltip/Tooltip';
@import 'Select/Select'; @import 'Select/Select';
@import 'PanelOptionsGroup/PanelOptionsGroup'; @import 'PanelOptionsGroup/PanelOptionsGroup';
......
import React from 'react';
import { AutoSizer } from 'react-virtualized';
export const withFullSizeStory = (component: React.ComponentType<any>, props: any) => (
<div
style={{
height: '100vh',
width: '100%',
}}
>
<AutoSizer>
{({ width, height }) => (
<>
{React.createElement(component, {
...props,
width,
height,
})}
</>
)}
</AutoSizer>
</div>
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment