1
0
mirror of https://github.com/lana-k/sqliteviz.git synced 2025-12-07 10:38:54 +08:00

add predefined queries

This commit is contained in:
lana-k
2020-11-04 19:13:27 +01:00
parent fec8fb5ac0
commit 1037185a6a
12 changed files with 359 additions and 87 deletions

View File

@@ -35,11 +35,6 @@ export default {
checked: this.init
}
},
watch: {
checked () {
this.$emit('change', this.checked)
}
},
methods: {
onClick () {
this.checked = !this.checked

View File

@@ -8,21 +8,70 @@
<button
v-if="$store.state.tabs.length > 0"
class="primary"
:disabled="$store.state.currentTab && !$store.state.currentTab.isUnsaved"
@click="saveQuery"
:disabled="currentQuery && !currentQuery.isUnsaved"
@click="checkQueryBeforeSave"
>
Save
</button>
<button class="primary" @click="createNewQuery">Create</button>
</div>
<!--Save Query dialog -->
<modal name="save" classes="dialog" height="auto">
<div class="dialog-header">
Save query
<close-icon @click="$modal.hide('save')"/>
</div>
<div class="dialog-body">
<div v-show="isPredefined" id="save-note">
<img :src="require('@/assets/images/info.svg')">
Note: Predefined queries can't be edited.
That's why your modifications will be saved as a new query. Enter the name for it.
</div>
<text-field
label="Query name"
:error-msg="errorMsg"
v-model="name"
width="100%"
/>
</div>
<div class="dialog-buttons-container">
<button class="secondary" @click="$modal.hide('save')">Cancel</button>
<button class="primary" @click="saveQuery">Save</button>
</div>
</modal>
</nav>
</template>
<script>
import { nanoid } from 'nanoid'
import TextField from '@/components/TextField'
import CloseIcon from '@/components/svg/close'
export default {
name: 'MainMenu',
components: {
TextField,
CloseIcon
},
data () {
return {
name: '',
errorMsg: null
}
},
computed: {
currentQuery () {
return this.$store.state.currentTab
},
isPredefined () {
if (this.currentQuery) {
return this.currentQuery.isPredefined
} else {
return false
}
}
},
created () {
this.$root.$on('createNewQuery', this.createNewQuery)
},
@@ -38,38 +87,69 @@ export default {
}
this.$store.commit('addTab', tab)
this.$store.commit('setCurrentTabId', tab.id)
this.$store.commit('updateUntitledLastIndex')
},
checkQueryBeforeSave () {
this.errorMsg = null
const isFromScratch = !this.currentQuery.initName
if (isFromScratch || this.isPredefined) {
this.$modal.show('save')
} else {
this.saveQuery()
}
},
saveQuery () {
const currentQuery = this.$store.state.currentTab
const isFromScratch = !this.$store.state.currentTab.initName
const isFromScratch = !this.currentQuery.initName
if ((isFromScratch || this.isPredefined) && !this.name) {
this.errorMsg = 'Query name can\'t be empty'
return
}
const dataSet = this.currentQuery.result
const tabView = this.currentQuery.view
// Prepare query
const value = {
id: currentQuery.id,
query: currentQuery.query,
chart: currentQuery.getChartSatateForSave()
}
if (isFromScratch) {
value.name = prompt('query name')
// TODO: create dialog
this.$store.commit('updateTabName', { index: currentQuery.tabIndex, newName: value.name })
value.createdAt = new Date()
} else {
value.name = currentQuery.initName
id: this.isPredefined ? nanoid() : this.currentQuery.id,
query: this.currentQuery.query,
chart: this.currentQuery.getChartSatateForSave(),
name: (!this.isPredefined && this.currentQuery.initName) || this.name,
createdAt: new Date()
}
// Save query
let myQueries = JSON.parse(localStorage.getItem('myQueries'))
if (!myQueries) {
myQueries = [value]
} else if (isFromScratch) {
} else if (isFromScratch || this.isPredefined) {
myQueries.push(value)
} else {
const queryIndex = myQueries.findIndex(query => query.id === currentQuery.id)
const queryIndex = myQueries.findIndex(query => query.id === this.currentQuery.id)
value.createdAt = myQueries[queryIndex].createdAt
myQueries[queryIndex] = value
}
localStorage.setItem('myQueries', JSON.stringify(myQueries))
currentQuery.isUnsaved = false
// Update tab
this.$store.commit('updateTab', {
index: this.currentQuery.tabIndex,
name: value.name,
id: value.id,
query: value.query,
chart: value.chart,
isUnsaved: false
})
// Restore data:
// e.g. if we save predefined query the tab will be created again
// (because of new id) and
// it will be without sql result and has default view - table.
// That's why we need to restore data and view
this.$nextTick(() => {
this.currentQuery.result = dataSet
this.currentQuery.view = tabView
})
// Hide dialog
this.$modal.hide('save')
}
}
}
@@ -89,6 +169,7 @@ nav {
left: 0;
width: 100vw;
padding: 0 52px;
z-index: 999;
}
a {
font-size: 18px;
@@ -103,4 +184,13 @@ a.router-link-active {
button {
margin-left: 16px;
}
#save-note {
margin-bottom: 24px;
display: flex;
align-items: flex-start;
}
#save-note img {
margin: -3px 6px 0 0;
}
</style>

