Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(components): add data-table
Browse files Browse the repository at this point in the history
closes #141
Johannes Werner committed Jun 16, 2018
1 parent bb12ac0 commit a03b854
Showing 16 changed files with 847 additions and 1 deletion.
1 change: 1 addition & 0 deletions i18n/de.json
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
"components.calendar.thursday.short": "D",
"components.calendar.tuesday.short": "D",
"components.calendar.wednesday.short": "M",
"components.dataTable.noResults": "No results found!",
"components.formExample.zipCode.error": "Please enter a Number",
"components.markdown": "### Markdown support\n - build on top of marked\n - server side rendering!!!\n - `github style` markdown",
"components.pagination.next": "Next",
1 change: 1 addition & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
"components.calendar.thursday.short": "T",
"components.calendar.tuesday.short": "T",
"components.calendar.wednesday.short": "W",
"components.dataTable.noResults": "No results found!",
"components.formExample.zipCode.error": "Please enter a Number",
"components.markdown": "### Markdown support\n - build on top of marked\n - server side rendering!!!\n - `github style` markdown",
"components.pagination.next": "Next",
1 change: 1 addition & 0 deletions i18n/pt.json
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
"components.calendar.thursday.short": "T",
"components.calendar.tuesday.short": "T",
"components.calendar.wednesday.short": "W",
"components.dataTable.noResults": "No results found!",
"components.formExample.zipCode.error": "Please enter a Number",
"components.markdown": "### Markdown support\n - build on top of marked\n - server side rendering!!!\n - `github style` markdown",
"components.pagination.next": "Next",
1 change: 1 addition & 0 deletions src/app/components/Components/Components.spec.ts
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ describe('Components.vue', () => {
wrapper.vm.onRequest('foo');
wrapper.vm.onRequest('foo', false);
wrapper.vm.onAutocompleteChange();
wrapper.vm.dataTableClick();

expect(wrapper.find('h1').text()).toBe('Components');
});
20 changes: 19 additions & 1 deletion src/app/components/Components/Components.vue
Original file line number Diff line number Diff line change
@@ -470,6 +470,17 @@
<vue-carousel :images="images" />
</vue-grid-item>
</vue-grid-row>

<vue-grid-row>
<vue-grid-item class="vueGridItem">
<h2>DataTable</h2>
<vue-data-table
:header="dataTableHeader"
:data="dataTableData"
placeholder="Search"
@click="dataTableClick" />
</vue-grid-item>
</vue-grid-row>
</vue-grid>
</div>
</template>
@@ -509,6 +520,8 @@
import { IAutocompleteOption } from '../../shared/components/VueAutocomplete/IAutocompleteOption';
import VueTruncate from '../../shared/components/VueTruncate/VueTruncate';
import VueCarousel from '../../shared/components/VueCarousel/VueCarousel';
import VueDataTable from '../../shared/components/VueDataTable/VueDataTable';
import { dataTableDataFixture, dataTableHeaderFixture } from '../../shared/components/VueDataTable/DataTableFixtures';
export default {
metaInfo: {
@@ -557,6 +570,7 @@
],
},
components: {
VueDataTable,
VueCarousel,
VueTruncate,
FormExample,
@@ -663,6 +677,8 @@
url: 'https://images.unsplash.com/photo-1492970471430-bc6bd7eb2b13?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=9893bc89e46e2b77a5d8c091fbba04e9&auto=format&fit=crop&w=2710&q=80',
},
],
dataTableHeader: dataTableHeaderFixture,
dataTableData: dataTableDataFixture,
};
},
methods: {
@@ -687,7 +703,6 @@
console.log(option);
this.selectedOption = option;
},
/* istanbul ignore next */
onRequest(query: string, shouldReturn: boolean = true) {
this.autocompleteLoading = true;
@@ -711,6 +726,9 @@
onAutocompleteChange(option: IAutocompleteOption) {
console.log(option);
},
dataTableClick(row: any) {
console.log(row);
},
},
};
</script>
42 changes: 42 additions & 0 deletions src/app/shared/components/VueDataTable/DataTableFixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { IDataTableHeader } from './IDataTable';

export const dataTableHeaderFixture: IDataTableHeader = {
id: {
visible: false,
},
firstname: {
title: 'Firstname',
},
lastname: {
title: 'Lastname',
},
age: {
title: 'Age',
},
address: {
title: 'Address',
},
};

