mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
add schema styles and view switcher
This commit is contained in:
3
src/assets/images/database-edit.svg
Normal file
3
src/assets/images/database-edit.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 10.5V12.75C3 14.25 5.2875 15.54 8.25 15.75V13.5825L8.3475 13.5C5.34 13.32 3 12.045 3 10.5ZM9 9.75C5.685 9.75 3 8.4075 3 6.75V9C3 10.6575 5.685 12 9 12C9.2925 12 9.5775 12 9.87 12L12.75 9.09C11.55 9.54 10.2825 9.75 9 9.75ZM9 2.25C5.685 2.25 3 3.5925 3 5.25C3 6.9075 5.685 8.25 9 8.25C12.315 8.25 15 6.9075 15 5.25C15 3.5925 12.315 2.25 9 2.25ZM15.75 8.3475C15.6375 8.3475 15.5325 8.3925 15.4575 8.475L14.7075 9.225L16.245 10.725L16.995 9.975C17.1525 9.825 17.16 9.57 16.995 9.3975L16.065 8.475C15.99 8.3925 15.885 8.3475 15.78 8.3475H15.75ZM14.28 9.66L9.75 14.205V15.75H11.295L15.84 11.1975L14.28 9.66Z" fill="#A2B1C6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 735 B |
13
src/assets/styles/textFields.css
Normal file
13
src/assets/styles/textFields.css
Normal file
@@ -0,0 +1,13 @@
|
||||
input[type="text"] {
|
||||
background: var(--color-white);
|
||||
border: 1px solid var(--color-border);
|
||||
color: var(--color-text-base);
|
||||
border-radius: var(--border-radius-medium-2);
|
||||
height: 36px;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
input[type="text"]::placeholder {
|
||||
color: var(--color-text-light-2);
|
||||
}
|
||||
@@ -3,10 +3,13 @@
|
||||
--color-gray-light: #F3F6FA;
|
||||
--color-gray-light-2: #DFE8F3;
|
||||
--color-gray-light-3: #C8D4E3;
|
||||
--color-gray-light-4:#EBF0F8;
|
||||
--color-gray-medium: #A2B1C6;
|
||||
--color-gray-dark: #506784;
|
||||
--color-blue-medium: #119DFF;
|
||||
--color-blue-dark: #0D76BF;
|
||||
--color-blue-dark-2: #2A3F5F;
|
||||
|
||||
|
||||
|
||||
--color-bg-light: var(--color-gray-light);
|
||||
@@ -19,10 +22,15 @@
|
||||
--color-text-light-2: var(--color-gray-medium);
|
||||
--color-text-base: var(--color-gray-dark);
|
||||
--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);
|
||||
|
||||
--border-radius-big: 5px;
|
||||
--border-radius-medium: 3px;
|
||||
--border-radius-medium-2: 4px;
|
||||
--border-radius-small: 2px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
<template>
|
||||
<div>
|
||||
<input type="text" placeholder="Search table"/>
|
||||
<div id="db">
|
||||
<div @click="schemaVisible = !schemaVisible" class="db-name">
|
||||
<svg
|
||||
:style="{transform: schemaVisible ? 'rotate(90deg)' : 'rotate(0)'}"
|
||||
class="chevron-icon"
|
||||
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="schemaVisible ? '#506784' : 'rgba(80, 103, 132, 0.5)'"
|
||||
/>
|
||||
</svg>
|
||||
{{ dbName }}
|
||||
</div>
|
||||
<div class="db-edit">
|
||||
<svg
|
||||
class="db-edit-icon"
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M3 10.5V12.75C3 14.25 5.2875 15.54 8.25 15.75V13.5825L8.3475 13.5C5.34 13.32 3 12.045 3 10.5ZM9 9.75C5.685 9.75 3 8.4075 3 6.75V9C3 10.6575 5.685 12 9 12C9.2925 12 9.5775 12 9.87 12L12.75 9.09C11.55 9.54 10.2825 9.75 9 9.75ZM9 2.25C5.685 2.25 3 3.5925 3 5.25C3 6.9075 5.685 8.25 9 8.25C12.315 8.25 15 6.9075 15 5.25C15 3.5925 12.315 2.25 9 2.25ZM15.75 8.3475C15.6375 8.3475 15.5325 8.3925 15.4575 8.475L14.7075 9.225L16.245 10.725L16.995 9.975C17.1525 9.825 17.16 9.57 16.995 9.3975L16.065 8.475C15.99 8.3925 15.885 8.3475 15.78 8.3475H15.75ZM14.28 9.66L9.75 14.205V15.75H11.295L15.84 11.1975L14.28 9.66Z"
|
||||
fill="#A2B1C6"/>
|
||||
</svg>
|
||||
<span class="db-edit-tooltip">Change database</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="schemaVisible" class="schema">
|
||||
<table-description
|
||||
v-for="(table, index) in schema"
|
||||
:key="index"
|
||||
@@ -7,6 +42,7 @@
|
||||
:sql="table[1]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -15,6 +51,71 @@ import TableDescription from '@/components/TableDescription'
|
||||
export default {
|
||||
name: 'Schema',
|
||||
components: { TableDescription },
|
||||
props: ['schema']
|
||||
props: ['schema', 'dbName'],
|
||||
data () {
|
||||
return {
|
||||
schemaVisible: true
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.schema {
|
||||
margin-left: 12px;
|
||||
}
|
||||
.schema, .db-name {
|
||||
color: var(--color-text-base);
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#db {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.db-name {
|
||||
cursor: pointer;
|
||||
}
|
||||
>>> .chevron-icon {
|
||||
-webkit-transition: transform .15s ease-in-out;
|
||||
transition: transform .15s ease-in-out;
|
||||
}
|
||||
.db-name:hover .chevron-icon path,
|
||||
>>> .table-name:hover .chevron-icon path {
|
||||
fill: #506784;
|
||||
}
|
||||
|
||||
.db-edit {
|
||||
position: relative;
|
||||
}
|
||||
.db-edit-icon {
|
||||
display: block;
|
||||
}
|
||||
.db-edit-icon:hover path{
|
||||
fill: var(--color-accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.db-edit-tooltip {
|
||||
visibility: hidden;
|
||||
background-color: rgba(80, 103, 132, 0.75);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
padding: 0 6px;
|
||||
line-height: 19px;;
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
height: 19px;
|
||||
left: 24px;
|
||||
top: -12px;
|
||||
border-radius: var(--border-radius-medium);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.db-edit:hover .db-edit-tooltip {
|
||||
visibility: visible;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<div @click="colVisible = !colVisible" class="table-name">{{ name }}</div>
|
||||
<div @click="colVisible = !colVisible" class="table-name">
|
||||
<svg
|
||||
:style="{transform: colVisible ? 'rotate(90deg)' : 'rotate(0)'}"
|
||||
class="chevron-icon"
|
||||
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="colVisible ? '#506784' : 'rgba(80, 103, 132, 0.5)'"
|
||||
/>
|
||||
</svg>
|
||||
{{ name }}
|
||||
</div>
|
||||
<div v-show="colVisible" class="columns">
|
||||
<div v-for="(col, index) in columns" :key="index">
|
||||
{{ col.name }}, {{ col.type }}
|
||||
<div v-for="(col, index) in columns" :key="index" class="column">
|
||||
{{ col.name }}
|
||||
<span class="column-type">{{ col.type }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,10 +62,23 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.table-name, .column {
|
||||
margin-top: 11px;
|
||||
}
|
||||
|
||||
.table-name:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.columns {
|
||||
margin-left: 30px;
|
||||
margin-left: 24px;
|
||||
}
|
||||
.column-type {
|
||||
display: inline-block;
|
||||
background-color: var(--color-gray-light-4);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--border-radius-small);
|
||||
padding: 2px 6px;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
|
||||
66
src/components/ViewSwitcher.vue
Normal file
66
src/components/ViewSwitcher.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="view-switcher">
|
||||
<div
|
||||
:class="['table-mode', {'active-mode': view === 'table'}]"
|
||||
@click="$emit('update:view','table')"
|
||||
>
|
||||
Table
|
||||
</div>
|
||||
<div
|
||||
:class="['chart-mode', {'active-mode': view === 'chart'}]"
|
||||
@click="$emit('update:view','chart')"
|
||||
>
|
||||
Chart
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ViewSwitcher',
|
||||
props: ['view']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.view-switcher {
|
||||
height: 28px;
|
||||
display: flex;
|
||||
margin: 12px;
|
||||
}
|
||||
.view-switcher div {
|
||||
height: 100%;
|
||||
width: 136px;
|
||||
box-sizing: border-box;
|
||||
line-height: 28px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
background: var(--color-white);
|
||||
border: 1px solid var(--color-border);
|
||||
color: var(--color-text-base);
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
}
|
||||
.view-switcher div:hover {
|
||||
background-color: var(--color-bg-light);
|
||||
color: var(--color-text-active);
|
||||
}
|
||||
.view-switcher div.active-mode {
|
||||
background: var(--color-accent);
|
||||
border: 1px solid var(--color-accent-shade);
|
||||
color: var(--color-text-light);
|
||||
text-shadow: var(--shadow);
|
||||
z-index: 1;
|
||||
font-weight: 600;
|
||||
}
|
||||
.view-switcher div.active-mode:hover {
|
||||
background: var(--color-accent-shade);
|
||||
}
|
||||
.table-mode {
|
||||
border-radius: var(--border-radius-medium) 0 0 var(--border-radius-medium);
|
||||
}
|
||||
.chart-mode {
|
||||
margin-left: -1px;
|
||||
border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0;
|
||||
}
|
||||
</style>
|
||||
@@ -58,7 +58,7 @@ export default {
|
||||
}
|
||||
.splitpanes__splitter .toggle-btn {
|
||||
background-color: var(--color-bg-light-2);
|
||||
border-radius: 2px;
|
||||
border-radius: var(--border-radius-small);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
|
||||
@@ -7,6 +7,7 @@ import PlotlyEditor from 'react-chart-editor'
|
||||
|
||||
import '@/assets/styles/variables.css'
|
||||
import '@/assets/styles/buttons.css'
|
||||
import '@/assets/styles/textFields.css'
|
||||
|
||||
Vue.use(VueReact)
|
||||
Vue.react('PlotlyEditor', PlotlyEditor)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
:after="{ size: 80, max: 100 }"
|
||||
>
|
||||
<div slot="left-pane">
|
||||
<schema :schema="schema"/>
|
||||
<schema :schema="schema" :db-name="fileName"/>
|
||||
</div>
|
||||
<div slot="right-pane">
|
||||
<splitpanes
|
||||
@@ -18,18 +18,21 @@
|
||||
<div slot="left-pane">
|
||||
<div>
|
||||
<codemirror v-model="code" :options="cmOptions" @changes="onCmChange" />
|
||||
<button id="execute" class="button" @click="execEditorContents">Execute</button>
|
||||
<button id="execute" class="button" @click="execEditorContents">Run</button>
|
||||
<label class="button">
|
||||
Load an SQLite database file: <input type='file' ref='dbfile' @change="loadDb">
|
||||
</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div slot="right-pane">
|
||||
<view-switcher :view.sync="view" />
|
||||
<div v-show="view === 'table'">
|
||||
<div id="error" class="error"></div>
|
||||
<pre ref="output" id="output">Results will be displayed here</pre>
|
||||
<sql-table :data="result" />
|
||||
</div>
|
||||
</div>
|
||||
<div slot="right-pane">
|
||||
<PlotlyEditor
|
||||
v-show="view === 'chart'"
|
||||
:data="state.data"
|
||||
:layout="state.layout"
|
||||
:frames="state.frames"
|
||||
@@ -53,6 +56,7 @@
|
||||
import SqlTable from '@/components/SqlTable'
|
||||
import Schema from '@/components/Schema'
|
||||
import Splitpanes from '@/components/splitpanes'
|
||||
import ViewSwitcher from '@/components/ViewSwitcher'
|
||||
|
||||
import plotly from 'plotly.js/dist/plotly'
|
||||
import 'react-chart-editor/lib/react-chart-editor.min.css'
|
||||
@@ -72,7 +76,8 @@ export default {
|
||||
codemirror,
|
||||
SqlTable,
|
||||
Schema,
|
||||
Splitpanes
|
||||
Splitpanes,
|
||||
ViewSwitcher
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -93,6 +98,8 @@ export default {
|
||||
},
|
||||
result: null,
|
||||
schema: null,
|
||||
fileName: null,
|
||||
view: 'table',
|
||||
worker: this.$store.state.worker
|
||||
}
|
||||
},
|
||||
@@ -171,7 +178,8 @@ export default {
|
||||
execEditorContents () {
|
||||
this.execute(this.code + ';')
|
||||
},
|
||||
loadDb () {
|
||||
loadDb (filename) {
|
||||
this.fileName = this.$refs.dbfile.value.substr(this.$refs.dbfile.value.lastIndexOf('\\') + 1)
|
||||
const f = this.$refs.dbfile.files[0]
|
||||
const r = new FileReader()
|
||||
r.onload = () => {
|
||||
|
||||
Reference in New Issue
Block a user