mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
Loading remote database and inquiries #109
This commit is contained in:
@@ -75,14 +75,23 @@ export default {
|
||||
props: {
|
||||
horizontal: { type: Boolean, default: false },
|
||||
before: { type: Object },
|
||||
after: { type: Object }
|
||||
after: { type: Object },
|
||||
default: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
before: 50,
|
||||
after: 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
container: null,
|
||||
paneBefore: this.before,
|
||||
paneAfter: this.after,
|
||||
beforeMinimising: {
|
||||
beforeMinimising: !this.after.size || !this.before.size ? this.default : {
|
||||
before: this.before.size,
|
||||
after: this.after.size
|
||||
},
|
||||
|
||||
@@ -77,7 +77,7 @@ class Database {
|
||||
}
|
||||
|
||||
this.dbName = file ? fu.getFileName(file) : 'database'
|
||||
this.refreshSchema()
|
||||
await this.refreshSchema()
|
||||
|
||||
events.send('database.import', file ? file.size : 0, {
|
||||
from: file ? 'sqlite' : 'none',
|
||||
|
||||
@@ -22,6 +22,7 @@ export default class Tab {
|
||||
table: 'bottom',
|
||||
dataView: 'hidden'
|
||||
}
|
||||
this.maximize = inquiry.maximize
|
||||
|
||||
this.isSaved = !!inquiry.id
|
||||
this.state = state
|
||||
|
||||
@@ -4,6 +4,7 @@ import Workspace from '@/views/Main/Workspace'
|
||||
import Inquiries from '@/views/Main/Inquiries'
|
||||
import Welcome from '@/views/Welcome'
|
||||
import Main from '@/views/Main'
|
||||
import LoadView from '@/views/LoadView'
|
||||
import store from '@/store'
|
||||
import database from '@/lib/database'
|
||||
|
||||
@@ -31,6 +32,11 @@ const routes = [
|
||||
component: Inquiries
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/load',
|
||||
name: 'Load',
|
||||
component: LoadView
|
||||
}
|
||||
]
|
||||
|
||||
@@ -39,7 +45,7 @@ const router = new VueRouter({
|
||||
})
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
if (!store.state.db) {
|
||||
if (!store.state.db && to.name !== 'Load') {
|
||||
const newDb = database.getNewDatabase()
|
||||
await newDb.loadDb()
|
||||
store.commit('setDb', newDb)
|
||||
|
||||
188
src/views/LoadView.vue
Normal file
188
src/views/LoadView.vue
Normal file
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<div>
|
||||
<logs
|
||||
id="logs"
|
||||
:messages="messages"
|
||||
/>
|
||||
<button
|
||||
v-if="hasErrors"
|
||||
id="open-workspace-btn"
|
||||
class="secondary"
|
||||
@click="$router.push('/workspace?hide_schema=1')">
|
||||
Open workspace
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import fu from '@/lib/utils/fileIo'
|
||||
import database from '@/lib/database'
|
||||
import Logs from '@/components/Logs'
|
||||
|
||||
export default {
|
||||
name: 'LoadView',
|
||||
components: {
|
||||
Logs
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
newDb: null,
|
||||
messages: [],
|
||||
dataMsg: {},
|
||||
inquiryMsg: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasErrors () {
|
||||
return this.dataMsg.type === 'error' || this.inquiryMsg.type === 'error'
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
const {
|
||||
data_url: dataUrl,
|
||||
data_format: dataFormat,
|
||||
inquiry_url: inquiryUrl,
|
||||
inquiry_id: inquiryIds,
|
||||
maximize
|
||||
} = this.$route.query
|
||||
|
||||
await this.loadData(dataUrl, dataFormat)
|
||||
const inquiries = await this.loadInquiries(inquiryUrl, inquiryIds)
|
||||
if (inquiries && inquiries.length > 0) {
|
||||
await this.openInquiries(inquiries, maximize)
|
||||
}
|
||||
if (!this.hasErrors) {
|
||||
this.$router.push('/workspace?hide_schema=1')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async loadData (dataUrl, dataFormat) {
|
||||
this.newDb = database.getNewDatabase()
|
||||
if (dataUrl) {
|
||||
this.dataMsg = {
|
||||
message: 'Preparing data...',
|
||||
type: 'info'
|
||||
}
|
||||
this.messages.push(this.dataMsg)
|
||||
|
||||
// Show loading indicator after 1 second
|
||||
const loadingDataIndicator = setTimeout(() => {
|
||||
if (this.dataMsg.type === 'info') {
|
||||
this.dataMsg.type = 'loading'
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
if (dataFormat === 'sqlite') {
|
||||
await this.getSqliteDb(dataUrl)
|
||||
}
|
||||
|
||||
// Loading indicator is not needed anymore
|
||||
clearTimeout(loadingDataIndicator)
|
||||
} else {
|
||||
await this.newDb.loadDb()
|
||||
}
|
||||
this.$store.commit('setDb', this.newDb)
|
||||
},
|
||||
async getSqliteDb (dataUrl) {
|
||||
try {
|
||||
const filename = new URL(dataUrl).pathname.split('/').pop()
|
||||
const res = await fu.readFile(dataUrl)
|
||||
if (!res.ok) {
|
||||
throw new Error('Fetching DB failed')
|
||||
}
|
||||
const file = await res.blob()
|
||||
file.name = filename
|
||||
|
||||
await this.newDb.loadDb(file)
|
||||
this.dataMsg.message = 'Data is ready'
|
||||
this.dataMsg.type = 'success'
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
this.dataMsg.message = error
|
||||
this.dataMsg.type = 'error'
|
||||
}
|
||||
},
|
||||
async loadInquiries (inquiryUrl, inquiryIds = []) {
|
||||
if (!inquiryUrl) {
|
||||
return []
|
||||
}
|
||||
// Show loading indicator after 1 second
|
||||
const loadingInquiriesIndicator = setTimeout(() => {
|
||||
if (this.inquiryMsg.type === 'info') {
|
||||
this.inquiryMsg.type = 'loading'
|
||||
}
|
||||
}, 1000)
|
||||
try {
|
||||
this.inquiryMsg = {
|
||||
message: 'Preparing inquiries...',
|
||||
type: 'info'
|
||||
}
|
||||
this.messages.push(this.inquiryMsg)
|
||||
|
||||
const res = await fu.readFile(inquiryUrl)
|
||||
const file = await res.json()
|
||||
|
||||
this.inquiryMsg.message = 'Inquiries are ready'
|
||||
this.inquiryMsg.type = 'success'
|
||||
|
||||
return inquiryIds.length > 0
|
||||
? file.inquiries.filter(inquiry => inquiryIds.includes(inquiry.id))
|
||||
: file.inquiries
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
this.inquiryMsg.message = error
|
||||
this.inquiryMsg.type = 'error'
|
||||
}
|
||||
// Loading indicator is not needed anymore
|
||||
clearTimeout(loadingInquiriesIndicator)
|
||||
},
|
||||
async openInquiries (inquiries, maximize) {
|
||||
let tabToOpen = null
|
||||
const layout = maximize ? this.getLayout(maximize) : undefined
|
||||
for (const inquiry of inquiries) {
|
||||
const tabId = await this.$store.dispatch('addTab', {
|
||||
...inquiry,
|
||||
id: undefined,
|
||||
layout,
|
||||
maximize
|
||||
})
|
||||
if (!tabToOpen) {
|
||||
tabToOpen = tabId
|
||||
this.$store.commit('setCurrentTabId', tabToOpen)
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.state.currentTab.execute()
|
||||
},
|
||||
|
||||
getLayout (panelToMaximize) {
|
||||
if (panelToMaximize === 'dataView') {
|
||||
return {
|
||||
sqlEditor: 'hidden',
|
||||
table: 'above',
|
||||
dataView: 'bottom'
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
sqlEditor: 'above',
|
||||
table: 'bottom',
|
||||
dataView: 'hidden'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#logs {
|
||||
margin: 8px auto;
|
||||
max-width: 800px;
|
||||
|
||||
}
|
||||
|
||||
#open-workspace-btn {
|
||||
margin: 16px auto;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@@ -3,8 +3,9 @@
|
||||
<splitpanes
|
||||
class="query-results-splitter"
|
||||
horizontal
|
||||
:before="{ size: 50, max: 100 }"
|
||||
:after="{ size: 50, max: 100 }"
|
||||
:before="{ size: topPaneSize, max: 100 }"
|
||||
:after="{ size: 100 - topPaneSize, max: 100 }"
|
||||
:default="{ before: 50, after: 50 }"
|
||||
>
|
||||
<template #left-pane>
|
||||
<div :id="'above-' + tab.id" class="above" />
|
||||
@@ -70,6 +71,13 @@ export default {
|
||||
Splitpanes,
|
||||
Teleport
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
topPaneSize: this.tab.maximize
|
||||
? this.tab.layout[this.tab.maximize] === 'above' ? 100 : 0
|
||||
: 50
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isActive () {
|
||||
return this.tab.id === this.$store.state.currentTabId
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
<div>
|
||||
<splitpanes
|
||||
class="schema-tabs-splitter"
|
||||
:before="{ size: 20, max: 30 }"
|
||||
:after="{ size: 80, max: 100 }"
|
||||
:before="{ size: schemaWidth, max: 30 }"
|
||||
:after="{ size: 100 - schemaWidth, max: 100 }"
|
||||
:default="{ before: 20, after: 80 }"
|
||||
>
|
||||
<template #left-pane>
|
||||
<schema/>
|
||||
@@ -28,6 +29,11 @@ export default {
|
||||
Splitpanes,
|
||||
Tabs
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
schemaWidth: this.$route.query.hide_schema === '1' ? 0 : 20
|
||||
}
|
||||
},
|
||||
async beforeCreate () {
|
||||
const schema = this.$store.state.db.schema
|
||||
if (!schema || schema.length === 0) {
|
||||
|
||||
Reference in New Issue
Block a user