mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 10:08:52 +08:00
add tab switcher
This commit is contained in:
@@ -13,11 +13,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="table-container" ref="table-container" @scroll="onScrollTable" :style="{height: `${height}px`}">
|
||||
<table id="table">
|
||||
<div
|
||||
id="table-container"
|
||||
ref="table-container"
|
||||
@scroll="onScrollTable"
|
||||
:style="{height: `${height}px`}"
|
||||
>
|
||||
<table ref="table">
|
||||
<thead>
|
||||
<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>
|
||||
</th>
|
||||
</tr>
|
||||
@@ -76,7 +81,7 @@ export default {
|
||||
calculateHeadersWidth () {
|
||||
this.tableWidth = this.$refs['table-container'].offsetWidth
|
||||
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 }
|
||||
})
|
||||
})
|
||||
@@ -89,7 +94,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
new ResizeObserver(this.calculateHeadersWidth).observe(document.getElementById('table'))
|
||||
new ResizeObserver(this.calculateHeadersWidth).observe(this.$refs.table)
|
||||
this.calculateHeadersWidth()
|
||||
},
|
||||
watch: {
|
||||
@@ -127,7 +132,6 @@ export default {
|
||||
}
|
||||
#table-container {
|
||||
width: 100%;
|
||||
/* height: 200px; */
|
||||
overflow: auto;
|
||||
}
|
||||
table {
|
||||
@@ -167,7 +171,6 @@ td > div.cell-data {
|
||||
width: -moz-max-content;
|
||||
width: max-content;
|
||||
white-space: nowrap;
|
||||
/* max-width: 250px; */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@@ -1,41 +1,43 @@
|
||||
<template>
|
||||
<splitpanes
|
||||
class="query-results-splitter"
|
||||
horizontal
|
||||
:before="{ size: 50, max: 50 }"
|
||||
:after="{ size: 50, max: 100 }"
|
||||
>
|
||||
<div slot="left-pane" class="query-editor">
|
||||
<div class="codemirror-container">
|
||||
<codemirror v-model="code" :options="cmOptions" @changes="onCmChange" />
|
||||
<div class="tab-content-container" v-show="isActive">
|
||||
<splitpanes
|
||||
class="query-results-splitter"
|
||||
horizontal
|
||||
:before="{ size: 50, max: 50 }"
|
||||
:after="{ size: 50, max: 100 }"
|
||||
>
|
||||
<div slot="left-pane" class="query-editor">
|
||||
<div class="codemirror-container">
|
||||
<codemirror v-model="code" :options="cmOptions" @changes="onCmChange" />
|
||||
</div>
|
||||
<div class="run-btn-container">
|
||||
<button class="primary run-btn" @click="execEditorContents">Run</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="run-btn-container">
|
||||
<button class="primary run-btn" @click="execEditorContents">Run</button>
|
||||
<div slot="right-pane" id="bottomPane" ref="bottomPane">
|
||||
<view-switcher :view.sync="view" />
|
||||
<div v-show="view === 'table'" class="table-view">
|
||||
<!-- <div id="error" class="error"></div>
|
||||
<pre ref="output" id="output">Results will be displayed here</pre> -->
|
||||
<sql-table v-if="result" :data="result" :height="tableViewHeight" />
|
||||
</div>
|
||||
<PlotlyEditor
|
||||
v-show="view === 'chart'"
|
||||
:data="state.data"
|
||||
:layout="state.layout"
|
||||
:frames="state.frames"
|
||||
:config="{ editable: true }"
|
||||
:dataSources="dataSources"
|
||||
:dataSourceOptions="dataSourceOptions"
|
||||
:plotly="plotly"
|
||||
@onUpdate="update"
|
||||
:useResizeHandler="true"
|
||||
:debug="true"
|
||||
:advancedTraceTypeSelector="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="right-pane" id="bottomPane">
|
||||
<view-switcher :view.sync="view" />
|
||||
<div v-show="view === 'table'" class="table-view">
|
||||
<!-- <div id="error" class="error"></div>
|
||||
<pre ref="output" id="output">Results will be displayed here</pre> -->
|
||||
<sql-table v-if="result" :data="result" :height="tableViewHeight" />
|
||||
</div>
|
||||
<PlotlyEditor
|
||||
v-show="view === 'chart'"
|
||||
:data="state.data"
|
||||
:layout="state.layout"
|
||||
:frames="state.frames"
|
||||
:config="{ editable: true }"
|
||||
:dataSources="dataSources"
|
||||
:dataSourceOptions="dataSourceOptions"
|
||||
:plotly="plotly"
|
||||
@onUpdate="update"
|
||||
:useResizeHandler="true"
|
||||
:debug="true"
|
||||
:advancedTraceTypeSelector="true"
|
||||
/>
|
||||
</div>
|
||||
</splitpanes>
|
||||
</splitpanes>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -57,6 +59,7 @@ import 'codemirror/addon/hint/sql-hint.js'
|
||||
|
||||
export default {
|
||||
name: 'TabContent',
|
||||
props: ['name', 'isActive'],
|
||||
components: {
|
||||
codemirror,
|
||||
SqlTable,
|
||||
@@ -108,7 +111,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
new ResizeObserver(this.calculateTableHeight).observe(document.getElementById('bottomPane'))
|
||||
new ResizeObserver(this.calculateTableHeight).observe(this.$refs.bottomPane)
|
||||
this.calculateTableHeight()
|
||||
},
|
||||
methods: {
|
||||
@@ -154,7 +157,7 @@ export default {
|
||||
this.execute(this.code + ';')
|
||||
},
|
||||
calculateTableHeight () {
|
||||
const bottomPane = document.getElementById('bottomPane')
|
||||
const bottomPane = this.$refs.bottomPane
|
||||
// 88 - view swittcher height
|
||||
// 42 - table footer width
|
||||
// 30 - desirable space after the table
|
||||
@@ -168,13 +171,19 @@ export default {
|
||||
</script>
|
||||
|
||||
<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 {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.query-results-splitter {
|
||||
height: calc(100vh - 74px);
|
||||
margin-top: 6px;
|
||||
height: calc(100vh - 110px);
|
||||
background-color: var(--color-bg-light);
|
||||
}
|
||||
|
||||
@@ -183,7 +192,7 @@ export default {
|
||||
}
|
||||
|
||||
.query-editor {
|
||||
padding: 0 52px 24px;
|
||||
padding: 52px 52px 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
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 />
|
||||
</div>
|
||||
<div slot="right-pane">
|
||||
<tab-content />
|
||||
<tabs />
|
||||
</div>
|
||||
</splitpanes>
|
||||
</div>
|
||||
@@ -18,14 +18,14 @@
|
||||
<script>
|
||||
import Splitpanes from '@/components/splitpanes'
|
||||
import Schema from '@/components/Schema'
|
||||
import TabContent from '@/components/TabContent'
|
||||
import Tabs from '@/components/Tabs'
|
||||
|
||||
export default {
|
||||
name: 'Editor',
|
||||
components: {
|
||||
Schema,
|
||||
Splitpanes,
|
||||
TabContent
|
||||
Tabs
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user