mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
Compare commits
23 Commits
310a939109
...
0.21.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c456ef135 | ||
|
|
c713c713b7 | ||
|
|
babf0074c0 | ||
|
|
e71e6700c1 | ||
|
|
84e66b8167 | ||
|
|
9e84cf269e | ||
|
|
e897b4913b | ||
|
|
0646f58ca0 | ||
|
|
c674bf11e3 | ||
|
|
2d8a91675e | ||
|
|
45b1021559 | ||
|
|
7216e996d1 | ||
|
|
6eae9a0f2d | ||
|
|
7486b32bd1 | ||
|
|
2c564767f8 | ||
|
|
289a727cbe | ||
|
|
5f2b8ba5a9 | ||
|
|
f0a4212e2b | ||
|
|
c8deff32c1 | ||
|
|
d56604a7d6 | ||
|
|
48e311bff8 | ||
|
|
518b22b489 | ||
|
|
a20dd7f849 |
21
.github/workflows/main.yml
vendored
21
.github/workflows/main.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Deploy to GitHub Pages and create release
|
name: Create release
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
@@ -7,7 +7,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
name: Deploy to GitHub Pages and create release
|
name: Create release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -24,10 +24,11 @@ jobs:
|
|||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
- name: Create archive
|
- name: Create archives
|
||||||
run: |
|
run: |
|
||||||
cd dist
|
cd dist
|
||||||
zip -9 -r dist.zip . -x "js/*.map" -x "/*.map"
|
zip -9 -r ../dist.zip . -x "js/*.map" -x "/*.map"
|
||||||
|
zip -9 -r ../dist_map.zip .
|
||||||
|
|
||||||
- name: Create Release Notes
|
- name: Create Release Notes
|
||||||
run: |
|
run: |
|
||||||
@@ -39,16 +40,6 @@ jobs:
|
|||||||
- name: Create release
|
- name: Create release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
artifacts: "dist/dist.zip"
|
artifacts: "dist.zip,dist_map.zip"
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
bodyFile: "CHANGELOG.md"
|
bodyFile: "CHANGELOG.md"
|
||||||
|
|
||||||
- name: Deploy 🚀
|
|
||||||
uses: JamesIves/github-pages-deploy-action@4.1.1
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
branch: build # The branch the action should deploy to.
|
|
||||||
folder: dist/ # The folder the action should deploy.
|
|
||||||
clean: true # Automatically remove deleted files from the deploy branch
|
|
||||||
clean-exclude: .nojekyll
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ With sqliteviz you can:
|
|||||||
https://user-images.githubusercontent.com/24638357/128249848-f8fab0f5-9add-46e0-a9c1-dd5085a8623e.mp4
|
https://user-images.githubusercontent.com/24638357/128249848-f8fab0f5-9add-46e0-a9c1-dd5085a8623e.mp4
|
||||||
|
|
||||||
## Quickstart
|
## Quickstart
|
||||||
The latest release of sqliteviz is deployed on GitHub Pages at [lana-k.github.io/sqliteviz][6].
|
The latest release of sqliteviz is deployed on [sqliteviz.com/app][6].
|
||||||
|
|
||||||
## Wiki
|
## Wiki
|
||||||
For user documentation, check out sqliteviz [Wiki][7].
|
For user documentation, check out sqliteviz [documentation][7].
|
||||||
|
|
||||||
## Motivation
|
## Motivation
|
||||||
It's a kind of middleground between [Plotly Falcon][1] and [Redash][2].
|
It's a kind of middleground between [Plotly Falcon][1] and [Redash][2].
|
||||||
@@ -34,8 +34,8 @@ It is built on top of [react-chart-editor][3], [PivotTable.js][12], [sql.js][4]
|
|||||||
[3]: https://github.com/plotly/react-chart-editor
|
[3]: https://github.com/plotly/react-chart-editor
|
||||||
[4]: https://github.com/sql-js/sql.js
|
[4]: https://github.com/sql-js/sql.js
|
||||||
[5]: https://github.com/vuejs/vue
|
[5]: https://github.com/vuejs/vue
|
||||||
[6]: https://lana-k.github.io/sqliteviz/
|
[6]: https://sqliteviz.com/app/
|
||||||
[7]: https://github.com/lana-k/sqliteviz/wiki
|
[7]: https://sqliteviz.com/docs
|
||||||
[8]: https://github.com/surmon-china/vue-codemirror#readme
|
[8]: https://github.com/surmon-china/vue-codemirror#readme
|
||||||
[9]: https://www.papaparse.com/
|
[9]: https://www.papaparse.com/
|
||||||
[10]: https://github.com/lana-k/sqliteviz/wiki/Predefined-queries
|
[10]: https://github.com/lana-k/sqliteviz/wiki/Predefined-queries
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:12-buster
|
FROM node:14-bullseye
|
||||||
|
|
||||||
RUN set -ex; \
|
RUN set -ex; \
|
||||||
echo 'deb http://deb.debian.org/debian unstable main' \
|
echo 'deb http://deb.debian.org/debian unstable main' \
|
||||||
|
|||||||
@@ -1,21 +1,44 @@
|
|||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
cleanup () {
|
||||||
|
rm -rf lib/dist $flag_file
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
if [ ! -f sample.csv ]; then
|
if [ ! -f sample.csv ]; then
|
||||||
wget --header="accept-encoding: gzip" -q -O- \
|
wget --header="accept-encoding: gzip" -q -O- \
|
||||||
https://github.com/plotly/datasets/raw/547090bd/wellspublic.csv \
|
https://github.com/plotly/datasets/raw/547090bd/wellspublic.csv \
|
||||||
| gunzip -c > sample.csv
|
| gunzip -c > sample.csv
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# for renice to work run like "sudo -E env PATH=$PATH ./make.sh"
|
||||||
|
test_ni=$(nice -n -1 nice)
|
||||||
|
if [ $test_ni == -1 ]; then
|
||||||
|
flag_file=$(mktemp)
|
||||||
|
fi
|
||||||
|
(
|
||||||
|
while [ -f $flag_file ]; do
|
||||||
|
root_pid=$(
|
||||||
|
docker ps -f status=running -f name='^sqljs-benchmark-' -q \
|
||||||
|
| xargs -r -I{} -- docker inspect -f '{{.State.Pid}}' {}
|
||||||
|
)
|
||||||
|
if [ ! -z $root_pid ]; then
|
||||||
|
procpath query -d $'\n' "$..children[?(@.stat.pid == $root_pid)]..pid" \
|
||||||
|
| xargs -I{} -- renice -n -1 -p {} > /dev/null
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done &
|
||||||
|
)
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
for d in lib/build-* ; do
|
for d in lib/build-* ; do
|
||||||
rm -r lib/dist || true
|
rm -rf lib/dist
|
||||||
cp -r $d lib/dist
|
cp -r $d lib/dist
|
||||||
|
|
||||||
name=$(basename $d)
|
name=$(basename $d)
|
||||||
docker build -t sqliteviz/sqljs-benchmark:$name .
|
docker build -t sqliteviz/sqljs-benchmark:$name .
|
||||||
docker rm sqljs-benchmark-$name 2> /dev/null || true
|
docker rm sqljs-benchmark-$name 2> /dev/null || true
|
||||||
docker run -it --name sqljs-benchmark-$name sqliteviz/sqljs-benchmark:$name
|
docker run -it --cpus 2 --name sqljs-benchmark-$name sqliteviz/sqljs-benchmark:$name
|
||||||
docker cp sqljs-benchmark-$name:/tmp/build/suite-result.json ${name}-result.json
|
docker cp sqljs-benchmark-$name:/tmp/build/suite-result.json ${name}-result.json
|
||||||
docker rm sqljs-benchmark-$name
|
docker rm sqljs-benchmark-$name
|
||||||
done
|
done
|
||||||
|
|
||||||
rm -r lib/dist
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"benchmark_path = Path('/path/to/sqliteviz/project/sqliteviz/lib/sql-js/benchmark')"
|
"benchmark_path = Path()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from pathlib import Path
|
|||||||
from urllib import request
|
from urllib import request
|
||||||
|
|
||||||
|
|
||||||
amalgamation_url = 'https://sqlite.org/2021/sqlite-amalgamation-3360000.zip'
|
amalgamation_url = 'https://sqlite.org/2022/sqlite-amalgamation-3390000.zip'
|
||||||
|
|
||||||
# Extension-functions
|
# Extension-functions
|
||||||
# ===================
|
# ===================
|
||||||
@@ -20,7 +20,7 @@ contrib_functions_url = 'https://sqlite.org/contrib/download/extension-functions
|
|||||||
extension_urls = (
|
extension_urls = (
|
||||||
# Miscellaneous extensions
|
# Miscellaneous extensions
|
||||||
# ========================
|
# ========================
|
||||||
('https://sqlite.org/src/raw/c6bd5d24?at=series.c', 'sqlite3_series_init'),
|
('https://sqlite.org/src/raw/8d79354f?at=series.c', 'sqlite3_series_init'),
|
||||||
('https://sqlite.org/src/raw/dbfd8543?at=closure.c', 'sqlite3_closure_init'),
|
('https://sqlite.org/src/raw/dbfd8543?at=closure.c', 'sqlite3_closure_init'),
|
||||||
('https://sqlite.org/src/raw/5bb2264c?at=uuid.c', 'sqlite3_uuid_init'),
|
('https://sqlite.org/src/raw/5bb2264c?at=uuid.c', 'sqlite3_uuid_init'),
|
||||||
('https://sqlite.org/src/raw/5853b0e5?at=regexp.c', 'sqlite3_regexp_init'),
|
('https://sqlite.org/src/raw/5853b0e5?at=regexp.c', 'sqlite3_regexp_init'),
|
||||||
|
|||||||
2
lib/sql-js/dist/sql-wasm.js
vendored
2
lib/sql-js/dist/sql-wasm.js
vendored
File diff suppressed because one or more lines are too long
BIN
lib/sql-js/dist/sql-wasm.wasm
vendored
BIN
lib/sql-js/dist/sql-wasm.wasm
vendored
Binary file not shown.
26334
package-lock.json
generated
26334
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sqliteviz",
|
"name": "sqliteviz",
|
||||||
"version": "0.18.0",
|
"version": "0.21.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -69,6 +69,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<!-- head extention slot start -->
|
||||||
|
<!-- head extention slot end -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
@@ -93,6 +95,8 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- extention slot start -->
|
||||||
|
<!-- extention slot end -->
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
3
src/assets/images/logo_simple.svg
Normal file
3
src/assets/images/logo_simple.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M26.8311 34.6554C25.4675 33.8178 24.177 32.8655 22.9735 31.8086V14.3616H30.5728V36.753C29.3146 36.0982 28.0673 35.399 26.8311 34.6554ZM41.4669 25.8486H33.8675V38.1514C36.3477 39.3055 38.884 40.3334 41.4669 41.2313V25.8486ZM22.9735 35.3046L22.4768 34.9051C21.7152 34.2725 21.0033 33.6232 20.3245 32.9739L2.2947 30.8763L5.60596 37.3024L28.7848 39.2002C26.7511 38.0537 24.8082 36.7513 22.9735 35.3046ZM41.0695 44.6441C38.4829 43.7946 35.9458 42.7997 33.4702 41.6641L32.543 41.198L17.2616 40.1825L19.8444 45.593L46.5 46.209C44.6788 45.7761 42.8411 45.2434 41.0695 44.6441ZM9.34768 14.3616C12.2649 19.4905 15.735 24.2807 19.6954 28.6455V11.2651L2.99007 2.99115L1.5 22.3859L18.702 31.2592C14.1919 26.5283 10.9703 20.7087 9.34768 14.3616Z" fill="#119DFF"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 862 B |
@@ -112,6 +112,7 @@ import SqlTable from '@/components/SqlTable'
|
|||||||
import Logs from '@/components/Logs'
|
import Logs from '@/components/Logs'
|
||||||
import time from '@/lib/utils/time'
|
import time from '@/lib/utils/time'
|
||||||
import fIo from '@/lib/utils/fileIo'
|
import fIo from '@/lib/utils/fileIo'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CsvImport',
|
name: 'CsvImport',
|
||||||
@@ -335,6 +336,7 @@ export default {
|
|||||||
this.$store.commit('setCurrentTabId', tabId)
|
this.$store.commit('setCurrentTabId', tabId)
|
||||||
this.importCsvCompleted = false
|
this.importCsvCompleted = false
|
||||||
this.$emit('finish')
|
this.$emit('finish')
|
||||||
|
events.send('inquiry.create', null, { auto: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ import fIo from '@/lib/utils/fileIo'
|
|||||||
import ChangeDbIcon from '@/components/svg/changeDb'
|
import ChangeDbIcon from '@/components/svg/changeDb'
|
||||||
import database from '@/lib/database'
|
import database from '@/lib/database'
|
||||||
import CsvImport from '@/components/CsvImport'
|
import CsvImport from '@/components/CsvImport'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DbUploader',
|
name: 'DbUploader',
|
||||||
@@ -127,6 +128,11 @@ export default {
|
|||||||
if (fIo.isDatabase(file)) {
|
if (fIo.isDatabase(file)) {
|
||||||
this.loadDb(file)
|
this.loadDb(file)
|
||||||
} else {
|
} else {
|
||||||
|
events.send('database.import', file.size, {
|
||||||
|
from: 'csv',
|
||||||
|
new_db: true
|
||||||
|
})
|
||||||
|
|
||||||
this.file = file
|
this.file = file
|
||||||
await this.$nextTick()
|
await this.$nextTick()
|
||||||
const csvImport = this.$refs.addCsv
|
const csvImport = this.$refs.addCsv
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import Worker from './_worker.js'
|
|||||||
// https://github.com/nolanlawson/promise-worker
|
// https://github.com/nolanlawson/promise-worker
|
||||||
import PromiseWorker from 'promise-worker'
|
import PromiseWorker from 'promise-worker'
|
||||||
|
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
function getNewDatabase () {
|
function getNewDatabase () {
|
||||||
const worker = new Worker()
|
const worker = new Worker()
|
||||||
return new Database(worker)
|
return new Database(worker)
|
||||||
@@ -76,6 +78,11 @@ class Database {
|
|||||||
|
|
||||||
this.dbName = file ? fu.getFileName(file) : 'database'
|
this.dbName = file ? fu.getFileName(file) : 'database'
|
||||||
this.refreshSchema()
|
this.refreshSchema()
|
||||||
|
|
||||||
|
events.send('database.import', file ? file.size : 0, {
|
||||||
|
from: file ? 'sqlite' : 'none',
|
||||||
|
new_db: true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshSchema () {
|
async refreshSchema () {
|
||||||
@@ -114,6 +121,7 @@ class Database {
|
|||||||
throw new Error(data.error)
|
throw new Error(data.error)
|
||||||
}
|
}
|
||||||
fu.exportToFile(data, fileName)
|
fu.exportToFile(data, fileName)
|
||||||
|
events.send('database.export', data.byteLength, { to: 'sqlite' })
|
||||||
}
|
}
|
||||||
|
|
||||||
async validateTableName (name) {
|
async validateTableName (name) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { nanoid } from 'nanoid'
|
import { nanoid } from 'nanoid'
|
||||||
import fu from '@/lib/utils/fileIo'
|
import fu from '@/lib/utils/fileIo'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
import migration from './_migrations'
|
import migration from './_migrations'
|
||||||
|
|
||||||
const migrate = migration._migrate
|
const migrate = migration._migrate
|
||||||
@@ -103,9 +104,19 @@ export default {
|
|||||||
importInquiries () {
|
importInquiries () {
|
||||||
return fu.importFile()
|
return fu.importFile()
|
||||||
.then(str => {
|
.then(str => {
|
||||||
return this.deserialiseInquiries(str)
|
const inquires = this.deserialiseInquiries(str)
|
||||||
|
|
||||||
|
events.send('inquiry.import', inquires.length)
|
||||||
|
|
||||||
|
return inquires
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
export (inquiryList, fileName) {
|
||||||
|
const jsonStr = this.serialiseInquiries(inquiryList)
|
||||||
|
fu.exportToFile(jsonStr, fileName)
|
||||||
|
|
||||||
|
events.send('inquiry.export', inquiryList.length)
|
||||||
|
},
|
||||||
|
|
||||||
async readPredefinedInquiries () {
|
async readPredefinedInquiries () {
|
||||||
const res = await fu.readFile('./inquiries.json')
|
const res = await fu.readFile('./inquiries.json')
|
||||||
|
|||||||
12
src/lib/utils/events.js
Normal file
12
src/lib/utils/events.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export default {
|
||||||
|
send (name, value, labels) {
|
||||||
|
const event = new CustomEvent('sqliteviz-app-event', {
|
||||||
|
detail: {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
labels: labels || {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
window.dispatchEvent(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import events from '@/lib/utils/events'
|
||||||
let refresh = false
|
let refresh = false
|
||||||
|
|
||||||
function invokeServiceWorkerUpdateFlow (registration) {
|
function invokeServiceWorkerUpdateFlow (registration) {
|
||||||
@@ -41,4 +42,8 @@ if ('serviceWorker' in navigator) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
window.addEventListener('appinstalled', () => {
|
||||||
|
events.send('pwa.install')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export default {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
#app-info-icon {
|
#app-info-icon {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
width: 24px;
|
||||||
}
|
}
|
||||||
#app-info-container {
|
#app-info-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -159,7 +159,6 @@ import TextField from '@/components/TextField'
|
|||||||
import CheckBox from '@/components/CheckBox'
|
import CheckBox from '@/components/CheckBox'
|
||||||
import tooltipMixin from '@/tooltipMixin'
|
import tooltipMixin from '@/tooltipMixin'
|
||||||
import storedInquiries from '@/lib/storedInquiries'
|
import storedInquiries from '@/lib/storedInquiries'
|
||||||
import fu from '@/lib/utils/fileIo'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Inquiries',
|
name: 'Inquiries',
|
||||||
@@ -385,8 +384,7 @@ export default {
|
|||||||
return this.$store.state.tabs.findIndex(tab => tab.id === id)
|
return this.$store.state.tabs.findIndex(tab => tab.id === id)
|
||||||
},
|
},
|
||||||
exportToFile (inquiryList, fileName) {
|
exportToFile (inquiryList, fileName) {
|
||||||
const jsonStr = storedInquiries.serialiseInquiries(inquiryList)
|
storedInquiries.export(inquiryList, fileName)
|
||||||
fu.exportToFile(jsonStr, fileName)
|
|
||||||
},
|
},
|
||||||
exportSelectedInquiries () {
|
exportSelectedInquiries () {
|
||||||
const inquiryList = this.allInquiries.filter(
|
const inquiryList = this.allInquiries.filter(
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav>
|
<nav>
|
||||||
<div>
|
<div id="nav-links">
|
||||||
|
<a href="https://sqliteviz.com">
|
||||||
|
<img :src="require('@/assets/images/logo_simple.svg')">
|
||||||
|
</a>
|
||||||
<router-link to="/workspace">Workspace</router-link>
|
<router-link to="/workspace">Workspace</router-link>
|
||||||
<router-link to="/inquiries">Inquiries</router-link>
|
<router-link to="/inquiries">Inquiries</router-link>
|
||||||
<a href="https://github.com/lana-k/sqliteviz/wiki" target="_blank">Help</a>
|
<a href="https://sqliteviz.com/docs" target="_blank">Help</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="nav-buttons">
|
<div id="nav-buttons">
|
||||||
<button
|
<button
|
||||||
@@ -57,6 +60,7 @@ import TextField from '@/components/TextField'
|
|||||||
import CloseIcon from '@/components/svg/close'
|
import CloseIcon from '@/components/svg/close'
|
||||||
import storedInquiries from '@/lib/storedInquiries'
|
import storedInquiries from '@/lib/storedInquiries'
|
||||||
import AppDiagnosticInfo from './AppDiagnosticInfo'
|
import AppDiagnosticInfo from './AppDiagnosticInfo'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MainMenu',
|
name: 'MainMenu',
|
||||||
@@ -110,6 +114,8 @@ export default {
|
|||||||
this.$router.push('/workspace')
|
this.$router.push('/workspace')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
events.send('inquiry.create', null, { auto: false })
|
||||||
},
|
},
|
||||||
cancelSave () {
|
cancelSave () {
|
||||||
this.$modal.hide('save')
|
this.$modal.hide('save')
|
||||||
@@ -163,6 +169,7 @@ export default {
|
|||||||
|
|
||||||
// Signal about saving
|
// Signal about saving
|
||||||
this.$root.$emit('inquirySaved')
|
this.$root.$emit('inquirySaved')
|
||||||
|
events.send('inquiry.save')
|
||||||
},
|
},
|
||||||
_keyListener (e) {
|
_keyListener (e) {
|
||||||
if (this.$route.path === '/workspace') {
|
if (this.$route.path === '/workspace') {
|
||||||
@@ -237,4 +244,12 @@ button {
|
|||||||
#nav-buttons {
|
#nav-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#nav-links {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
#nav-links img {
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import fIo from '@/lib/utils/fileIo'
|
import fIo from '@/lib/utils/fileIo'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
import TableDescription from './TableDescription'
|
import TableDescription from './TableDescription'
|
||||||
import TextField from '@/components/TextField'
|
import TextField from '@/components/TextField'
|
||||||
import TreeChevron from '@/components/svg/treeChevron'
|
import TreeChevron from '@/components/svg/treeChevron'
|
||||||
@@ -86,6 +87,11 @@ export default {
|
|||||||
csvImport.reset()
|
csvImport.reset()
|
||||||
await csvImport.previewCsv()
|
await csvImport.previewCsv()
|
||||||
csvImport.open()
|
csvImport.open()
|
||||||
|
|
||||||
|
events.send('database.import', this.file.size, {
|
||||||
|
from: 'csv',
|
||||||
|
new_db: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,15 @@ import PlotlyEditor from 'react-chart-editor'
|
|||||||
import chartHelper from '@/lib/chartHelper'
|
import chartHelper from '@/lib/chartHelper'
|
||||||
import dereference from 'react-chart-editor/lib/lib/dereference'
|
import dereference from 'react-chart-editor/lib/lib/dereference'
|
||||||
import fIo from '@/lib/utils/fileIo'
|
import fIo from '@/lib/utils/fileIo'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Chart',
|
name: 'Chart',
|
||||||
props: ['dataSources', 'initOptions', 'importToPngEnabled', 'importToSvgEnabled'],
|
props: [
|
||||||
|
'dataSources', 'initOptions',
|
||||||
|
'importToPngEnabled', 'importToSvgEnabled',
|
||||||
|
'forPivot'
|
||||||
|
],
|
||||||
components: {
|
components: {
|
||||||
PlotlyEditor
|
PlotlyEditor
|
||||||
},
|
},
|
||||||
@@ -60,6 +65,17 @@ export default {
|
|||||||
plotly.setPlotConfig({
|
plotly.setPlotConfig({
|
||||||
notifyOnLogging: 1
|
notifyOnLogging: 1
|
||||||
})
|
})
|
||||||
|
this.$watch(
|
||||||
|
() => this.state.data.map(trace => `${trace.type}-${trace.mode}`)
|
||||||
|
.join(','),
|
||||||
|
(value) => {
|
||||||
|
events.send('viz_plotly.render', null, {
|
||||||
|
type: value,
|
||||||
|
pivot: !!this.forPivot
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.resizeObserver = new ResizeObserver(this.handleResize)
|
this.resizeObserver = new ResizeObserver(this.handleResize)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import pivotHelper from './pivotHelper'
|
|||||||
import Chart from '@/views/Main/Workspace/Tabs/Tab/DataView/Chart'
|
import Chart from '@/views/Main/Workspace/Tabs/Tab/DataView/Chart'
|
||||||
import chartHelper from '@/lib/chartHelper'
|
import chartHelper from '@/lib/chartHelper'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
const ChartClass = Vue.extend(Chart)
|
const ChartClass = Vue.extend(Chart)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -87,8 +88,17 @@ export default {
|
|||||||
'pivotOptions.rendererName': {
|
'pivotOptions.rendererName': {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler () {
|
handler () {
|
||||||
this.$emit('update:importToPngEnabled', this.pivotOptions.rendererName !== 'TSV Export')
|
this.$emit(
|
||||||
this.$emit('update:importToSvgEnabled', this.viewStandartChart || this.viewCustomChart)
|
'update:importToPngEnabled',
|
||||||
|
this.pivotOptions.rendererName !== 'TSV Export'
|
||||||
|
)
|
||||||
|
this.$emit(
|
||||||
|
'update:importToSvgEnabled',
|
||||||
|
this.viewStandartChart || this.viewCustomChart
|
||||||
|
)
|
||||||
|
events.send('viz_pivot.render', null, {
|
||||||
|
type: this.pivotOptions.rendererName
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pivotOptions () {
|
pivotOptions () {
|
||||||
@@ -179,11 +189,11 @@ export default {
|
|||||||
async prepareCopy () {
|
async prepareCopy () {
|
||||||
if (this.viewCustomChart) {
|
if (this.viewCustomChart) {
|
||||||
return await this.pivotOptions.rendererOptions.customChartComponent.prepareCopy()
|
return await this.pivotOptions.rendererOptions.customChartComponent.prepareCopy()
|
||||||
} else if (this.viewStandartChart) {
|
|
||||||
return await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png')
|
|
||||||
} else {
|
|
||||||
return await pivotHelper.getPivotCanvas(this.$refs.pivotOutput)
|
|
||||||
}
|
}
|
||||||
|
if (this.viewStandartChart) {
|
||||||
|
return await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png')
|
||||||
|
}
|
||||||
|
return await pivotHelper.getPivotCanvas(this.$refs.pivotOutput)
|
||||||
},
|
},
|
||||||
|
|
||||||
async saveAsSvg () {
|
async saveAsSvg () {
|
||||||
@@ -198,20 +208,23 @@ export default {
|
|||||||
saveAsHtml () {
|
saveAsHtml () {
|
||||||
if (this.viewCustomChart) {
|
if (this.viewCustomChart) {
|
||||||
this.pivotOptions.rendererOptions.customChartComponent.saveAsHtml()
|
this.pivotOptions.rendererOptions.customChartComponent.saveAsHtml()
|
||||||
} else if (this.viewStandartChart) {
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.viewStandartChart) {
|
||||||
const chartState = chartHelper.getChartData(this.$refs.pivotOutput)
|
const chartState = chartHelper.getChartData(this.$refs.pivotOutput)
|
||||||
fIo.exportToFile(
|
fIo.exportToFile(
|
||||||
chartHelper.getHtml(chartState),
|
chartHelper.getHtml(chartState),
|
||||||
'chart.html',
|
'chart.html',
|
||||||
'text/html'
|
'text/html'
|
||||||
)
|
)
|
||||||
} else {
|
return
|
||||||
fIo.exportToFile(
|
|
||||||
pivotHelper.getPivotHtml(this.$refs.pivotOutput),
|
|
||||||
'pivot.html',
|
|
||||||
'text/html'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
fIo.exportToFile(
|
||||||
|
pivotHelper.getPivotHtml(this.$refs.pivotOutput),
|
||||||
|
'pivot.html',
|
||||||
|
'text/html'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ export function _getDataSources (pivotData) {
|
|||||||
|
|
||||||
function customChartRenderer (data, options) {
|
function customChartRenderer (data, options) {
|
||||||
options.customChartComponent.dataSources = _getDataSources(data)
|
options.customChartComponent.dataSources = _getDataSources(data)
|
||||||
|
options.customChartComponent.forPivot = true
|
||||||
|
|
||||||
options.customChartComponent.$mount()
|
options.customChartComponent.$mount()
|
||||||
|
|
||||||
return $(options.customChartComponent.$el)
|
return $(options.customChartComponent.$el)
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ import ClipboardIcon from '@/components/svg/clipboard'
|
|||||||
import cIo from '@/lib/utils/clipboardIo'
|
import cIo from '@/lib/utils/clipboardIo'
|
||||||
import loadingDialog from '@/components/LoadingDialog'
|
import loadingDialog from '@/components/LoadingDialog'
|
||||||
import time from '@/lib/utils/time'
|
import time from '@/lib/utils/time'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DataView',
|
name: 'DataView',
|
||||||
@@ -123,6 +124,11 @@ export default {
|
|||||||
dataToCopy: null
|
dataToCopy: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
plotlyInPivot () {
|
||||||
|
return this.mode === 'pivot' && this.$refs.viewComponent.viewCustomChart
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
mode () {
|
mode () {
|
||||||
this.$emit('update')
|
this.$emit('update')
|
||||||
@@ -148,6 +154,7 @@ export default {
|
|||||||
*/
|
*/
|
||||||
await time.sleep(0)
|
await time.sleep(0)
|
||||||
this.$refs.viewComponent.saveAsPng()
|
this.$refs.viewComponent.saveAsPng()
|
||||||
|
this.exportSignal('png')
|
||||||
},
|
},
|
||||||
getOptionsForSave () {
|
getOptionsForSave () {
|
||||||
return this.$refs.viewComponent.getOptionsForSave()
|
return this.$refs.viewComponent.getOptionsForSave()
|
||||||
@@ -178,6 +185,7 @@ export default {
|
|||||||
async copyToClipboard () {
|
async copyToClipboard () {
|
||||||
cIo.copyImage(this.dataToCopy)
|
cIo.copyImage(this.dataToCopy)
|
||||||
this.$modal.hide('prepareCopy')
|
this.$modal.hide('prepareCopy')
|
||||||
|
this.exportSignal('clipboard')
|
||||||
},
|
},
|
||||||
cancelCopy () {
|
cancelCopy () {
|
||||||
this.dataToCopy = null
|
this.dataToCopy = null
|
||||||
@@ -186,9 +194,26 @@ export default {
|
|||||||
|
|
||||||
saveAsSvg () {
|
saveAsSvg () {
|
||||||
this.$refs.viewComponent.saveAsSvg()
|
this.$refs.viewComponent.saveAsSvg()
|
||||||
|
this.exportSignal('svg')
|
||||||
},
|
},
|
||||||
saveAsHtml () {
|
saveAsHtml () {
|
||||||
this.$refs.viewComponent.saveAsHtml()
|
this.$refs.viewComponent.saveAsHtml()
|
||||||
|
this.exportSignal('html')
|
||||||
|
},
|
||||||
|
exportSignal (to) {
|
||||||
|
const eventLabels = { type: to }
|
||||||
|
|
||||||
|
if (this.mode === 'chart' || this.plotlyInPivot) {
|
||||||
|
eventLabels.pivot = this.plotlyInPivot
|
||||||
|
}
|
||||||
|
|
||||||
|
events.send(
|
||||||
|
this.mode === 'chart' || this.plotlyInPivot
|
||||||
|
? 'viz_plotly.export'
|
||||||
|
: 'viz_pivot.export',
|
||||||
|
null,
|
||||||
|
eventLabels
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ import fIo from '@/lib/utils/fileIo'
|
|||||||
import cIo from '@/lib/utils/clipboardIo'
|
import cIo from '@/lib/utils/clipboardIo'
|
||||||
import time from '@/lib/utils/time'
|
import time from '@/lib/utils/time'
|
||||||
import loadingDialog from '@/components/LoadingDialog'
|
import loadingDialog from '@/components/LoadingDialog'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RunResult',
|
name: 'RunResult',
|
||||||
@@ -117,10 +118,24 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
exportToCsv () {
|
exportToCsv () {
|
||||||
|
if (this.result && this.result.values) {
|
||||||
|
events.send('resultset.export',
|
||||||
|
this.result.values[this.result.columns[0]].length,
|
||||||
|
{ to: 'csv' }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fIo.exportToFile(csv.serialize(this.result), 'result_set.csv', 'text/csv')
|
fIo.exportToFile(csv.serialize(this.result), 'result_set.csv', 'text/csv')
|
||||||
},
|
},
|
||||||
|
|
||||||
async prepareCopy () {
|
async prepareCopy () {
|
||||||
|
if (this.result && this.result.values) {
|
||||||
|
events.send('resultset.export',
|
||||||
|
this.result.values[this.result.columns[0]].length,
|
||||||
|
{ to: 'clipboard' }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if ('ClipboardItem' in window) {
|
if ('ClipboardItem' in window) {
|
||||||
this.preparingCopy = true
|
this.preparingCopy = true
|
||||||
this.$modal.show('prepareCSVCopy')
|
this.$modal.show('prepareCSVCopy')
|
||||||
|
|||||||
@@ -3,14 +3,20 @@ import 'codemirror/addon/hint/show-hint.js'
|
|||||||
import 'codemirror/addon/hint/sql-hint.js'
|
import 'codemirror/addon/hint/sql-hint.js'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
|
|
||||||
|
function _getHintText (hint) {
|
||||||
|
return typeof hint === 'string' ? hint : hint.text
|
||||||
|
}
|
||||||
export function getHints (cm, options) {
|
export function getHints (cm, options) {
|
||||||
const token = cm.getTokenAt(cm.getCursor()).string.toUpperCase()
|
|
||||||
const result = CM.hint.sql(cm, options)
|
const result = CM.hint.sql(cm, options)
|
||||||
|
|
||||||
// Don't show the hint if there is only one option
|
// Don't show the hint if there is only one option
|
||||||
// and the token is already completed with this option
|
// and the replacingText is already equals to this option
|
||||||
if (result.list.length === 1 && result.list[0].text.toUpperCase() === token) {
|
const replacedText = cm.getRange(result.from, result.to).toUpperCase()
|
||||||
|
if (result.list.length === 1 &&
|
||||||
|
_getHintText(result.list[0]).toUpperCase() === replacedText) {
|
||||||
result.list = []
|
result.list = []
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import DataView from './DataView'
|
|||||||
import RunResult from './RunResult'
|
import RunResult from './RunResult'
|
||||||
import time from '@/lib/utils/time'
|
import time from '@/lib/utils/time'
|
||||||
import Teleport from 'vue2-teleport'
|
import Teleport from 'vue2-teleport'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Tab',
|
name: 'Tab',
|
||||||
@@ -108,6 +109,8 @@ export default {
|
|||||||
const fromPosition = this.layout[from]
|
const fromPosition = this.layout[from]
|
||||||
this.layout[from] = this.layout[to]
|
this.layout[from] = this.layout[to]
|
||||||
this.layout[to] = fromPosition
|
this.layout[to] = fromPosition
|
||||||
|
|
||||||
|
events.send('inquiry.panel', null, { panel: to })
|
||||||
},
|
},
|
||||||
onDataViewUpdate () {
|
onDataViewUpdate () {
|
||||||
this.$store.commit('updateTab', { index: this.tabIndex, isSaved: false })
|
this.$store.commit('updateTab', { index: this.tabIndex, isSaved: false })
|
||||||
@@ -121,11 +124,21 @@ export default {
|
|||||||
const start = new Date()
|
const start = new Date()
|
||||||
this.result = await state.db.execute(this.query + ';')
|
this.result = await state.db.execute(this.query + ';')
|
||||||
this.time = time.getPeriod(start, new Date())
|
this.time = time.getPeriod(start, new Date())
|
||||||
|
|
||||||
|
if (this.result && this.result.values) {
|
||||||
|
events.send('resultset.create',
|
||||||
|
this.result.values[this.result.columns[0]].length
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
events.send('query.run', parseFloat(this.time), { status: 'success' })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.error = {
|
this.error = {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: err
|
message: err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
events.send('query.run', 0, { status: 'error' })
|
||||||
}
|
}
|
||||||
state.db.refreshSchema()
|
state.db.refreshSchema()
|
||||||
this.isGettingResults = false
|
this.isGettingResults = false
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
import Splitpanes from '@/components/Splitpanes'
|
import Splitpanes from '@/components/Splitpanes'
|
||||||
import Schema from './Schema'
|
import Schema from './Schema'
|
||||||
import Tabs from './Tabs'
|
import Tabs from './Tabs'
|
||||||
|
import events from '@/lib/utils/events'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Workspace',
|
name: 'Workspace',
|
||||||
@@ -49,6 +50,8 @@ export default {
|
|||||||
|
|
||||||
const tabId = await this.$store.dispatch('addTab', { query: stmt })
|
const tabId = await this.$store.dispatch('addTab', { query: stmt })
|
||||||
this.$store.commit('setCurrentTabId', tabId)
|
this.$store.commit('setCurrentTabId', tabId)
|
||||||
|
|
||||||
|
events.send('inquiry.create', null, { auto: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ describe('Logs.vue', () => {
|
|||||||
await wrapper.vm.$nextTick()
|
await wrapper.vm.$nextTick()
|
||||||
messages.push({ type: 'error', message: 'msg 5' })
|
messages.push({ type: 'error', message: 'msg 5' })
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
await wrapper.vm.$nextTick()
|
await wrapper.vm.$nextTick()
|
||||||
const height = wrapper.find('.logs-container').element.scrollHeight
|
const height = wrapper.find('.logs-container').element.scrollHeight
|
||||||
expect(wrapper.find('.logs-container').element.scrollTop)
|
expect(wrapper.find('.logs-container').element.scrollTop)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ describe('database.js', () => {
|
|||||||
expect(schema[0].columns[0].type).to.equal('N/A')
|
expect(schema[0].columns[0].type).to.equal('N/A')
|
||||||
|
|
||||||
expect(schema[0].columns[1].name).to.equal('col2')
|
expect(schema[0].columns[1].name).to.equal('col2')
|
||||||
expect(schema[0].columns[1].type).to.equal('integer')
|
expect(schema[0].columns[1].type).to.equal('INTEGER')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('creates schema with view', async () => {
|
it('creates schema with view', async () => {
|
||||||
@@ -68,12 +68,12 @@ describe('database.js', () => {
|
|||||||
|
|
||||||
expect(schema[0].columns[1]).to.eql({
|
expect(schema[0].columns[1]).to.eql({
|
||||||
name: 'col2',
|
name: 'col2',
|
||||||
type: 'integer'
|
type: 'INTEGER'
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(schema[1].columns).to.eql([{
|
expect(schema[1].columns).to.eql([{
|
||||||
name: 'amount',
|
name: 'amount',
|
||||||
type: 'integer'
|
type: 'INTEGER'
|
||||||
}])
|
}])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ describe('time.js', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('sleep resolves after n ms', async () => {
|
it('sleep resolves after n ms', async () => {
|
||||||
let before = performance.now()
|
let before = Date.now()
|
||||||
await time.sleep(10)
|
await time.sleep(10)
|
||||||
expect(performance.now() - before).to.be.least(10)
|
expect(Date.now() - before).to.be.least(10)
|
||||||
|
|
||||||
before = performance.now()
|
before = Date.now()
|
||||||
await time.sleep(30)
|
await time.sleep(30)
|
||||||
expect(performance.now() - before).to.be.least(30)
|
expect(Date.now() - before).to.be.least(30)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -461,6 +461,7 @@ describe('Pivot.vue', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('saveAsPng - table', async () => {
|
it('saveAsPng - table', async () => {
|
||||||
|
sinon.stub(pivotHelper, 'getPivotCanvas').returns(document.createElement('canvas'))
|
||||||
sinon.stub(HTMLCanvasElement.prototype, 'toDataURL').returns('canvas data url')
|
sinon.stub(HTMLCanvasElement.prototype, 'toDataURL').returns('canvas data url')
|
||||||
sinon.stub(fIo, 'downloadFromUrl')
|
sinon.stub(fIo, 'downloadFromUrl')
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { _getDataSources, getPivotCanvas, getPivotHtml }
|
import { _getDataSources, getPivotCanvas, getPivotHtml }
|
||||||
from '@/views/Main/Workspace/Tabs/Tab/DataView/Pivot/pivotHelper'
|
from '@/views/Main/Workspace/Tabs/Tab/DataView/Pivot/pivotHelper'
|
||||||
|
|
||||||
describe('pivotHelper.js', () => {
|
describe('pivotHelper.js', () => {
|
||||||
it('_getDataSources returns data sources', () => {
|
it('_getDataSources returns data sources', () => {
|
||||||
|
|||||||
@@ -138,15 +138,37 @@ describe('hint.js', () => {
|
|||||||
'getHints returns [ ] if there is only one option and token is completed with this option',
|
'getHints returns [ ] if there is only one option and token is completed with this option',
|
||||||
() => {
|
() => {
|
||||||
// mock CM.hint.sql and editor
|
// mock CM.hint.sql and editor
|
||||||
sinon.stub(CM.hint, 'sql').returns({ list: [{ text: 'SELECT' }] })
|
sinon.stub(CM.hint, 'sql').returns({
|
||||||
|
list: [{ text: 'SELECT' }],
|
||||||
|
from: null, // from/to doesn't metter because getRange is mocked
|
||||||
|
to: null
|
||||||
|
})
|
||||||
|
|
||||||
const editor = {
|
const editor = {
|
||||||
getTokenAt () {
|
getRange () {
|
||||||
return {
|
return 'select'
|
||||||
string: 'select',
|
}
|
||||||
type: 'keyword'
|
}
|
||||||
}
|
|
||||||
},
|
const hints = getHints(editor, {})
|
||||||
getCursor: sinon.stub()
|
expect(hints.list).to.eql([])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
'getHints returns [ ] if there is only one string option and token ' +
|
||||||
|
'is completed with this option',
|
||||||
|
() => {
|
||||||
|
// mock CM.hint.sql and editor
|
||||||
|
sinon.stub(CM.hint, 'sql').returns({
|
||||||
|
list: ['house.name'],
|
||||||
|
from: null, // from/to doesn't metter because getRange is mocked
|
||||||
|
to: null
|
||||||
|
})
|
||||||
|
const editor = {
|
||||||
|
getRange () {
|
||||||
|
return 'house.name'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const hints = getHints(editor, {})
|
const hints = getHints(editor, {})
|
||||||
@@ -160,15 +182,11 @@ describe('hint.js', () => {
|
|||||||
{ text: 'SELECT' },
|
{ text: 'SELECT' },
|
||||||
{ text: 'ST' }
|
{ text: 'ST' }
|
||||||
]
|
]
|
||||||
sinon.stub(CM.hint, 'sql').returns({ list })
|
sinon.stub(CM.hint, 'sql').returns({ list, from: null, to: null })
|
||||||
const editor = {
|
const editor = {
|
||||||
getTokenAt () {
|
getRange () {
|
||||||
return {
|
return 'se'
|
||||||
string: 'se',
|
}
|
||||||
type: 'keyword'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getCursor: sinon.stub()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const hints = getHints(editor, {})
|
const hints = getHints(editor, {})
|
||||||
@@ -182,15 +200,11 @@ describe('hint.js', () => {
|
|||||||
() => {
|
() => {
|
||||||
// mock CM.hint.sql and editor
|
// mock CM.hint.sql and editor
|
||||||
const list = [{ text: 'SELECT' }]
|
const list = [{ text: 'SELECT' }]
|
||||||
sinon.stub(CM.hint, 'sql').returns({ list })
|
sinon.stub(CM.hint, 'sql').returns({ list, from: null, to: null })
|
||||||
const editor = {
|
const editor = {
|
||||||
getTokenAt () {
|
getRange () {
|
||||||
return {
|
return 'sele'
|
||||||
string: 'sele',
|
}
|
||||||
type: 'keyword'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getCursor: sinon.stub()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const hints = getHints(editor, {})
|
const hints = getHints(editor, {})
|
||||||
|
|||||||
@@ -41,5 +41,12 @@ module.exports = {
|
|||||||
.end()
|
.end()
|
||||||
|
|
||||||
config.module.rule('js').exclude.add(/worker\.js$/)
|
config.module.rule('js').exclude.add(/worker\.js$/)
|
||||||
|
|
||||||
|
config
|
||||||
|
.plugin('html')
|
||||||
|
.tap(args => {
|
||||||
|
args[0].minify = false
|
||||||
|
return args
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user