Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a07f2d3d99 | ||
|
|
b9844b8696 | ||
|
|
464bff3db8 | ||
|
|
00e434e142 | ||
|
|
5d6280abec | ||
|
|
7a39e905b9 | ||
|
|
297ea2c18a |
30
package-lock.json
generated
@@ -14,7 +14,7 @@
|
||||
"debounce": "^1.2.0",
|
||||
"nanoid": "^3.1.12",
|
||||
"papaparse": "^5.3.0",
|
||||
"plotly.js": "^1.57.1",
|
||||
"plotly.js": "^1.58.4",
|
||||
"promise-worker": "^2.0.1",
|
||||
"react": "^16.13.1",
|
||||
"react-chart-editor": "^0.42.0",
|
||||
@@ -10057,9 +10057,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/gl-plot3d": {
|
||||
"version": "2.4.6",
|
||||
"resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-2.4.6.tgz",
|
||||
"integrity": "sha512-CkrNvDKu0p74Di2g2Oc9kU+s1Oe+wi4cIfHzXABp8DvfoRl0/bayqJ9q8EcRAqMeQQxQZYGvJkk4hlBwI758Jw==",
|
||||
"version": "2.4.7",
|
||||
"resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-2.4.7.tgz",
|
||||
"integrity": "sha512-mLDVWrl4Dj0O0druWyHUK5l7cBQrRIJRn2oROEgrRuOgbbrLAzsREKefwMO0bA0YqkiZMFMnV5VvPA9j57X5Xg==",
|
||||
"dependencies": {
|
||||
"3d-view": "^2.0.0",
|
||||
"a-big-triangle": "^1.0.3",
|
||||
@@ -15945,9 +15945,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/plotly.js": {
|
||||
"version": "1.57.1",
|
||||
"resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.57.1.tgz",
|
||||
"integrity": "sha512-23GlzClmOGT1lE86Ys0DLuxBM/fgRNzJqH9y7ZylO4VPwstPAlQd12DklXsuqOgCNSxnnWUaP+J7BaUOFplsUg==",
|
||||
"version": "1.58.4",
|
||||
"resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.58.4.tgz",
|
||||
"integrity": "sha512-hdt/aEvkPjS1HJ7tJKcPqsqi9ErEZPhUFs4d2ANTLeBim+AmVcHzS1rtwr7ZrVCINgliW/+92u81omJoy+lbUw==",
|
||||
"dependencies": {
|
||||
"@plotly/d3-sankey": "0.7.2",
|
||||
"@plotly/d3-sankey-circular": "0.33.1",
|
||||
@@ -15979,7 +15979,7 @@
|
||||
"gl-mat4": "^1.2.0",
|
||||
"gl-mesh3d": "^2.3.1",
|
||||
"gl-plot2d": "^1.4.5",
|
||||
"gl-plot3d": "^2.4.6",
|
||||
"gl-plot3d": "^2.4.7",
|
||||
"gl-pointcloud2d": "^1.0.3",
|
||||
"gl-scatter3d": "^1.2.3",
|
||||
"gl-select-box": "^1.0.4",
|
||||
@@ -32186,9 +32186,9 @@
|
||||
}
|
||||
},
|
||||
"gl-plot3d": {
|
||||
"version": "2.4.6",
|
||||
"resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-2.4.6.tgz",
|
||||
"integrity": "sha512-CkrNvDKu0p74Di2g2Oc9kU+s1Oe+wi4cIfHzXABp8DvfoRl0/bayqJ9q8EcRAqMeQQxQZYGvJkk4hlBwI758Jw==",
|
||||
"version": "2.4.7",
|
||||
"resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-2.4.7.tgz",
|
||||
"integrity": "sha512-mLDVWrl4Dj0O0druWyHUK5l7cBQrRIJRn2oROEgrRuOgbbrLAzsREKefwMO0bA0YqkiZMFMnV5VvPA9j57X5Xg==",
|
||||
"requires": {
|
||||
"3d-view": "^2.0.0",
|
||||
"a-big-triangle": "^1.0.3",
|
||||
@@ -37188,9 +37188,9 @@
|
||||
}
|
||||
},
|
||||
"plotly.js": {
|
||||
"version": "1.57.1",
|
||||
"resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.57.1.tgz",
|
||||
"integrity": "sha512-23GlzClmOGT1lE86Ys0DLuxBM/fgRNzJqH9y7ZylO4VPwstPAlQd12DklXsuqOgCNSxnnWUaP+J7BaUOFplsUg==",
|
||||
"version": "1.58.4",
|
||||
"resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.58.4.tgz",
|
||||
"integrity": "sha512-hdt/aEvkPjS1HJ7tJKcPqsqi9ErEZPhUFs4d2ANTLeBim+AmVcHzS1rtwr7ZrVCINgliW/+92u81omJoy+lbUw==",
|
||||
"requires": {
|
||||
"@plotly/d3-sankey": "0.7.2",
|
||||
"@plotly/d3-sankey-circular": "0.33.1",
|
||||
@@ -37222,7 +37222,7 @@
|
||||
"gl-mat4": "^1.2.0",
|
||||
"gl-mesh3d": "^2.3.1",
|
||||
"gl-plot2d": "^1.4.5",
|
||||
"gl-plot3d": "^2.4.6",
|
||||
"gl-plot3d": "^2.4.7",
|
||||
"gl-pointcloud2d": "^1.0.3",
|
||||
"gl-scatter3d": "^1.2.3",
|
||||
"gl-select-box": "^1.0.4",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"debounce": "^1.2.0",
|
||||
"nanoid": "^3.1.12",
|
||||
"papaparse": "^5.3.0",
|
||||
"plotly.js": "^1.57.1",
|
||||
"plotly.js": "^1.58.4",
|
||||
"promise-worker": "^2.0.1",
|
||||
"react": "^16.13.1",
|
||||
"react-chart-editor": "^0.42.0",
|
||||
|
||||
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 11 KiB |
BIN
public/Logo48x48.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 798 B After Width: | Height: | Size: 774 B |
@@ -3,6 +3,16 @@
|
||||
"description": "Sqliteviz is a single-page application for fully client-side visualisation of SQLite databases or CSV.",
|
||||
"display": "fullscreen",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.png",
|
||||
"sizes": "32x32",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "Logo48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "Logo192x192.png",
|
||||
"sizes": "192x192",
|
||||
|
||||
@@ -13,7 +13,7 @@ function invokeServiceWorkerUpdateFlow (registration) {
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', async () => {
|
||||
const registration = await navigator.serviceWorker.register('/service-worker.js')
|
||||
const registration = await navigator.serviceWorker.register('service-worker.js')
|
||||
// ensure the case when the updatefound event was missed is also handled
|
||||
// by re-invoking the prompt when there's a waiting Service Worker
|
||||
if (registration.waiting) {
|
||||
|
||||
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 42 KiB |
@@ -233,6 +233,7 @@ export default {
|
||||
this.$modal.hide('parse')
|
||||
const tabId = await this.$store.dispatch('addTab', { query: 'select * from csv_import' })
|
||||
this.$store.commit('setCurrentTabId', tabId)
|
||||
this.importCsvCompleted = false
|
||||
}
|
||||
if (this.$route.path !== '/editor') {
|
||||
this.$router.push('/editor')
|
||||
|
||||
@@ -10,7 +10,7 @@ export default {
|
||||
getResult (source) {
|
||||
const result = {}
|
||||
if (source.meta.fields) {
|
||||
result.columns = source.meta.fields
|
||||
result.columns = source.meta.fields.map(col => col.trim())
|
||||
result.values = source.data.map(row => {
|
||||
const resultRow = []
|
||||
result.columns.forEach(col => { resultRow.push(row[col]) })
|
||||
|
||||
@@ -25,6 +25,10 @@ const hintOptions = {
|
||||
}
|
||||
return tables
|
||||
},
|
||||
get defaultTable () {
|
||||
const schema = store.state.schema
|
||||
return schema.length === 1 ? schema[0].name : null
|
||||
},
|
||||
completeSingle: false,
|
||||
completeOnSingleClick: true,
|
||||
alignWithWord: false
|
||||
|
||||
@@ -838,4 +838,49 @@ describe('DbUploader.vue import CSV', () => {
|
||||
expect(newDb.shutDown.calledOnce).to.equal(true)
|
||||
expect(wrapper.find('[data-modal="parse"]').exists()).to.equal(false)
|
||||
})
|
||||
|
||||
it("doesn't open new tab when load db after importing CSV", async () => {
|
||||
fu.getFileFromUser.onCall(0).resolves({ type: 'text/csv', name: 'foo.csv' })
|
||||
fu.getFileFromUser.onCall(1).resolves({ type: 'application/x-sqlite3', name: 'bar.sqlite3' })
|
||||
sinon.stub(csv, 'parse').resolves({
|
||||
delimiter: '|',
|
||||
data: {
|
||||
columns: ['col1', 'col2'],
|
||||
values: [
|
||||
[1, 'foo']
|
||||
]
|
||||
},
|
||||
hasErrors: false,
|
||||
messages: []
|
||||
})
|
||||
|
||||
const schema = {}
|
||||
const newDb = {
|
||||
createDb: sinon.stub().resolves(schema),
|
||||
createProgressCounter: sinon.stub().returns(1),
|
||||
deleteProgressCounter: sinon.stub(),
|
||||
loadDb: sinon.stub().resolves()
|
||||
}
|
||||
sinon.stub(database, 'getNewDatabase').returns(newDb)
|
||||
|
||||
await wrapper.find('.drop-area').trigger('click')
|
||||
await csv.parse.returnValues[0]
|
||||
await wrapper.vm.animationPromise
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
await wrapper.find('#csv-import').trigger('click')
|
||||
await csv.parse.returnValues[1]
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
await wrapper.find('#csv-finish').trigger('click')
|
||||
|
||||
expect(actions.addTab.calledOnce).to.equal(true)
|
||||
await actions.addTab.returnValues[0]
|
||||
expect(mutations.setCurrentTabId.calledOnceWith(state, newTabId)).to.equal(true)
|
||||
|
||||
await wrapper.find('.drop-area').trigger('click')
|
||||
await newDb.loadDb.returnValues[0]
|
||||
expect(actions.addTab.calledOnce).to.equal(true)
|
||||
expect(mutations.setCurrentTabId.calledOnce).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('csv.js', () => {
|
||||
{ id: 2, name: 'bar' }
|
||||
],
|
||||
meta: {
|
||||
fields: ['id', 'name']
|
||||
fields: ['id', 'name ']
|
||||
}
|
||||
}
|
||||
expect(csv.getResult(source)).to.eql({
|
||||
|
||||
@@ -49,6 +49,39 @@ describe('hint.js', () => {
|
||||
foo: ['fooId', 'name'],
|
||||
bar: ['barId']
|
||||
})
|
||||
expect(CM.showHint.firstCall.args[2].defaultTable).to.equal(null)
|
||||
})
|
||||
|
||||
it('Add default table if there is only one table in schema', () => {
|
||||
// mock store state
|
||||
const schema = [
|
||||
{
|
||||
name: 'foo',
|
||||
columns: [
|
||||
{ name: 'fooId', type: 'INTEGER' },
|
||||
{ name: 'name', type: 'NVARCHAR(20)' }
|
||||
]
|
||||
}
|
||||
]
|
||||
sinon.stub(state, 'schema').value(schema)
|
||||
|
||||
// mock showHint and editor
|
||||
sinon.stub(CM, 'showHint')
|
||||
const editor = {
|
||||
getTokenAt () {
|
||||
return {
|
||||
string: 'SELECT',
|
||||
type: 'keyword'
|
||||
}
|
||||
},
|
||||
getCursor: sinon.stub()
|
||||
}
|
||||
|
||||
const clock = sinon.useFakeTimers()
|
||||
hint.show(editor)
|
||||
clock.tick(500)
|
||||
|
||||
expect(CM.showHint.firstCall.args[2].defaultTable).to.equal('foo')
|
||||
})
|
||||
|
||||
it("Doesn't show hint when in string or space, or ';'", () => {
|
||||
|
||||