mock data an implement basic datatable

This commit is contained in:
busti 2019-11-14 19:30:00 +01:00
parent 66b1e070d6
commit 46be8e8629
7 changed files with 74 additions and 17 deletions

View file

@ -15,6 +15,7 @@ module.exports = {
'vue' 'vue'
], ],
'rules': { 'rules': {
"no-console": "off",
'indent': [ 'indent': [
'error', 'error',
2 2

5
package-lock.json generated
View file

@ -8500,6 +8500,11 @@
"integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
"dev": true "dev": true
}, },
"ramda": {
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz",
"integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ=="
},
"randombytes": { "randombytes": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",

View file

@ -15,6 +15,7 @@
"core-js": "^3.3.2", "core-js": "^3.3.2",
"jquery": "^3.4.1", "jquery": "^3.4.1",
"popper.js": "^1.16.0", "popper.js": "^1.16.0",
"ramda": "^0.26.1",
"vue": "^2.6.10", "vue": "^2.6.10",
"vuex": "^3.1.2" "vuex": "^3.1.2"
}, },

View file

@ -3,7 +3,11 @@
<Navbar/> <Navbar/>
<div class="container mt-2"> <div class="container mt-2">
<Table/> <Table
:columns="['uid', 'description', 'box', 'image']"
:items="loadedItems"
:keyName="'uid'"
/>
</div> </div>
</div> </div>
</template> </template>
@ -11,15 +15,17 @@
<script> <script>
import Table from '@/components/Table'; import Table from '@/components/Table';
import Navbar from '@/components/Navbar'; import Navbar from '@/components/Navbar';
import { mapState } from 'vuex';
export default { export default {
name: 'app', name: 'app',
components: { Navbar, Table }, components: { Navbar, Table },
computed: mapState(['loadedItems'])
}; };
</script> </script>
<style> <style>
body, html, #app { body, html, #app {
background: #222; background: #000;
} }
</style> </style>

View file

@ -1,23 +1,59 @@
<template> <template>
<table class="table table-striped table-dark"> <table class="table table-striped table-dark">
<thead> <thead>
<tr> <tr>
<th scope="col" v-for="(column, index) in columns" :key="index">{{ column.name }}</th> <th scope="col" v-for="(column, index) in columns" :key="index">
</tr> <button class="btn text-light" v-on:click="toggleSort(column)">
{{ column }}
<span :class="{ 'text-info': column === sortBy }">
<font-awesome-icon :icon="sortIcon(column)"/>
</span>
</button>
</th>
</tr>
</thead> </thead>
<tbody>
<tr v-for="item in internalItems" :key="item[keyName]">
<td v-for="(column, index) in columns" :key="index">{{ item[column] }}</td>
</tr>
</tbody>
</table> </table>
</template> </template>
<script> <script>
import * as R from 'ramda';
export default { export default {
name: 'Table', name: 'Table',
data: () => ({ props: ['columns', 'items', 'keyName'],
columns: [ data: (self) => ({
{ name: 'uid', sortFn: (items) => items }, sortBy: self.keyName,
{ name: 'description', sortFn: (items) => items }, ascend: true
{ name: 'box', sortFn: (items) => items }, }),
{ name: 'image', sortFn: (items) => items } computed: {
] internalItems() {
}) const sortByOrd = R.sortBy(R.prop(this.sortBy));
const sorted = sortByOrd(this.items, [this.sortBy]);
return this.ascend ? sorted : R.reverse(sorted);
}
},
methods: {
sortIcon(column) {
if (column !== this.sortBy) return 'sort';
if (this.ascend) return 'sort-up';
return 'sort-down';
},
toggleSort(column) {
if (column === this.sortBy)
this.ascend = !this.ascend;
this.sortBy = column;
}
}
}; };
</script> </script>
<style>
.table-body-move {
transition: transform 1s;
}
</style>

View file

@ -9,10 +9,10 @@ import 'bootstrap/dist/js/bootstrap.min.js';
// fontawesome // fontawesome
import { library } from '@fortawesome/fontawesome-svg-core'; import { library } from '@fortawesome/fontawesome-svg-core';
import { faPlus, faCheckCircle, faEdit, faTrash, faCat, faSyncAlt } from '@fortawesome/free-solid-svg-icons'; import { faPlus, faCheckCircle, faEdit, faTrash, faCat, faSyncAlt, faSort, faSortUp, faSortDown } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
library.add(faPlus, faCheckCircle, faEdit, faTrash, faCat, faSyncAlt); library.add(faPlus, faCheckCircle, faEdit, faTrash, faCat, faSyncAlt, faSort, faSortUp, faSortDown);
Vue.component('font-awesome-icon', FontAwesomeIcon); Vue.component('font-awesome-icon', FontAwesomeIcon);

View file

@ -7,7 +7,15 @@ export default new Vuex.Store({
state: { state: {
events: ['35c3', 'camp19', '36c3'], events: ['35c3', 'camp19', '36c3'],
activeEvent: '36c3', activeEvent: '36c3',
loadedItems: [] loadedItems: [
{ uid: 1, description: 'sleeping bag', box: 7, image: 41 },
{ uid: 2, description: 'tent', box: 7, image: 23 },
{ uid: 3, description: 'chest', box: 7, image: 52 },
{ uid: 4, description: 'power supply black', box: 5, image: 62 },
{ uid: 5, description: 'pullover yellow "pesthörnchen"', box: 5, image: 84 },
{ uid: 6, description: '"blue black second skin"', box: 6, image: 72 },
{ uid: 7, description: '"the bike blog" bottle orange', box: 6, image: 71 }
]
}, },
mutations: { mutations: {
changeEvent(state, event) { changeEvent(state, event) {