export const dataTableDataFixture = [
{ id: 1, firstname: 'Toni', lastname: 'Stark', address: 'Wallstreet 1', age: 37 },
{ id: 2, firstname: 'Richard', lastname: 'Brenson', address: 'Aurora', age: 19 },
{ id: 3, firstname: 'Julia', lastname: 'Roberts', address: 'Elmstreet', age: 3 },
{ id: 4, firstname: 'Justus', lastname: 'Jonas', address: 'Mainvalley', age: 56 },
{ id: 5, firstname: 'Sheldon', lastname: 'Cooper', address: 'BigBang', age: 42 },
{ id: 6, firstname: 'Toni', lastname: 'Stark', address: 'Wallstreet 1', age: 37 },
{ id: 8, firstname: 'Julia', lastname: 'Roberts', address: 'Elmstreet', age: 3 },
{ id: 10, firstname: 'Sheldon', lastname: 'Cooper', address: 'BigBang', age: 42 },
{ id: 7, firstname: 'Richard', lastname: 'Brenson', address: 'Aurora', age: 19 },
{ id: 9, firstname: 'Justus', lastname: 'Jonas', address: 'Mainvalley', age: 56 },
{ id: 12, firstname: 'Richard', lastname: 'Brenson', address: 'Aurora', age: 19 },
{ id: 11, firstname: 'Toni', lastname: 'Stark', address: 'Wallstreet 1', age: 37 },
{ id: 14, firstname: 'Justus', lastname: 'Jonas', address: 'Mainvalley', age: 56 },
{ id: 15, firstname: 'Sheldon', lastname: 'Cooper', address: 'BigBang', age: 42 },
{ id: 18, firstname: 'Julia', lastname: 'Roberts', address: 'Elmstreet', age: 3 },
{ id: 20, firstname: 'Sheldon', lastname: 'Cooper', address: 'BigBang', age: 42 },
{ id: 13, firstname: 'Julia', lastname: 'Roberts', address: 'Elmstreet', age: 3 },
{ id: 17, firstname: 'Richard', lastname: 'Brenson', address: 'Aurora', age: 19 },
{ id: 19, firstname: 'Justus', lastname: 'Jonas', address: 'Mainvalley', age: 56 },
{ id: 16, firstname: 'Toni', lastname: 'Stark', address: 'Wallstreet 1', age: 37 },
];
15 changes: 15 additions & 0 deletions src/app/shared/components/VueDataTable/IDataTable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export interface IDataTableHeader {
[key: string]: IDataTableHeaderItem;
}

export interface IDataTableHeaderItem {
title?: string;
visible?: boolean;
sortKey?: string;
}

export interface IComputedDataRowColumn {
key: string;
value: any;
visible: boolean;
}
166 changes: 166 additions & 0 deletions src/app/shared/components/VueDataTable/VueDataTable.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { createLocalVue, mount } from '@vue/test-utils';
import { i18n } from '../../plugins/i18n/i18n';
import VueDataTable from './VueDataTable.vue';
import { IDataTableHeader } from './IDataTable';
import VueDataTableSearch from './VueDataTableSearch/VueDataTableSearch.vue';
import VueDataTableHeader from './VueDataTableHeader/VueDataTableHeader.vue';
import VueDataTableRow from './VueDataTableRow/VueDataTableRow.vue';
import VuePagination from '../VuePagination/VuePagination.vue';
import { dataTableDataFixture, dataTableHeaderFixture } from './DataTableFixtures';

const localVue = createLocalVue();