View File

@@ -22,7 +22,7 @@
<table ref="table">
<thead>
<tr>
<th v-for="(th,index) in data.columns" :key="index" ref="th">
<th v-for="(th,index) in dataSet.columns" :key="index" ref="th">
<div class="cell-data" :style="cellStyle">{{ th }}</div>
</th>
</tr>
@@ -39,7 +39,7 @@
</div>
<div class="table-footer">
<div class="table-footer-count">
{{ data.values.length}} {{data.values.length === 1 ? 'row' : 'rows'}} retrieved
{{ dataSet.values.length}} {{dataSet.values.length === 1 ? 'row' : 'rows'}} retrieved
</div>
<pager v-show="pageCount > 1" :page-count="pageCount" v-model="currentPage" />
</div>
@@ -52,17 +52,18 @@ import Pager from '@/components/Pager'
export default {
name: 'SqlTable',
components: { Pager },
props: ['data', 'height'],
props: ['dataSet', 'height'],
data () {
return {
header: null,
tableWidth: null,
currentPage: 1
currentPage: 1,
resizeObserver: null
}
},
computed: {
cellStyle () {
const eq = this.tableWidth / this.data.columns.length
const eq = this.tableWidth / this.dataSet.columns.length
return { maxWidth: `${Math.max(eq, 100)}px` }
},
@@ -70,11 +71,11 @@ export default {
return Math.max(Math.floor(this.height / 40), 20)
},
pageCount () {
return Math.ceil(this.data.values.length / this.pageSize)
return Math.ceil(this.dataSet.values.length / this.pageSize)
},
currentPageData () {
const start = (this.currentPage - 1) * this.pageSize
return this.data.values.slice(start, start + this.pageSize)
return this.dataSet.values.slice(start, start + this.pageSize)
}
},
methods: {
@@ -94,12 +95,16 @@ export default {
}
},
mounted () {
new ResizeObserver(this.calculateHeadersWidth).observe(this.$refs.table)
this.resizeObserver = new ResizeObserver(this.calculateHeadersWidth)
this.resizeObserver.observe(this.$refs.table)
this.calculateHeadersWidth()
},
beforeDestroy () {
this.resizeObserver.unobserve(this.$refs.table)
},
watch: {
currentPageData: 'calculateHeadersWidth',
data () {
dataSet () {
this.currentPage = 1
}
}

View File

@@ -36,7 +36,7 @@
<div v-show="error" class="table-preview error">
{{ error }}
</div>
<sql-table v-if="result" :data="result" :height="tableViewHeight" />
<sql-table v-if="result" :data-set="result" :height="tableViewHeight" />
</div>
<chart
:visible="view === 'chart'"
@@ -59,8 +59,8 @@ import ViewSwitcher from '@/components/ViewSwitcher'
import Chart from '@/components/Chart'
export default {
name: 'TabContent',
props: ['id', 'initName', 'initQuery', 'initChart', 'tabIndex'],
name: 'Tab',
props: ['id', 'initName', 'initQuery', 'initChart', 'tabIndex', 'isPredefined'],
components: {
SqlEditor,
SqlTable,
@@ -76,7 +76,8 @@ export default {
tableViewHeight: 0,
isUnsaved: !this.initName,
isGettingResults: false,
error: null
error: null,
resizeObserver: null
}
},
computed: {
@@ -88,9 +89,13 @@ export default {
this.$store.commit('setCurrentTab', this)
},
mounted () {
new ResizeObserver(this.handleResize).observe(this.$refs.bottomPane)
this.resizeObserver = new ResizeObserver(this.handleResize)
this.resizeObserver.observe(this.$refs.bottomPane)
this.calculateTableHeight()
},
beforeDestroy () {
this.resizeObserver.unobserve(this.$refs.bottomPane)
},
watch: {
isActive () {
if (this.isActive) {

View File

@@ -3,7 +3,7 @@
<div id="tabs__header" v-if="tabs.length > 0">
<div
v-for="(tab, index) in tabs"
:key="tab.id"
:key="index"
@click="selectTab(tab.id)"
:class="[{'tab__selected': (tab.id === selectedIndex)}, 'tab']"
>
@@ -29,13 +29,14 @@
</div>
</div>
</div>
<tab-content
<tab
v-for="(tab, index) in tabs"
:key="tab.id"
:id="tab.id"
:init-name="tab.name"
:init-query="tab.query"
:init-chart="tab.chart"
:is-predefined="tab.isPredefined"
:tab-index="index"
/>
<div v-if="tabs.length === 0" id="start-guide">
@@ -47,11 +48,11 @@
</template>
<script>
import TabContent from '@/components/TabContent'
import Tab from '@/components/Tab'
export default {
components: {
TabContent
Tab
},
data () {
return {
@@ -153,5 +154,6 @@ export default {
color: var(--color-accent);
text-decoration: none;
cursor: pointer;
white-space: nowrap;
}
</style>

View File

@@ -13,7 +13,7 @@ export default {
<style scoped>
.icon {
vertical-align: middle;
margin: 0 0 0 12px;
margin: 0 12px;
}
.icon:hover path {

View File

@@ -13,7 +13,7 @@ export default {
<style scoped>
.icon {
vertical-align: middle;
margin: 0 12px 0 6px;
margin: 0 12px;
}
.icon:hover path {