Skip to content

Commit

Permalink
feature :: define a basic dataset type (#120)
Browse files Browse the repository at this point in the history
DataSet type is defined as two properties:

- `headers`: a list of objects defining columns
  - each column is itself defined by a `name` and
    an optional `type`. We'll probably add extra
    metadata later,

- `data`: a list of list of values

Use this type in the `DataViewer` component.

Related to ToucanToco/weaverbird#26
  • Loading branch information
adimascio authored May 6, 2019
1 parent 1347b46 commit d7b3df3
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 118 deletions.
45 changes: 13 additions & 32 deletions src/components/DataViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
</tr>
</thead>
<tbody class="data-viewer__body">
<tr class="data-viewer__row" v-for="(row, index) in dataset" :key="index">
<tr class="data-viewer__row" v-for="(row, index) in dataset.data" :key="index">
<DataViewerCell
v-for="columnName in columnNames"
:key="columnName"
:isSelected="isSelected(columnName)"
:value="getValue(row, columnName)"
v-for="(cell, cellidx) in row"
:key="cellidx"
:isSelected="isSelected(columnNames[cellidx])"
:value="cell"
/>
</tr>
</tbody>
Expand All @@ -28,21 +28,16 @@
<script lang="ts">
import _ from 'lodash';
import Vue from 'vue';
import { DataSet } from '@/lib/dataset';
import { Component, Prop } from 'vue-property-decorator';
import DataViewerCell from './DataViewerCell.vue';
/**
* @name DataRow
* @description A simple interface that represent a row from a dataset
*/
interface DataRow {
[key: string]: any;
}
/**
* @name DataViewer
* @description A Vue Component that displays data into a table
* @param {Array<DataRow>} dataset - The dataset that we want to display
* @param {DataSet} dataset - The dataset that we want to display
*/
@Component({
name: 'data-viewer',
Expand All @@ -52,10 +47,10 @@ interface DataRow {
})
export default class DataViewer extends Vue {
@Prop({
default: () => [],
type: Array,
default: () => ({ headers: [], data: [] }),
type: Object,
})
dataset!: Array<DataRow>;
dataset!: DataSet;
/**
* @description Array of column's name selected by the user
Expand All @@ -67,7 +62,7 @@ export default class DataViewer extends Vue {
* @return {boolean}
*/
get datasetIsntEmpty() {
return this.dataset.length !== 0;
return this.dataset.data.length !== 0;
}
/**
Expand All @@ -77,10 +72,7 @@ export default class DataViewer extends Vue {
* @return {Array<string>}
*/
get columnNames() {
return _.chain(this.dataset)
.flatMap(row => _.keys(row))
.uniq()
.value();
return this.dataset.headers.map(col => col.name);
}
/**
Expand Down Expand Up @@ -108,17 +100,6 @@ export default class DataViewer extends Vue {
return this.selectedColumns.includes(column);
}
/**
* @description Return the value from a specific cell
*
* @param {DataRow} row - A row from our dataset
* @param {string} column - A column name
* @return {any}
*/
getValue(row: DataRow, column: string) {
return row[column];
}
/**
* @description Select or deselect a column by its name
*
Expand Down
31 changes: 31 additions & 0 deletions src/lib/dataset/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* This module contains helpers and definitions related to datasets.
*/

export type DataSetColumn = {
name: string;
type?: 'integer' | 'float' | 'boolean' | 'string' | 'date' | 'object';
};

/**
* Here's a dataset example:
* ```javascript
* {
* headers: [
* { name: 'col1' },
* { name: 'col2' },
* { name: 'col3' }
* ],
* data: [
* [ 'ab', 12, true ],
* [ 'cd', 13, null ]
* ]
* }
*
* NOTE that we use `null` to represent empty values.
* ```
*/
export type DataSet = {
headers: Array<DataSetColumn>;
data: Array<Array<any>>;
};
33 changes: 33 additions & 0 deletions src/lib/dataset/mongo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* mongo specific helpers for dataset manipulation.
*/

import { DataSet } from '@/lib/dataset';

type MongoDocument = { [k: string]: any };
export type MongoResults = Array<MongoDocument>;

/**
* transform a mongo resultset (i.e. a list of json documents) into
* a `DataSet` structure
*/
export function mongoResultsToDataset(results: MongoResults): DataSet {
const dataset: DataSet = { headers: [], data: [] };
if (results.length) {
const colnames = results
// get list of list of key
.map(row => Object.keys(row))
// then flatten them
.flat()
// and remove duplicates by keeping the _first_ occurence
.filter((col, colidx, array) => array.indexOf(col) === colidx);
// transform set of names to list of DataSetColumn objects
dataset.headers = colnames.map(name => ({ name }));
for (const row of results) {
dataset.data.push(
dataset.headers.map(coldef => (row.hasOwnProperty(coldef.name) ? row[coldef.name] : null)),
);
}
}
return dataset;
}
50 changes: 29 additions & 21 deletions stories/data-viewer.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
import { storiesOf } from '@storybook/vue';
import {storiesOf} from '@storybook/vue';

import { DataViewer } from '../dist/storybook/components';
import {DataViewer} from '../dist/storybook/components';

const stories = storiesOf('DataViewer', module);

stories.add('empty', () => ({
components: { DataViewer },
template: `
components: {DataViewer},
template: `
<data-viewer>
</data-viewer>
`,
}));
}));

stories.add('simple', () => ({
components: { DataViewer },
props: {
dataset: {
default() {
return [
{ columnA: 'value1', columnB: 'value2', columnC: 'value3' },
{ columnA: 'value4', columnB: 'value5', columnC: 'value6' },
{ columnA: 'value7', columnB: 'value8', columnC: 'value9' },
{ columnA: 'value10', columnB: 'value11', columnC: 'value12' },
{ columnA: 'value13', columnB: { obj: 'value14' }, columnC: undefined },
];
},
},
},
template: `
components: {DataViewer},
props: {
dataset: {
default() {
return {
headers:
[
{name: 'columnA'},
{name: 'columnB'},
{name: 'columnC'},
],
data: [
['value1', 'value2', 'value3'],
['value4', 'value5', 'value6'],
['value7', 'value8', 'value9'],
['value10', 'value11', 'value12'],
['value10', {obj: 'value14'}, null],
]
}
},
},
},
template: `
<data-viewer
:dataset="dataset"
>
</data-viewer>
`,
}));
}));
Loading

0 comments on commit d7b3df3

Please sign in to comment.