mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
add tab switcher
This commit is contained in:
@@ -13,11 +13,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="table-container" ref="table-container" @scroll="onScrollTable" :style="{height: `${height}px`}">
|
<div
|
||||||
<table id="table">
|
id="table-container"
|
||||||
|
ref="table-container"
|
||||||
|
@scroll="onScrollTable"
|
||||||
|
:style="{height: `${height}px`}"
|
||||||
|
>
|
||||||
|
<table ref="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th v-for="(th,index) in data.columns" :key="index">
|
<th v-for="(th,index) in data.columns" :key="index" ref="th">
|
||||||
<div class="cell-data" :style="cellStyle">{{ th }}</div>
|
<div class="cell-data" :style="cellStyle">{{ th }}</div>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -76,7 +81,7 @@ export default {
|
|||||||
calculateHeadersWidth () {
|
calculateHeadersWidth () {
|
||||||
this.tableWidth = this.$refs['table-container'].offsetWidth
|
this.tableWidth = this.$refs['table-container'].offsetWidth
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.header = Array.from(document.querySelectorAll('th')).map(th => {
|
this.header = this.$refs.th.map(th => {
|
||||||
return { name: th.innerText, width: th.offsetWidth }
|
return { name: th.innerText, width: th.offsetWidth }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -89,7 +94,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
new ResizeObserver(this.calculateHeadersWidth).observe(document.getElementById('table'))
|
new ResizeObserver(this.calculateHeadersWidth).observe(this.$refs.table)
|
||||||
this.calculateHeadersWidth()
|
this.calculateHeadersWidth()
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -127,7 +132,6 @@ export default {
|
|||||||
}
|
}
|
||||||
#table-container {
|
#table-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/* height: 200px; */
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
table {
|
table {
|
||||||
@@ -167,7 +171,6 @@ td > div.cell-data {
|
|||||||
width: -moz-max-content;
|
width: -moz-max-content;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
/* max-width: 250px; */
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div class="tab-content-container" v-show="isActive">
|
||||||
<splitpanes
|
<splitpanes
|
||||||
class="query-results-splitter"
|
class="query-results-splitter"
|
||||||
horizontal
|
horizontal
|
||||||
@@ -13,7 +14,7 @@
|
|||||||
<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" id="bottomPane">
|
<div slot="right-pane" id="bottomPane" ref="bottomPane">
|
||||||
<view-switcher :view.sync="view" />
|
<view-switcher :view.sync="view" />
|
||||||
<div v-show="view === 'table'" class="table-view">
|
<div v-show="view === 'table'" class="table-view">
|
||||||
<!-- <div id="error" class="error"></div>
|
<!-- <div id="error" class="error"></div>
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</splitpanes>
|
</splitpanes>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -57,6 +59,7 @@ import 'codemirror/addon/hint/sql-hint.js'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TabContent',
|
name: 'TabContent',
|
||||||
|
props: ['name', 'isActive'],
|
||||||
components: {
|
components: {
|
||||||
codemirror,
|
codemirror,
|
||||||
SqlTable,
|
SqlTable,
|
||||||
@@ -108,7 +111,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
new ResizeObserver(this.calculateTableHeight).observe(document.getElementById('bottomPane'))
|
new ResizeObserver(this.calculateTableHeight).observe(this.$refs.bottomPane)
|
||||||
this.calculateTableHeight()
|
this.calculateTableHeight()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -154,7 +157,7 @@ export default {
|
|||||||
this.execute(this.code + ';')
|
this.execute(this.code + ';')
|
||||||
},
|
},
|
||||||
calculateTableHeight () {
|
calculateTableHeight () {
|
||||||
const bottomPane = document.getElementById('bottomPane')
|
const bottomPane = this.$refs.bottomPane
|
||||||
// 88 - view swittcher height
|
// 88 - view swittcher height
|
||||||
// 42 - table footer width
|
// 42 - table footer width
|
||||||
// 30 - desirable space after the table
|
// 30 - desirable space after the table
|
||||||
@@ -168,13 +171,19 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.tab-content-container {
|
||||||
|
padding-top: 6px;
|
||||||
|
background-color: var(--color-bg-light);
|
||||||
|
border-top: 1px solid var(--color-border-light);
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
#bottomPane {
|
#bottomPane {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.query-results-splitter {
|
.query-results-splitter {
|
||||||
height: calc(100vh - 74px);
|
height: calc(100vh - 110px);
|
||||||
margin-top: 6px;
|
|
||||||
background-color: var(--color-bg-light);
|
background-color: var(--color-bg-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +192,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.query-editor {
|
.query-editor {
|
||||||
padding: 0 52px 24px;
|
padding: 52px 52px 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
87
src/components/Tabs.vue
Normal file
87
src/components/Tabs.vue
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div id="tabs__header">
|
||||||
|
<div
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.id"
|
||||||
|
@click="selectTab(tab.id)"
|
||||||
|
:class='{"tab__selected": (tab.id === selectedIndex)}'
|
||||||
|
>
|
||||||
|
{{ tab.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<tab-content
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.id"
|
||||||
|
:is-active="tab.isActive"
|
||||||
|
:name="tab.name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TabContent from '@/components/TabContent'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
TabContent
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
selectedIndex: 0,
|
||||||
|
tabs: [
|
||||||
|
{ id: 1, name: 'New query', isActive: true },
|
||||||
|
{ id: 2, name: 'New query 2', isActive: false }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
selectTab (id) {
|
||||||
|
this.selectedIndex = id
|
||||||
|
this.tabs.forEach(tab => {
|
||||||
|
tab.isActive = (tab.id === id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#tabs__header {
|
||||||
|
display: flex;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#tabs__header div {
|
||||||
|
height: 36px;
|
||||||
|
background-color: var(--color-bg-light);
|
||||||
|
border-right: 1px solid var(--color-border-light);
|
||||||
|
border-bottom: 1px solid var(--color-border-light);
|
||||||
|
line-height: 36px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text-base);
|
||||||
|
padding: 0 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#tabs__header div:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabs__header .tab__selected {
|
||||||
|
color: var(--color-text-active);
|
||||||
|
font-weight: 600;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
#tabs__header .tab__selected:hover {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
#tabs__header .tab__selected:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 5px;
|
||||||
|
background-color: var(--color-accent);
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<schema />
|
<schema />
|
||||||
</div>
|
</div>
|
||||||
<div slot="right-pane">
|
<div slot="right-pane">
|
||||||
<tab-content />
|
<tabs />
|
||||||
</div>
|
</div>
|
||||||
</splitpanes>
|
</splitpanes>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,14 +18,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import Splitpanes from '@/components/splitpanes'
|
import Splitpanes from '@/components/splitpanes'
|
||||||
import Schema from '@/components/Schema'
|
import Schema from '@/components/Schema'
|
||||||
import TabContent from '@/components/TabContent'
|
import Tabs from '@/components/Tabs'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Editor',
|
name: 'Editor',
|
||||||
components: {
|
components: {
|
||||||
Schema,
|
Schema,
|
||||||
Splitpanes,
|
Splitpanes,
|
||||||
TabContent
|
Tabs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user