mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
styles and pagination for sql results table
This commit is contained in:
54
package-lock.json
generated
54
package-lock.json
generated
@@ -5123,11 +5123,6 @@
|
|||||||
"whatwg-url": "^7.0.0"
|
"whatwg-url": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"date-fns": {
|
|
||||||
"version": "2.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz",
|
|
||||||
"integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ=="
|
|
||||||
},
|
|
||||||
"de-indent": {
|
"de-indent": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
|
||||||
@@ -5457,11 +5452,6 @@
|
|||||||
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
|
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"diacriticless": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/diacriticless/-/diacriticless-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-592peMKRlgm7SK7h78XeajN71MM="
|
|
||||||
},
|
|
||||||
"diff": {
|
"diff": {
|
||||||
"version": "3.5.0",
|
"version": "3.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
||||||
@@ -9667,37 +9657,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
|
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
|
||||||
},
|
},
|
||||||
"lodash.assign": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
|
|
||||||
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
|
|
||||||
},
|
|
||||||
"lodash.clonedeep": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
|
||||||
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
|
|
||||||
},
|
|
||||||
"lodash.defaultsdeep": {
|
"lodash.defaultsdeep": {
|
||||||
"version": "4.6.1",
|
"version": "4.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz",
|
||||||
"integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
|
"integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash.filter": {
|
|
||||||
"version": "4.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
|
|
||||||
"integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4="
|
|
||||||
},
|
|
||||||
"lodash.foreach": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
|
|
||||||
"integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM="
|
|
||||||
},
|
|
||||||
"lodash.isequal": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
|
||||||
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
|
||||||
},
|
|
||||||
"lodash.kebabcase": {
|
"lodash.kebabcase": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
|
||||||
@@ -15907,20 +15872,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-good-table": {
|
|
||||||
"version": "2.21.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-good-table/-/vue-good-table-2.21.0.tgz",
|
|
||||||
"integrity": "sha512-e384AGlmEBG0CfTkZXN/OZe1O58V2mbxQafsKqzVrqvROcMZsa9iSyK11D4YS2JzlJo9mRqsad4/vrV/U/Xbdw==",
|
|
||||||
"requires": {
|
|
||||||
"date-fns": "^2.0.0-beta.4",
|
|
||||||
"diacriticless": "1.0.1",
|
|
||||||
"lodash.assign": "^4.2.0",
|
|
||||||
"lodash.clonedeep": "^4.5.0",
|
|
||||||
"lodash.filter": "^4.6.0",
|
|
||||||
"lodash.foreach": "^4.5.0",
|
|
||||||
"lodash.isequal": "^4.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vue-hot-reload-api": {
|
"vue-hot-reload-api": {
|
||||||
"version": "2.3.4",
|
"version": "2.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
|
||||||
@@ -15992,6 +15943,11 @@
|
|||||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"vuejs-paginate": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuejs-paginate/-/vuejs-paginate-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-gnwyXlmCiDOu9MLWxN5UJ4PGijKGNOMpHG8ujsrynCzTJljn/rp7Jq0WiDGDAMi5/u0AHuYIHhced+tUW4jblA=="
|
||||||
|
},
|
||||||
"vuex": {
|
"vuex": {
|
||||||
"version": "3.5.1",
|
"version": "3.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz",
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
"sqlite-parser": "^1.0.1",
|
"sqlite-parser": "^1.0.1",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-codemirror": "^4.0.6",
|
"vue-codemirror": "^4.0.6",
|
||||||
"vue-good-table": "^2.21.0",
|
|
||||||
"vue-react": "^1.2.0",
|
"vue-react": "^1.2.0",
|
||||||
"vue-router": "^3.2.0",
|
"vue-router": "^3.2.0",
|
||||||
|
"vuejs-paginate": "^2.1.0",
|
||||||
"vuex": "^3.4.0"
|
"vuex": "^3.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
/* width */
|
/* width */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 5px;
|
width: 5px;
|
||||||
}
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Track */
|
/* Track */
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
background: #ebf0f8;
|
background: transparent;
|
||||||
}
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle */
|
/* Handle */
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: var(--color-accent);
|
background: var(--color-accent);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +1,37 @@
|
|||||||
:root {
|
:root {
|
||||||
--color-white: #ffffff;
|
--color-white: #ffffff;
|
||||||
--color-gray-light: #F3F6FA;
|
--color-gray-light: #F3F6FA;
|
||||||
--color-gray-light-2: #DFE8F3;
|
--color-gray-light-2: #DFE8F3;
|
||||||
--color-gray-light-3: #C8D4E3;
|
--color-gray-light-3: #C8D4E3;
|
||||||
--color-gray-light-4:#EBF0F8;
|
--color-gray-light-4:#EBF0F8;
|
||||||
--color-gray-medium: #A2B1C6;
|
--color-gray-medium: #A2B1C6;
|
||||||
--color-gray-dark: #506784;
|
--color-gray-dark: #506784;
|
||||||
--color-blue-medium: #119DFF;
|
--color-blue-medium: #119DFF;
|
||||||
--color-blue-dark: #0D76BF;
|
--color-blue-dark: #0D76BF;
|
||||||
--color-blue-dark-2: #2A3F5F;
|
--color-blue-dark-2: #2A3F5F;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--color-bg-light: var(--color-gray-light);
|
--color-bg-light: var(--color-gray-light);
|
||||||
--color-bg-light-2: var(--color-gray-light-2);
|
--color-bg-light-2: var(--color-gray-light-2);
|
||||||
--color-accent: var(--color-blue-medium);
|
--color-bg-dark: var(--color-gray-dark);
|
||||||
--color-accent-shade: var(--color-blue-dark);
|
--color-accent: var(--color-blue-medium);
|
||||||
--color-border-light: var(--color-gray-light-2);
|
--color-accent-shade: var(--color-blue-dark);
|
||||||
--color-border: var(--color-gray-light-3);
|
--color-border-light: var(--color-gray-light-2);
|
||||||
--color-text-light: var(--color-white);
|
--color-border: var(--color-gray-light-3);
|
||||||
--color-text-light-2: var(--color-gray-medium);
|
--color-text-light: var(--color-white);
|
||||||
--color-text-base: var(--color-gray-dark);
|
--color-text-light-2: var(--color-gray-medium);
|
||||||
--color-text-medium: var(--color-gray-medium);
|
--color-text-base: var(--color-gray-dark);
|
||||||
--color-text-active: var(--color-blue-dark-2);
|
--color-text-medium: var(--color-gray-medium);
|
||||||
|
--color-text-active: var(--color-blue-dark-2);
|
||||||
|
|
||||||
--shadow: 0 1px 2px rgba(42, 63, 95, 0.7);
|
--shadow: 0 1px 2px rgba(42, 63, 95, 0.7);
|
||||||
|
|
||||||
|
--border-radius-big: 5px;
|
||||||
|
--border-radius-medium: 3px;
|
||||||
|
--border-radius-medium-2: 4px;
|
||||||
|
--border-radius-small: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
--border-radius-big: 5px;
|
|
||||||
--border-radius-medium: 3px;
|
|
||||||
--border-radius-medium-2: 4px;
|
|
||||||
--border-radius-small: 2px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
97
src/components/Pager.vue
Normal file
97
src/components/Pager.vue
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<template>
|
||||||
|
<paginate
|
||||||
|
:page-count="pageCount"
|
||||||
|
:page-range="5"
|
||||||
|
:margin-pages="1"
|
||||||
|
:prev-text="chevron"
|
||||||
|
:next-text="chevron"
|
||||||
|
:no-li-surround="true"
|
||||||
|
container-class="paginator-continer"
|
||||||
|
page-link-class="paginator-page-link"
|
||||||
|
active-class="paginator-active-page"
|
||||||
|
break-view-link-class="paginator-break"
|
||||||
|
next-link-class="paginator-next"
|
||||||
|
prev-link-class="paginator-prev"
|
||||||
|
disabled-class="paginator-disabled"
|
||||||
|
v-model="page"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Paginate from 'vuejs-paginate'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Pager',
|
||||||
|
components: { Paginate },
|
||||||
|
props: ['pageCount', 'value'],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
page: this.value,
|
||||||
|
chevron: `
|
||||||
|
<svg width="9" height="9" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0.721924 9.93097L4.85292 5.79997L0.721924 1.66897L1.99992 0.399973L7.39992 5.79997L1.99992 11.2L0.721924 9.93097Z" fill="#506784"/>
|
||||||
|
</svg>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
page () {
|
||||||
|
this.$emit('input', this.page)
|
||||||
|
},
|
||||||
|
value () {
|
||||||
|
this.page = this.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.paginator-continer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
>>> .paginator-page-link {
|
||||||
|
padding: 2px 3px;
|
||||||
|
margin: 0 5px;
|
||||||
|
display: block;
|
||||||
|
color: var(--color-text-base);
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
>>> .paginator-page-link:hover {
|
||||||
|
color: var(--color-text-active);
|
||||||
|
}
|
||||||
|
>>> .paginator-page-link:active,
|
||||||
|
>>> .paginator-page-link:visited,
|
||||||
|
>>> .paginator-page-link:focus,
|
||||||
|
>>> .paginator-next:active,
|
||||||
|
>>> .paginator-next:visited,
|
||||||
|
>>> .paginator-next:focus,
|
||||||
|
>>> .paginator-prev:active,
|
||||||
|
>>> .paginator-prev:visited,
|
||||||
|
>>> .paginator-prev:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
>>> .paginator-active-page,
|
||||||
|
>>> .paginator-active-page:hover {
|
||||||
|
color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
>>> .paginator-break:hover,
|
||||||
|
>>> .paginator-disabled:hover {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
>>> .paginator-prev svg {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
>>> .paginator-next:hover path,
|
||||||
|
>>> .paginator-prev:hover path {
|
||||||
|
fill: var(--color-text-active);
|
||||||
|
}
|
||||||
|
>>> .paginator-disabled path,
|
||||||
|
>>> .paginator-disabled:hover path {
|
||||||
|
fill: var(--color-text-light-2);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,35 +1,183 @@
|
|||||||
<template>
|
<template>
|
||||||
<vue-good-table v-if="data" :columns="columns" :rows="rows"/>
|
<div>
|
||||||
|
<div id="rounded-bg">
|
||||||
|
<div id="header-container" ref="header-container">
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
v-for="(th, index) in header"
|
||||||
|
class="fixed-header"
|
||||||
|
:style="{ width: `${th.width}px` }"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
{{ th.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="table-container" ref="table-container" @scroll="onScrollTable" :style="{height: `${height}px`}">
|
||||||
|
<table id="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th v-for="(th,index) in data.columns" :key="index">
|
||||||
|
<div class="cell-data" :style="cellStyle">{{ th }}</div>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(row,index) in currentPageData" :key="index">
|
||||||
|
<td v-for="(value, valIndex) in row" :key="valIndex">
|
||||||
|
<div class="cell-data" :style="cellStyle">{{ value }}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-footer">
|
||||||
|
<div class="table-footer-count">
|
||||||
|
{{ data.values.length}} {{data.values.length === 1 ? 'row' : 'rows'}} retrieved
|
||||||
|
</div>
|
||||||
|
<pager v-show="pageCount > 1" :page-count="pageCount" v-model="currentPage" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import 'vue-good-table/dist/vue-good-table.css'
|
import Pager from '@/components/Pager'
|
||||||
import { VueGoodTable } from 'vue-good-table'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SqlTable',
|
name: 'SqlTable',
|
||||||
components: { VueGoodTable },
|
components: { Pager },
|
||||||
props: ['data'],
|
props: ['data', 'height'],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
header: null,
|
||||||
|
tableWidth: null,
|
||||||
|
currentPage: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
columns () {
|
cellStyle () {
|
||||||
const columns = []
|
const eq = this.tableWidth / this.data.columns.length
|
||||||
this.data.columns.forEach(column => {
|
|
||||||
columns.push({ label: column, field: column })
|
return { maxWidth: `${Math.max(eq, 100)}px` }
|
||||||
})
|
|
||||||
return columns
|
|
||||||
},
|
},
|
||||||
rows () {
|
pageSize () {
|
||||||
const rows = []
|
return Math.max(Math.floor(this.height / 40), 20)
|
||||||
this.data.values.forEach(row => {
|
},
|
||||||
const newRow = {}
|
pageCount () {
|
||||||
row.forEach((value, index) => {
|
return Math.ceil(this.data.values.length / this.pageSize)
|
||||||
const column = this.data.columns[index]
|
},
|
||||||
newRow[column] = value
|
currentPageData () {
|
||||||
|
const start = (this.currentPage - 1) * this.pageSize
|
||||||
|
return this.data.values.slice(start, start + this.pageSize)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
calculateHeadersWidth () {
|
||||||
|
this.tableWidth = this.$refs['table-container'].offsetWidth
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.header = Array.from(document.querySelectorAll('th')).map(th => {
|
||||||
|
return { name: th.innerText, width: th.offsetWidth }
|
||||||
})
|
})
|
||||||
rows.push(newRow)
|
|
||||||
})
|
})
|
||||||
return rows
|
},
|
||||||
|
onScrollTable () {
|
||||||
|
this.$refs['header-container'].scrollLeft = this.$refs['table-container'].scrollLeft
|
||||||
|
},
|
||||||
|
functionName () {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
new ResizeObserver(this.calculateHeadersWidth).observe(document.getElementById('table'))
|
||||||
|
this.calculateHeadersWidth()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
currentPageData: 'calculateHeadersWidth',
|
||||||
|
data () {
|
||||||
|
this.currentPage = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#rounded-bg {
|
||||||
|
padding: 40px 5px 5px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#header-container {
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
padding-left: 6px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: var(--color-bg-dark);
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-container div {
|
||||||
|
display: flex;
|
||||||
|
width: fit-content;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
#table-container {
|
||||||
|
width: 100%;
|
||||||
|
/* height: 200px; */
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
min-width: 100%;
|
||||||
|
margin-top: -40px;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
thead th, .fixed-header {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: var(--color-bg-dark);
|
||||||
|
color: var(--color-text-light);
|
||||||
|
border-right: 1px solid var(--color-border-light);
|
||||||
|
}
|
||||||
|
tbody td {
|
||||||
|
font-size: 13px;
|
||||||
|
background-color:white;
|
||||||
|
color: var(--color-text-base);
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-bottom: 1px solid var(--color-border-light);
|
||||||
|
border-right: 1px solid var(--color-border-light);
|
||||||
|
}
|
||||||
|
td, th, .fixed-header {
|
||||||
|
padding: 12px 24px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr td:last-child,
|
||||||
|
thead tr th:last-child,
|
||||||
|
#header-container div .fixed-header:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
td > div.cell-data {
|
||||||
|
width: -webkit-max-content;
|
||||||
|
width: -moz-max-content;
|
||||||
|
width: max-content;
|
||||||
|
white-space: nowrap;
|
||||||
|
/* max-width: 250px; */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.table-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 6px 12px;
|
||||||
|
}
|
||||||
|
.table-footer-count {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--color-text-base);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
<button class="primary run-btn" @click="execEditorContents">Run</button>
|
<button class="primary run-btn" @click="execEditorContents">Run</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div slot="right-pane">
|
<div slot="right-pane" id="bottomPane">
|
||||||
<view-switcher :view.sync="view" />
|
<view-switcher :view.sync="view" />
|
||||||
<div v-show="view === 'table'">
|
<div v-show="view === 'table'" class="table-view">
|
||||||
<div id="error" class="error"></div>
|
<!-- <div id="error" class="error"></div>
|
||||||
<pre ref="output" id="output">Results will be displayed here</pre>
|
<pre ref="output" id="output">Results will be displayed here</pre> -->
|
||||||
<sql-table :data="result" />
|
<sql-table v-if="result" :data="result" :height="tableViewHeight" />
|
||||||
</div>
|
</div>
|
||||||
<PlotlyEditor
|
<PlotlyEditor
|
||||||
v-show="view === 'chart'"
|
v-show="view === 'chart'"
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
:useResizeHandler="true"
|
:useResizeHandler="true"
|
||||||
:debug="true"
|
:debug="true"
|
||||||
:advancedTraceTypeSelector="true"
|
:advancedTraceTypeSelector="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</splitpanes>
|
</splitpanes>
|
||||||
</template>
|
</template>
|
||||||
@@ -82,6 +82,7 @@ export default {
|
|||||||
},
|
},
|
||||||
result: null,
|
result: null,
|
||||||
view: 'table',
|
view: 'table',
|
||||||
|
tableViewHeight: 0,
|
||||||
worker: this.$store.state.worker
|
worker: this.$store.state.worker
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -106,6 +107,10 @@ export default {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted () {
|
||||||
|
new ResizeObserver(this.calculateTableHeight).observe(document.getElementById('bottomPane'))
|
||||||
|
this.calculateTableHeight()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
update (data, layout, frames) {
|
update (data, layout, frames) {
|
||||||
this.state = { data, layout, frames }
|
this.state = { data, layout, frames }
|
||||||
@@ -137,22 +142,36 @@ export default {
|
|||||||
this.result = event.data.results[0]
|
this.result = event.data.results[0]
|
||||||
if (!this.result) {
|
if (!this.result) {
|
||||||
console.log(event.data.error)
|
console.log(event.data.error)
|
||||||
return
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$refs.output.innerHTML = ''
|
// this.$refs.output.innerHTML = ''
|
||||||
}
|
}
|
||||||
this.worker.postMessage({ action: 'exec', sql: commands })
|
this.worker.postMessage({ action: 'exec', sql: commands })
|
||||||
this.$refs.output.textContent = 'Fetching results...'
|
// this.$refs.output.textContent = 'Fetching results...'
|
||||||
},
|
},
|
||||||
execEditorContents () {
|
execEditorContents () {
|
||||||
this.execute(this.code + ';')
|
this.execute(this.code + ';')
|
||||||
|
},
|
||||||
|
calculateTableHeight () {
|
||||||
|
const bottomPane = document.getElementById('bottomPane')
|
||||||
|
// 88 - view swittcher height
|
||||||
|
// 42 - table footer width
|
||||||
|
// 30 - desirable space after the table
|
||||||
|
// 5 - padding-bottom of rounded table container
|
||||||
|
// 40 - height of table header
|
||||||
|
const freeSpace = bottomPane.offsetHeight - 88 - 42 - 30 - 5 - 40
|
||||||
|
this.tableViewHeight = freeSpace - (freeSpace % 40)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
#bottomPane {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.query-results-splitter {
|
.query-results-splitter {
|
||||||
height: calc(100vh - 74px);
|
height: calc(100vh - 74px);
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
@@ -192,4 +211,7 @@ export default {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
|
.table-view {
|
||||||
|
margin: 0 52px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ export default {
|
|||||||
.view-switcher {
|
.view-switcher {
|
||||||
height: 28px;
|
height: 28px;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 12px;
|
padding: 30px;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.view-switcher div {
|
.view-switcher div {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
Reference in New Issue
Block a user