...
 
Commits (5)
......@@ -37,6 +37,10 @@ All third party components incorporated into the DMX Tableview Software are lice
## Version History
**0.3.1**, Upcoming
* Debounce user input
**0.3.0** - Sep 02, 2019
* More performant aggregation of tableview data at server side (#56)
......
{
"name": "dm5-tableview",
"version": "0.3.0",
"version": "0.3.1-SNAPSHOT",
"description": "",
"author": "Daniel Mania & Malte Reißig",
"license": "AGPL-3.0",
......
......@@ -7,7 +7,7 @@
<name>DMX Tableview</name>
<groupId>systems.dmx</groupId>
<artifactId>dmx-tableview</artifactId>
<version>0.3.0</version>
<version>0.3.1-SNAPSHOT</version>
<packaging>bundle</packaging>
<parent>
......
......@@ -7,13 +7,13 @@
{{filteredRowCount}} of {{rowCount}} entries
</div>
<el-main>
<el-input clearable size="medium" class="global-search" placeholder="Search" v-model="filter.global">
<el-input @input="searchInput" clearable size="medium" class="global-search" placeholder="Search" v-model="filter.global">
</el-input>
<dm5-csv-button :data="csvData"></dm5-csv-button>
</el-main>
</el-container>
<el-table :data="filteredRows" :height="windowHeight">
<el-table :data="tableviewData" :height="windowHeight">
<el-table-column fixed="left" width="60">
<template slot-scope="scope">
......@@ -26,8 +26,8 @@
<template slot="header" slot-scope="scope">
<div class="title">{{ column.value }}</div>
<a @click.stop>
<el-input clearable v-model="filter[column.uri]" placeholder="Filter" size="mini"></el-input>
<a @click.stop><!-- do not sort on click -->
<el-input @input="searchInput" clearable v-model="filter[column.uri]" placeholder="Filter" size="mini"></el-input>
</a>
</template>
......@@ -75,13 +75,13 @@
<el-button slot="footer" class="dialog-footer" type="primary" @click="showTopic()">Show Topic</el-button>
</el-dialog>
</div>
</template>
<script>
import axios from 'axios';
import dm5 from 'dm5';
import Vue from "vue";
import CSVButton from "./dm5-csv-button";
......@@ -90,6 +90,9 @@ Vue.component("dm5-csv-button", CSVButton);
export default {
created () {
// initial dataset
this.tableviewData = this.data
// load topicmaps in tableview workspace
axios.get('/tableview/topicmaps/' + this.tableViewId)
.then(response => {
this.topicmaps = response.data
......@@ -132,43 +135,27 @@ export default {
dialogVisible: false,
windowHeight: undefined,
filteredRowCount: 0,
filter: {}
tableviewData: [],
filter: {},
inputs: {}
}
},
computed: {
watch: {
tableviewData: function() {
this.filteredRowCount = this.tableviewData.length
}
},
computed: {
topicmapTopics () {
return this.topicmaps && this.topicmaps.sort((t1, t2) => t1.value.localeCompare(t2.value))
},
filteredRows () {
let filteredData = this.data;
if (this.filter.global) {
filteredData = this.data.filter(row => this.rowIncludesQuery(row, this.filter.global))
}
let filteredRows = filteredData.filter(row =>
{
for (let column of this.columns) {
if (this.filter[column.uri] && !this.matches(row, column.uri)) {
return false;
}
}
return true
}
)
this.filteredRowCount = filteredRows.length
return filteredRows
},
csvData() {
csvData () {
let rows = [];
let originalRows = this.filteredRows.slice(0);
let originalRows = this.tableviewData.slice(0);
for (let i=0; i<originalRows.length; i++) {
let col = {};
for (let column of this.columns) {
......@@ -185,6 +172,26 @@ export default {
},
methods: {
searchInput: dm5.utils.debounce(function () {
this.computeTableViewData()
}, 300),
computeTableViewData () {
let filteredData = this.data
if (this.filter.global) {
filteredData = this.data.filter(row => this.rowIncludesQuery(row, this.filter.global))
}
let filteredRows = filteredData.filter(row => {
for (let column of this.columns) {
if (this.filter[column.uri] && !this.matches(row, column.uri)) {
return false
}
}
return true
})
this.tableviewData = filteredRows
},
matches (row, prop) {
const filter = this.filter[prop]
......@@ -194,16 +201,16 @@ export default {
matchesQuery (row, prop, query) {
return !filter || String(row.columns[prop].value).toLowerCase().includes(filter.global)
},
rowIncludesQuery(row, query) {
for (let col in row.columns) {
if (String(row.columns[col].value).toLowerCase().includes(query.toLowerCase())) {
return true
}
rowIncludesQuery (row, query) {
for (let col in row.columns) {
if (String(row.columns[col].value).toLowerCase().includes(query.toLowerCase())) {
return true
}
return false
}
return false
},
showTopic (topicmapId = this.topicmapId, topicId = this.topicId) {
this.dialogVisible = false
window.open(`/tableview/open-in-map/${topicmapId}/${topicId}`, '_blank')
......@@ -213,8 +220,7 @@ export default {
this.dialogVisible = true
this.topicId = id
},
topicmapTitleAppearsMultipleTimes(topicmap) {
topicmapTitleAppearsMultipleTimes (topicmap) {
if (!this.topicmaps) {
return false;
}
......
<template>
<div>
<dm5-tableview :title="tableTitle" :tableViewId="$route.params.id"
<dm5-tableview :title="tableTitle" :tableViewId="Number.parseInt($route.params.id)"
:data="data" :columns="columns"
:rowCount="csvDataRowCount"
v-loading="loading"/>
......
......@@ -10,7 +10,7 @@ import Vuex from 'vuex'
// 1) configure English as UI language
locale.use(lang)
console.log('[Tableview] 2019/09/02')
console.log('[Tableview] 2019/09/13')
// 2) Register Tableview UI components
Vue.use(Table)
......