describe('VueDataTable.vue', () => {
const header: IDataTableHeader = dataTableHeaderFixture;
const data: any[] = dataTableDataFixture;

test('renders component', () => {
const wrapper = mount(VueDataTable,
{
i18n,
localVue,
propsData: {
header,
data,
},
},
);

expect(wrapper.findAll(VueDataTableSearch)).toHaveLength(1);
expect(wrapper.findAll(VueDataTableHeader)).toHaveLength(1);
expect(wrapper.findAll(VueDataTableRow)).toHaveLength(5);
expect(wrapper.findAll(VuePagination)).toHaveLength(1);
});

test('renders component without search', () => {
const wrapper = mount(VueDataTable,
{
i18n,
localVue,
propsData: {
header,
data,
showSearch: false,
},
},
);

expect(wrapper.findAll(VueDataTableSearch)).toHaveLength(0);
expect(wrapper.findAll(VueDataTableHeader)).toHaveLength(1);
expect(wrapper.findAll(VueDataTableRow)).toHaveLength(5);
expect(wrapper.findAll(VuePagination)).toHaveLength(1);
});

test('should filter data', () => {
const wrapper = mount(VueDataTable,
{
i18n,
localVue,
propsData: {
header,
data,
},
},
) as any;

wrapper.vm.searchTerm = 'julia';
expect(wrapper.findAll(VueDataTableSearch)).toHaveLength(1);
expect(wrapper.findAll(VueDataTableHeader)).toHaveLength(1);
expect(wrapper.findAll(VueDataTableRow)).toHaveLength(4);

wrapper.vm.searchTerm = 'z';
expect(wrapper.findAll(VueDataTableSearch)).toHaveLength(1);
expect(wrapper.findAll(VueDataTableHeader)).toHaveLength(1);
expect(wrapper.findAll('.noResults')).toHaveLength(1);
expect(wrapper.findAll(VueDataTableRow)).toHaveLength(0);
});

test('should sort data', () => {
const wrapper = mount(VueDataTable,
{
i18n,
localVue,
propsData: {
header,
data,
},
},
) as any;

wrapper.vm.sortKey = 'firstname';

expect(wrapper.vm.sortedData[0].firstname).toBe('Julia');
expect(wrapper.vm.sortedData[1].firstname).toBe('Julia');
expect(wrapper.vm.sortedData[2].firstname).toBe('Julia');
expect(wrapper.vm.sortedData[3].firstname).toBe('Julia');

wrapper.vm.sortDirection = 'desc';

expect(wrapper.vm.sortedData[0].firstname).toBe('Toni');
expect(wrapper.vm.sortedData[1].firstname).toBe('Toni');
expect(wrapper.vm.sortedData[2].firstname).toBe('Toni');
expect(wrapper.vm.sortedData[3].firstname).toBe('Toni');
});

test('should change page', () => {
const wrapper = mount(VueDataTable,
{
i18n,
localVue,
propsData: {
header,
data,
},
},
) as any;

wrapper.vm.paginationClick(2);

expect(wrapper.vm.currentPage).toBe(1);
});

test('should emit click', () => {
const wrapper = mount(VueDataTable,
{
i18n,
localVue,
propsData: {
header,
data,
},
},
) as any;

wrapper.vm.rowClick('foo');

expect(wrapper.emitted('click')).toBeTruthy();
});

test('should emit click', () => {
const wrapper = mount(VueDataTable,
{
i18n,
localVue,
propsData: {
header,
data,
},
},
) as any;

expect(wrapper.vm.sortKey).toBe(null);
expect(wrapper.vm.sortDirection).toBe('asc');

wrapper.vm.columnClick({ sortKey: 'foo' });
expect(wrapper.vm.sortKey).toBe('foo');
expect(wrapper.vm.sortDirection).toBe('asc');

wrapper.vm.columnClick({ sortKey: 'foo' });
expect(wrapper.vm.sortKey).toBe('foo');
expect(wrapper.vm.sortDirection).toBe('desc');

wrapper.vm.columnClick({ sortKey: 'foo' });
expect(wrapper.vm.sortKey).toBe(null);
expect(wrapper.vm.sortDirection).toBe('asc');
});
});
40 changes: 40 additions & 0 deletions src/app/shared/components/VueDataTable/VueDataTable.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { storiesOf } from '@storybook/vue';
import VueInfoAddon from 'storybook-addon-vue-info';
import { action } from '@storybook/addon-actions';
import VueDataTable from './VueDataTable.vue';
import { i18n } from '../../plugins/i18n/i18n';
import { dataTableDataFixture, dataTableHeaderFixture } from './DataTableFixtures';

const story = (storiesOf('VueDataTable', module) as any);

story.addDecorator(VueInfoAddon);

story.add('Default', () => ({
i18n,
components: { VueDataTable },
data() {
return {
header: dataTableHeaderFixture,
data: dataTableDataFixture,
};
},
template: `<vue-data-table :header="header" :data="data" placeholder="Search" @click="action" />`,
methods: {
action: action('@onClick'),
},
}));

story.add('All Props', () => ({
i18n,
components: { VueDataTable },
data() {
return {
header: dataTableHeaderFixture,
data: dataTableDataFixture,
};
},
template: `<vue-data-table :header="header" :data="data" :show-search="false" :page="1" :max-rows="10" @click="action" />`,
methods: {
action: action('@onClick'),
},
}));
Loading

0 comments on commit a03b854

Please sign in to comment.