1
0
mirror of https://github.com/lana-k/sqliteviz.git synced 2026-02-04 15:38:55 +08:00

Compare commits

...

18 Commits

Author SHA1 Message Date
lana-k
4e5adc147f #132 node opacity 2026-01-22 22:25:36 +01:00
lana-k
7edc196a02 change repo structure 2026-01-15 21:53:12 +01:00
lana-k
85b5a200e2 fix tinycolor2 bundle 2025-12-27 21:11:01 +01:00
lana-k
a0ef93921f #131 fix label color 2025-12-26 20:56:08 +01:00
lana-k
859cd2ccfc #129 fix icon 2025-12-25 12:29:28 +01:00
lana-k
a59946c09d remove karma config 2025-12-24 22:14:48 +01:00
lana-k
7b06b3d9c8 uninstall mesa 2025-12-24 22:06:39 +01:00
lana-k
ced933f497 revert firefox base and env 2025-12-24 21:59:23 +01:00
lana-k
cda368f109 xvfb 2025-12-24 21:49:53 +01:00
lana-k
df67466c2f firefox base 2025-12-24 21:41:29 +01:00
lana-k
528549ae5a LIBGL_ALWAYS_SOFTWARE 2025-12-24 21:36:47 +01:00
lana-k
20f4dcc645 fix package names 2025-12-24 17:51:40 +01:00
lana-k
b8353ef0ce install mesa 2025-12-24 17:49:07 +01:00
lana-k
7975f419c9 anoter settings 2025-12-24 17:40:18 +01:00
lana-k
72aa0dd80b another settings 2025-12-24 17:30:05 +01:00
lana-k
e000ee71fc ensure webgl is enabled infirefox 2025-12-24 17:25:25 +01:00
lana-k
b6a12668d3 #43 fix lint errors 2025-12-24 16:17:49 +01:00
lana-k
713f5ac768 #43 graph 0.28.0 2025-12-23 21:41:17 +01:00
79 changed files with 573 additions and 257 deletions

View File

@@ -23,7 +23,10 @@ jobs:
export DEBIAN_FRONTEND=noninteractive
sudo add-apt-repository -y ppa:mozillateam/ppa
sudo apt-get update
sudo apt-get install -y chromium-browser firefox-esr
sudo apt-get install -y \
chromium-browser \
firefox-esr \
xvfb
- name: Update npm
run: npm install -g npm@10
@@ -35,4 +38,4 @@ jobs:
run: npm run lint -- --no-fix
- name: Run karma tests
run: npm run test
run: xvfb-run -a npm test

18
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "sqliteviz",
"version": "0.27.1",
"version": "0.28.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sqliteviz",
"version": "0.27.1",
"version": "0.28.2",
"license": "Apache-2.0",
"dependencies": {
"@sigma/export-image": "^3.0.0",
@@ -32,6 +32,7 @@
"sigma": "^3.0.1",
"sql.js": "file:./lib/sql-js",
"tiny-emitter": "^2.1.0",
"tinycolor2": "^1.4.2",
"veaury": "^2.5.1",
"vue": "^3.5.11",
"vue-final-modal": "^4.5.5",
@@ -13341,6 +13342,11 @@
"react": "^0.14.0 || ^15.0.0"
}
},
"node_modules/react-chart-editor/node_modules/tinycolor2": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
"integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
},
"node_modules/react-color": {
"version": "2.19.3",
"license": "MIT",
@@ -15514,8 +15520,12 @@
"license": "MIT"
},
"node_modules/tinycolor2": {
"version": "1.6.0",
"license": "MIT"
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
"integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==",
"engines": {
"node": "*"
}
},
"node_modules/tinyglobby": {
"version": "0.2.12",

View File

@@ -1,6 +1,6 @@
{
"name": "sqliteviz",
"version": "0.27.1",
"version": "0.28.2",
"license": "Apache-2.0",
"private": true,
"type": "module",
@@ -36,6 +36,7 @@
"sigma": "^3.0.1",
"sql.js": "file:./lib/sql-js",
"tiny-emitter": "^2.1.0",
"tinycolor2": "^1.4.2",
"veaury": "^2.5.1",
"vue": "^3.5.11",
"vue-final-modal": "^4.5.5",

View File

@@ -27,7 +27,7 @@
<script>
import CloseIcon from '@/components/svg/close'
import { version } from '../../../package.json'
import { version } from '../../package.json'
export default {
name: 'AppDiagnosticInfo',

View File

@@ -23,7 +23,7 @@
<script>
import tooltipMixin from '@/tooltipMixin'
import LoadingIndicator from '@/components/LoadingIndicator'
import LoadingIndicator from '@/components/Common/LoadingIndicator'
export default {
name: 'SideBarButton',

View File

@@ -46,7 +46,7 @@
</template>
<script>
import LoadingIndicator from '@/components/LoadingIndicator'
import LoadingIndicator from '@/components/Common/LoadingIndicator'
import CloseIcon from '@/components/svg/close'
export default {

View File

@@ -18,7 +18,7 @@
</template>
<script>
import LoadingIndicator from '@/components/LoadingIndicator'
import LoadingIndicator from '@/components/Common/LoadingIndicator'
export default {
name: 'Logs',

View File

@@ -102,11 +102,11 @@
<script>
import csv from '@/lib/csv'
import CloseIcon from '@/components/svg/close'
import TextField from '@/components/TextField'
import TextField from '@/components/Common/TextField'
import DelimiterSelector from './DelimiterSelector'
import CheckBox from '@/components/CheckBox'
import CheckBox from '@/components/Common/CheckBox'
import SqlTable from '@/components/SqlTable'
import Logs from '@/components/Logs'
import Logs from '@/components/Common/Logs'
import time from '@/lib/utils/time'
import fIo from '@/lib/utils/fileIo'
import events from '@/lib/utils/events'

View File

@@ -113,11 +113,11 @@
</template>
<script>
import Chart from './Chart/index.vue'
import Pivot from './Pivot/index.vue'
import Graph from './Graph/index.vue'
import SideToolBar from '../SideToolBar'
import IconButton from '@/components/IconButton'
import Chart from '@/components/Chart.vue'
import Pivot from '@/components/Pivot'
import Graph from '@/components/Graph/index.vue'
import SideToolBar from '@/components/SideToolBar'
import IconButton from '@/components/Common/IconButton'
import ChartIcon from '@/components/svg/chart'
import PivotIcon from '@/components/svg/pivot'
import GraphIcon from '@/components/svg/graph.vue'
@@ -127,7 +127,7 @@ import ExportToSvgIcon from '@/components/svg/exportToSvg'
import PngIcon from '@/components/svg/png'
import ClipboardIcon from '@/components/svg/clipboard'
import cIo from '@/lib/utils/clipboardIo'
import loadingDialog from '@/components/LoadingDialog.vue'
import loadingDialog from '@/components/Common/LoadingDialog.vue'
import time from '@/lib/utils/time'
import events from '@/lib/utils/events'

View File

@@ -40,7 +40,6 @@
import { applyPureReactInVue } from 'veaury'
import Field from 'react-chart-editor/lib/components/fields/Field'
import NumericInput from 'react-chart-editor/lib/components/widgets/NumericInput'
import Dropdown from 'react-chart-editor/lib/components/widgets/Dropdown'
import Multiselect from 'vue-multiselect'
import 'react-chart-editor/lib/react-chart-editor.css'
@@ -48,7 +47,6 @@ export default {
components: {
Field: applyPureReactInVue(Field),
NumericInput: applyPureReactInVue(NumericInput),
Dropdown: applyPureReactInVue(Dropdown),
Multiselect
},
props: {

View File

@@ -11,7 +11,7 @@
documentation</a
>.
</Field>
<Field label="Object type" ref="objectTypeField">
<Field ref="objectTypeField" label="Object type">
<Dropdown
:options="keysOptions"
:value="settings.structure.objectType"
@@ -172,15 +172,15 @@
<div class="force-atlas-buttons">
<Button
variant="secondary"
@click="resetFA2LayoutSettings"
class="test_fa2_reset"
@click="resetFA2LayoutSettings"
>
Reset
</Button>
<Button
variant="primary"
@click="toggleFA2Layout"
class="test_fa2_toggle"
@click="toggleFA2Layout"
>
<template #node:icon>
<div
@@ -225,6 +225,7 @@ import Button from 'react-chart-editor/lib/components/widgets/Button'
import Field from 'react-chart-editor/lib/components/fields/Field'
import RandomLayoutSettings from '@/components/Graph/RandomLayoutSettings.vue'
import ForceAtlasLayoutSettings from '@/components/Graph/ForceAtlasLayoutSettings.vue'
// eslint-disable-next-line max-len
import AdvancedForceAtlasLayoutSettings from '@/components/Graph/AdvancedForceAtlasLayoutSettings.vue'
import CirclePackLayoutSettings from '@/components/Graph/CirclePackLayoutSettings.vue'
import FA2Layout from 'graphology-layout-forceatlas2/worker'
@@ -318,7 +319,8 @@ export default {
},
color: {
type: 'constant',
value: '#1F77B4'
value: '#1F77B4',
opacity: 100
},
label: {
source: null,
@@ -436,7 +438,9 @@ export default {
this.updateLayout(this.settings.layout.type)
this.renderer = new Sigma(this.graph, this.$refs.graph, {
renderEdgeLabels: true,
allowInvalidContainer: true
allowInvalidContainer: true,
labelColor: { attribute: 'labelColor', color: '#444444' },
edgeLabelColor: { attribute: 'labelColor', color: '#a2b1c6' }
})
if (this.settings.layout.type === 'forceAtlas2') {
this.autoRunFA2Layout()

View File

@@ -57,10 +57,20 @@
</template>
</Field>
<Field label="Opacity" fieldContainerClassName="test_node_opacity">
<NumericInput
:value="modelValue.opacity"
:showSlider="true"
:integerOnly="true"
:max="100"
:min="0"
units="%"
@update="updateSettings('opacity', $event)"
/>
</Field>
<Field
v-if="
modelValue.sourceUsage === 'map_to' || modelValue.type === 'calculated'
"
v-if="modelValue.type === 'map_to' || modelValue.type === 'calculated'"
label="Color as"
fieldContainerClassName="test_node_color_as"
>
@@ -89,6 +99,7 @@
<script>
import { markRaw } from 'vue'
import { applyPureReactInVue } from 'veaury'
import NumericInput from 'react-chart-editor/lib/components/widgets/NumericInput'
import Dropdown from 'react-chart-editor/lib/components/widgets/Dropdown'
import RadioBlocks from 'react-chart-editor/lib/components/widgets/RadioBlocks'
import ColorscalePicker from 'react-chart-editor/lib/components/widgets/ColorscalePicker'
@@ -98,6 +109,7 @@ import 'react-chart-editor/lib/react-chart-editor.css'
export default {
components: {
NumericInput: applyPureReactInVue(NumericInput),
Dropdown: applyPureReactInVue(Dropdown),
RadioBlocks: applyPureReactInVue(RadioBlocks),
Field: applyPureReactInVue(Field),
@@ -134,19 +146,21 @@ export default {
{ label: 'Map to', value: 'map_to' }
]),
defaultColorSettings: {
constant: { value: '#1F77B4' },
constant: { value: '#1F77B4', opacity: 100 },
variable: {
source: null,
sourceUsage: 'map_to',
colorscale: null,
mode: 'categorical',
colorscaleDirection: 'normal'
colorscaleDirection: 'normal',
opacity: 100
},
calculated: {
method: 'degree',
colorscale: null,
mode: 'continious',
colorscaleDirection: 'normal'
colorscaleDirection: 'normal',
opacity: 100
}
}
}

View File

@@ -60,6 +60,21 @@ export default {
resizeObserver: null
}
},
computed: {
dataSourceIsValid() {
return !this.dataSources || dataSourceIsValid(this.dataSources)
}
},
watch: {
async showViewSettings() {
await this.$nextTick()
this.handleResize()
},
dataSources() {
this.$emit('update:exportToPngEnabled', !!this.dataSources)
this.$emit('update:exportToClipboardEnabled', !!this.dataSources)
}
},
created() {
this.$emit('update:exportToSvgEnabled', false)
this.$emit('update:exportToHtmlEnabled', false)
@@ -73,21 +88,6 @@ export default {
beforeUnmount() {
this.resizeObserver.unobserve(this.$refs.graphContainer)
},
watch: {
async showViewSettings() {
await this.$nextTick()
this.handleResize()
},
dataSources() {
this.$emit('update:exportToPngEnabled', !!this.dataSources)
this.$emit('update:exportToClipboardEnabled', !!this.dataSources)
}
},
computed: {
dataSourceIsValid() {
return !this.dataSources || dataSourceIsValid(this.dataSources)
}
},
methods: {
getOptionsForSave() {
return this.$refs.graphEditor.settings

View File

@@ -87,7 +87,7 @@
</template>
<script>
import TextField from '@/components/TextField'
import TextField from '@/components/Common/TextField'
import CloseIcon from '@/components/svg/close'
import storedInquiries from '@/lib/storedInquiries'
import AppDiagnosticInfo from './AppDiagnosticInfo'

View File

@@ -33,7 +33,7 @@ import 'pivottable'
import 'pivottable/dist/pivot.css'
import PivotUi from './PivotUi/index.vue'
import pivotHelper from './pivotHelper'
import Chart from '@/views/MainView/Workspace/Tabs/Tab/DataView/Chart'
import Chart from '@/components/Chart'
import chartHelper from '@/lib/chartHelper'
import events from '@/lib/utils/events'
import plotly from 'plotly.js'

View File

@@ -40,7 +40,7 @@
</template>
<script>
import IconButton from '@/components/IconButton'
import IconButton from '@/components/Common/IconButton'
import ArrowIcon from '@/components/svg/arrow'
import EdgeArrowIcon from '@/components/svg/edgeArrow'

View File

@@ -57,7 +57,7 @@ import 'codemirror/addon/fold/foldgutter.css'
import 'codemirror/addon/fold/brace-fold.js'
import 'codemirror/theme/neo.css'
import cIo from '@/lib/utils/clipboardIo'
import Logs from '@/components/Logs'
import Logs from '@/components/Common/Logs'
export default {
components: {

View File

@@ -135,21 +135,21 @@
</template>
<script>
import Logs from '@/components/Logs'
import SqlTable from '@/components/SqlTable/index.vue'
import LoadingIndicator from '@/components/LoadingIndicator'
import SideToolBar from '../SideToolBar'
import Splitpanes from '@/components/Splitpanes'
import Logs from '@/components/Common/Logs'
import SqlTable from '@/components/SqlTable'
import LoadingIndicator from '@/components/Common/LoadingIndicator'
import SideToolBar from '@/components/SideToolBar'
import Splitpanes from '@/components/Common/Splitpanes'
import ExportToCsvIcon from '@/components/svg/exportToCsv'
import ClipboardIcon from '@/components/svg/clipboard'
import ViewCellValueIcon from '@/components/svg/viewCellValue'
import RowIcon from '@/components/svg/row'
import IconButton from '@/components/IconButton'
import IconButton from '@/components/Common/IconButton'
import csv from '@/lib/csv'
import fIo from '@/lib/utils/fileIo'
import cIo from '@/lib/utils/clipboardIo'
import time from '@/lib/utils/time'
import loadingDialog from '@/components/LoadingDialog'
import loadingDialog from '@/components/Common/LoadingDialog'
import events from '@/lib/utils/events'
import ValueViewer from './ValueViewer'
import Record from './Record/index.vue'

View File

@@ -35,7 +35,7 @@
import fIo from '@/lib/utils/fileIo'
import events from '@/lib/utils/events'
import TableDescription from './TableDescription'
import TextField from '@/components/TextField'
import TextField from '@/components/Common/TextField'
import TreeChevron from '@/components/svg/treeChevron'
import DbUploader from '@/components/DbUploader'
import ExportIcon from '@/components/svg/export'

View File

@@ -37,7 +37,7 @@
</template>
<script>
import IconButton from '@/components/IconButton'
import IconButton from '@/components/Common/IconButton'
import TableIcon from '@/components/svg/table'
import SqlEditorIcon from '@/components/svg/sqlEditor'
import DataViewIcon from '@/components/svg/dataView'

View File

@@ -34,7 +34,7 @@ import 'codemirror/theme/neo.css'
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/display/autorefresh.js'
import SideToolBar from '../SideToolBar'
import IconButton from '@/components/IconButton'
import IconButton from '@/components/Common/IconButton'
import RunIcon from '@/components/svg/run'
export default {

View File

@@ -69,7 +69,7 @@
</template>
<script>
import Pager from './Pager.vue'
import Pager from '@/components/Common/Pager.vue'
export default {
name: 'SqlTable',

View File

@@ -64,10 +64,10 @@
</template>
<script>
import Splitpanes from '@/components/Splitpanes'
import SqlEditor from './SqlEditor'
import DataView from './DataView'
import RunResult from './RunResult'
import Splitpanes from '@/components/Common/Splitpanes'
import SqlEditor from '@/components/SqlEditor'
import DataView from '@/components/DataView'
import RunResult from '@/components/RunResult'
import { nextTick, computed } from 'vue'
import events from '@/lib/utils/events'

View File

@@ -7,27 +7,33 @@
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5 4C5 5.10457 4.10457 6 3 6C1.89543 6 1 5.10457 1 4C1 2.89543 1.89543 2 3 2C4.10457 2 5 2.89543 5 4Z"
d="M5 4C5 5.10457 4.10457 6 3 6C1.89543 6 1 5.10457 1 4C1 2.89543
1.89543 2 3 2C4.10457 2 5 2.89543 5 4Z"
fill="#A2B1C6"
/>
<path
d="M17 7.5C17 8.88071 15.8807 10 14.5 10C13.1193 10 12 8.88071 12 7.5C12 6.11929 13.1193 5 14.5 5C15.8807 5 17 6.11929 17 7.5Z"
d="M17 7.5C17 8.88071 15.8807 10 14.5 10C13.1193 10 12 8.88071 12
7.5C12 6.11929 13.1193 5 14.5 5C15.8807 5 17 6.11929 17 7.5Z"
fill="#A2B1C6"
/>
<path
d="M8 13.5C8 14.8807 6.88071 16 5.5 16C4.11929 16 3 14.8807 3 13.5C3 12.1193 4.11929 11 5.5 11C6.88071 11 8 12.1193 8 13.5Z"
d="M8 13.5C8 14.8807 6.88071 16 5.5 16C4.11929 16 3 14.8807 3 13.5C3
12.1193 4.11929 11 5.5 11C6.88071 11 8 12.1193 8 13.5Z"
fill="#A2B1C6"
/>
<path
d="M2.93128 5.31436L3.90527 5.08778L5.48693 11.8867L4.51294 12.1133L2.93128 5.31436Z"
d="M2.93128 5.31436L3.90527 5.08778L5.48693 11.8867L4.51294
12.1133L2.93128 5.31436Z"
fill="#A2B1C6"
/>
<path
d="M12.9447 7.79159L13.5548 8.58392L7.30516 13.3962L6.69507 12.6038L12.9447 7.79159Z"
d="M12.9447 7.79159L13.5548 8.58392L7.30516 13.3962L6.69507
12.6038L12.9447 7.79159Z"
fill="#A2B1C6"
/>
<path
d="M14.1316 6.51712L3.13166 3.51723L2.86844 4.48202L13.8684 7.48191L14.1316 6.51712Z"
d="M14.1316 6.51712L3.13166 3.51723L2.86844 4.48202L13.8684
7.48191L14.1316 6.51712Z"
fill="#A2B1C6"
/>
</svg>

File diff suppressed because one or more lines are too long

View File

@@ -7,7 +7,8 @@
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M3 4C3 3.44772 3.44772 3 4 3H14C14.5523 3 15 3.44772 15 4V14C15 14.5523 14.5523 15 14 15H4C3.44772 15 3 14.5523 3 14V4Z"
d="M3 4C3 3.44772 3.44772 3 4 3H14C14.5523 3 15 3.44772 15 4V14C15
14.5523 14.5523 15 14 15H4C3.44772 15 3 14.5523 3 14V4Z"
fill="#A2B1C6"
/>
</svg>

View File

@@ -161,9 +161,14 @@ function getUpdateSizeMethod(graph, sizeSettings) {
}
}
function getDirectVariableColorUpdateMethod(source) {
return attributes =>
(attributes.color = tinycolor(attributes.data[source]).toHexString())
function getDirectVariableColorUpdateMethod(source, opacity = 100) {
return attributes => {
const color = tinycolor(attributes.data[source])
const colorOpacity = color.getAlpha()
attributes.color = color
.setAlpha((opacity / 100) * colorOpacity)
.toHex8String()
}
}
function getUpdateNodeColorMethod(graph, colorSettings) {
@@ -175,10 +180,16 @@ function getUpdateNodeColorMethod(graph, colorSettings) {
colorscale,
colorscaleDirection,
mode,
method
method,
opacity
} = colorSettings
if (type === 'constant') {
return attributes => (attributes.color = value)
const color = tinycolor(value)
const colorOpacity = color.getAlpha()
return attributes =>
(attributes.color = color
.setAlpha((opacity / 100) * colorOpacity)
.toHex8String())
} else if (type === 'variable') {
return sourceUsage === 'map_to'
? getColorMethod(
@@ -187,9 +198,10 @@ function getUpdateNodeColorMethod(graph, colorSettings) {
(nodeId, attributes) => attributes.data[source],
colorscale,
colorscaleDirection,
getNodeValueScale
getNodeValueScale,
opacity
)
: getDirectVariableColorUpdateMethod(source)
: getDirectVariableColorUpdateMethod(source, opacity)
} else {
return getColorMethod(
graph,
@@ -197,7 +209,8 @@ function getUpdateNodeColorMethod(graph, colorSettings) {
nodeId => graph[method](nodeId),
colorscale,
colorscaleDirection,
getNodeValueScale
getNodeValueScale,
opacity
)
}
}
@@ -244,8 +257,10 @@ function getColorMethod(
sourceGetter,
selectedColorscale,
colorscaleDirection,
valueScaleGetter
valueScaleGetter,
opacity = 100
) {
const opacityFactor = opacity / 100
const valueScale = valueScaleGetter(graph, sourceGetter)
let colorscale = selectedColorscale || DEFAULT_SCALE
if (colorscaleDirection === 'reversed') {
@@ -261,7 +276,9 @@ function getColorMethod(
)
return (attributes, nodeId) => {
const category = sourceGetter(nodeId, attributes)
attributes.color = colorMap[category]
attributes.color = tinycolor(colorMap[category])
.setAlpha(opacityFactor)
.toHex8String()
}
} else {
const min = valueScale[0]
@@ -274,14 +291,18 @@ function getColorMethod(
const value = sourceGetter(nodeId, attributes)
const normalizedValue = (value - min) / (max - min)
if (isNaN(normalizedValue)) {
attributes.color = '#000000'
attributes.color = tinycolor('#000000')
.setAlpha(opacityFactor)
.toHex8String()
return
}
const exactMatch = normalizedColorscale.find(
([value]) => value === normalizedValue
)
if (exactMatch) {
attributes.color = tinycolor(exactMatch[1]).toHexString()
attributes.color = tinycolor(exactMatch[1])
.setAlpha(opacityFactor)
.toHex8String()
return
}
@@ -305,7 +326,9 @@ function getColorMethod(
r: r0 + interpolationFactor * (r1 - r0),
g: g0 + interpolationFactor * (g1 - g0),
b: b0 + interpolationFactor * (b1 - b0)
}).toHexString()
})
.setAlpha(opacityFactor)
.toHex8String()
}
}
}

View File

@@ -1,12 +1,21 @@
export default {
_migrate(installedVersion, inquiries) {
if (installedVersion === 1) {
inquiries.forEach(inquire => {
inquire.viewType = 'chart'
inquire.viewOptions = inquire.chart
delete inquire.chart
if (installedVersion < 2) {
inquiries.forEach(inquiry => {
inquiry.viewType = 'chart'
inquiry.viewOptions = inquiry.chart
delete inquiry.chart
})
return inquiries
}
if (installedVersion < 3) {
inquiries.forEach(inquiry => {
if (inquiry.viewType === 'graph') {
inquiry.viewOptions.style.nodes.color.opacity = 100
}
})
}
return inquiries
}
}

View File

@@ -7,7 +7,7 @@ const migrate = migration._migrate
const myInquiriesKey = 'myInquiries'
export default {
version: 2,
version: 3,
myInquiriesKey,
getStoredInquiries() {
let myInquiries = JSON.parse(localStorage.getItem(myInquiriesKey))
@@ -21,7 +21,13 @@ export default {
return []
}
return (myInquiries && myInquiries.inquiries) || []
if (myInquiries.version === 2) {
myInquiries = migrate(2, myInquiries.inquiries)
this.updateStorage(myInquiries)
return myInquiries
}
return myInquiries.inquiries || []
},
duplicateInquiry(baseInquiry) {
@@ -82,11 +88,11 @@ export default {
importInquiries() {
return fu.importFile().then(str => {
const inquires = this.deserialiseInquiries(str)
const inquiries = this.deserialiseInquiries(str)
events.send('inquiry.import', inquires.length)
events.send('inquiry.import', inquiries.length)
return inquires
return inquiries
})
},
export(inquiryList, fileName) {

View File

@@ -1,6 +1,6 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import Workspace from '@/views/MainView/Workspace'
import Inquiries from '@/views/MainView/Inquiries'
import Workspace from '@/views/Workspace'
import Inquiries from '@/views/Inquiries'
import Welcome from '@/views/Welcome'
import MainView from '@/views/MainView'
import LoadView from '@/views/LoadView'

View File

@@ -184,14 +184,14 @@
</template>
<script>
import RenameIcon from './svg/rename'
import CopyIcon from './svg/copy'
import RenameIcon from '@/components/svg/rename'
import CopyIcon from '@/components/svg/copy'
import ExportIcon from '@/components/svg/export'
import DeleteIcon from './svg/delete'
import DeleteIcon from '@/components/svg/delete'
import CloseIcon from '@/components/svg/close'
import TextField from '@/components/TextField'
import CheckBox from '@/components/CheckBox'
import LoadingIndicator from '@/components/LoadingIndicator'
import TextField from '@/components/Common/TextField'
import CheckBox from '@/components/Common/CheckBox'
import LoadingIndicator from '@/components/Common/LoadingIndicator'
import tooltipMixin from '@/tooltipMixin'
import storedInquiries from '@/lib/storedInquiries'
import eventBus from '@/lib/eventBus'

View File

@@ -15,7 +15,7 @@
<script>
import fu from '@/lib/utils/fileIo'
import database from '@/lib/database'
import Logs from '@/components/Logs'
import Logs from '@/components/Common/Logs'
import events from '@/lib/utils/events'
export default {

View File

@@ -10,7 +10,7 @@
</template>
<script>
import MainMenu from './MainMenu'
import MainMenu from '@/components/MainMenu'
import '@/assets/styles/scrollbars.css'
export default {

View File

@@ -17,9 +17,9 @@
</template>
<script>
import Splitpanes from '@/components/Splitpanes'
import Schema from './Schema'
import Tabs from './Tabs'
import Splitpanes from '@/components/Common/Splitpanes'
import Schema from '@/components/Schema'
import Tabs from '@/components/Tabs'
import events from '@/lib/utils/events'
export default {

View File

@@ -1,7 +1,7 @@
import { expect } from 'chai'
import sinon from 'sinon'
import { mount, flushPromises } from '@vue/test-utils'
import Chart from '@/views/MainView/Workspace/Tabs/Tab/DataView/Chart/index.vue'
import Chart from '@/components/Chart.vue'
import chartHelper from '@/lib/chartHelper'
import * as dereference from 'react-chart-editor/lib/lib/dereference'
import fIo from '@/lib/utils/fileIo'
@@ -128,6 +128,8 @@ describe('Chart.vue', () => {
expect(plot.scrollWidth).not.to.equal(initialPlotWidth)
expect(plot.scrollHeight).not.to.equal(initialPlotHeight)
container.style.width = 'unset'
container.style.height = 'unset'
wrapper.unmount()
})

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import CheckBox from '@/components/CheckBox'
import CheckBox from '@/components/Common/CheckBox'
describe('CheckBox', () => {
it('unchecked by default', () => {

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import LoadingIndicator from '@/components/LoadingIndicator'
import LoadingIndicator from '@/components/Common/LoadingIndicator'
describe('LoadingIndicator.vue', () => {
it('Calculates animation class', async () => {

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import Logs from '@/components/Logs'
import Logs from '@/components/Common/Logs'
import { nextTick } from 'vue'
let place

View File

@@ -1,7 +1,7 @@
import { expect } from 'chai'
import sinon from 'sinon'
import { mount } from '@vue/test-utils'
import Pager from '@/components/SqlTable/Pager'
import Pager from '@/components/Common/Pager'
describe('Pager.vue', () => {
afterEach(() => {

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import Splitpanes from '@/components/Splitpanes'
import Splitpanes from '@/components/Common/Splitpanes'
import { nextTick } from 'vue'
describe('Splitpanes.vue', () => {

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import sinon from 'sinon'
import splitter from '@/components/Splitpanes/splitter'
import splitter from '@/components/Common/Splitpanes/splitter'
describe('splitter.js', () => {
afterEach(() => {

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { mount } from '@vue/test-utils'
import DataView from '@/views/MainView/Workspace/Tabs/Tab/DataView/index.vue'
import DataView from '@/components/DataView.vue'
import sinon from 'sinon'
import { nextTick } from 'vue'
import cIo from '@/lib/utils/clipboardIo'

View File

@@ -1,7 +1,7 @@
import { expect } from 'chai'
import sinon from 'sinon'
import { mount, flushPromises } from '@vue/test-utils'
import Graph from '@/views/MainView/Workspace/Tabs/Tab/DataView/Graph/index.vue'
import Graph from '@/components/Graph/index.vue'
function getPixels(canvas) {
const context = canvas.getContext('webgl2')

View File

@@ -24,7 +24,8 @@ const defaultInitOptions = {
},
color: {
type: 'constant',
value: '#1F77B4'
value: '#1F77B4',
opacity: 100
},
label: {
source: null,
@@ -404,7 +405,7 @@ describe('GraphEditor', () => {
doc: [
'{"type": 0, "node_id": 1, "color": "#ff0000", "points": 5}',
'{"type": 0, "node_id": 2, "color": "#abcdff", "points": 15}',
'{"type": 0, "node_id": 3, "color": "#123456", "points": 10}',
'{"type": 0, "node_id": 3, "color": "#12345680", "points": 10}',
'{"type": 1, "source": 2, "target": 3}'
]
},
@@ -440,11 +441,11 @@ describe('GraphEditor', () => {
// Set constant color
await wrapper
.findAllComponents({ name: 'ColorPicker' })[1]
.vm.$emit('colorChange', '#ff00ff')
.vm.$emit('colorChange', '#ff00ff80')
expect(graph.export().nodes[0].attributes.color).to.equal('#ff00ff')
expect(graph.export().nodes[1].attributes.color).to.equal('#ff00ff')
expect(graph.export().nodes[2].attributes.color).to.equal('#ff00ff')
expect(graph.export().nodes[0].attributes.color).to.equal('#ff00ff80')
expect(graph.export().nodes[1].attributes.color).to.equal('#ff00ff80')
expect(graph.export().nodes[2].attributes.color).to.equal('#ff00ff80')
// Switch to Variable
const variable = wrapper.findAll('.test_node_color .radio-block__option')[1]
@@ -459,27 +460,27 @@ describe('GraphEditor', () => {
await wrapper.findAll('.Select__menu .Select__option')[2].trigger('click')
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6e')
expect(graph.export().nodes[1].attributes.color).to.equal('#bdea75')
expect(graph.export().nodes[2].attributes.color).to.equal('#86d780')
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6eff')
expect(graph.export().nodes[1].attributes.color).to.equal('#bdea75ff')
expect(graph.export().nodes[2].attributes.color).to.equal('#86d780ff')
// Select Direct mapping
await wrapper
.find('.test_node_color_mapping_mode .radio-block__option')
.trigger('click')
expect(graph.export().nodes[0].attributes.color).to.equal('#ff0000')
expect(graph.export().nodes[1].attributes.color).to.equal('#abcdff')
expect(graph.export().nodes[2].attributes.color).to.equal('#123456')
expect(graph.export().nodes[0].attributes.color).to.equal('#ff0000ff')
expect(graph.export().nodes[1].attributes.color).to.equal('#abcdffff')
expect(graph.export().nodes[2].attributes.color).to.equal('#12345680')
// Switch to Calculated
const calculated = wrapper.findAll(
'.test_node_color .radio-block__option'
)[2]
await calculated.trigger('click')
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6e')
expect(graph.export().nodes[1].attributes.color).to.equal('#2a4858')
expect(graph.export().nodes[2].attributes.color).to.equal('#2a4858')
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6eff')
expect(graph.export().nodes[1].attributes.color).to.equal('#2a4858ff')
expect(graph.export().nodes[2].attributes.color).to.equal('#2a4858ff')
await nextTick()
// Choose in-degree
@@ -491,45 +492,68 @@ describe('GraphEditor', () => {
await wrapper.findAll('.Select__menu .Select__option')[1].trigger('click')
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6e')
expect(graph.export().nodes[1].attributes.color).to.equal('#fafa6e')
expect(graph.export().nodes[2].attributes.color).to.equal('#2a4858')
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6eff')
expect(graph.export().nodes[1].attributes.color).to.equal('#fafa6eff')
expect(graph.export().nodes[2].attributes.color).to.equal('#2a4858ff')
await nextTick()
// Set another opacity for calculated color
let opacityInput = wrapper.find(
'.test_node_opacity input.numeric-input__number'
)
await opacityInput.setValue(50)
opacityInput.wrapperElement.dispatchEvent(
new Event('blur', { bubbles: true })
)
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6e80')
expect(graph.export().nodes[1].attributes.color).to.equal('#fafa6e80')
expect(graph.export().nodes[2].attributes.color).to.equal('#2a485880')
await nextTick()
// Set Color as to Categorical
await wrapper
.findAll('.test_node_color_as .radio-block__option')[1]
.trigger('click')
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6e')
expect(graph.export().nodes[1].attributes.color).to.equal('#fafa6e')
expect(graph.export().nodes[2].attributes.color).to.equal('#bdea75')
expect(graph.export().nodes[0].attributes.color).to.equal('#fafa6e80')
expect(graph.export().nodes[1].attributes.color).to.equal('#fafa6e80')
expect(graph.export().nodes[2].attributes.color).to.equal('#bdea7580')
await nextTick()
// Change colorscale direction
await wrapper
.findAll('.test_node_color_colorscale_direction .radio-block__option')[1]
.trigger('click')
expect(graph.export().nodes[0].attributes.color).to.equal('#2a4858')
expect(graph.export().nodes[1].attributes.color).to.equal('#2a4858')
expect(graph.export().nodes[2].attributes.color).to.equal('#1f5f70')
expect(graph.export().nodes[0].attributes.color).to.equal('#2a485880')
expect(graph.export().nodes[1].attributes.color).to.equal('#2a485880')
expect(graph.export().nodes[2].attributes.color).to.equal('#1f5f7080')
await nextTick()
// Switch to Variable
await variable.trigger('click')
// The latest settings from variable mode are applied
expect(graph.export().nodes[0].attributes.color).to.equal('#ff0000')
expect(graph.export().nodes[1].attributes.color).to.equal('#abcdff')
expect(graph.export().nodes[2].attributes.color).to.equal('#123456')
expect(graph.export().nodes[0].attributes.color).to.equal('#ff0000ff')
expect(graph.export().nodes[1].attributes.color).to.equal('#abcdffff')
expect(graph.export().nodes[2].attributes.color).to.equal('#12345680')
// Switch to Constant
const constant = wrapper.findAll('.test_node_color .radio-block__option')[0]
await constant.trigger('click')
// The latest settings from constant mode are applied
expect(graph.export().nodes[0].attributes.color).to.equal('#ff00ff')
expect(graph.export().nodes[1].attributes.color).to.equal('#ff00ff')
expect(graph.export().nodes[2].attributes.color).to.equal('#ff00ff')
expect(graph.export().nodes[0].attributes.color).to.equal('#ff00ff80')
expect(graph.export().nodes[1].attributes.color).to.equal('#ff00ff80')
expect(graph.export().nodes[2].attributes.color).to.equal('#ff00ff80')
// Set another opacity for constant color
await opacityInput.setValue(50)
opacityInput.wrapperElement.dispatchEvent(
new Event('blur', { bubbles: true })
)
expect(graph.export().nodes[0].attributes.color).to.equal('#ff00ff40')
expect(graph.export().nodes[1].attributes.color).to.equal('#ff00ff40')
expect(graph.export().nodes[2].attributes.color).to.equal('#ff00ff40')
await nextTick()
wrapper.unmount()
})
@@ -840,26 +864,26 @@ describe('GraphEditor', () => {
)
await wrapper.findAll('.Select__menu .Select__option')[5].trigger('click')
expect(graph.export().edges[0].attributes.color).to.equal('#fafa6e')
expect(graph.export().edges[1].attributes.color).to.equal('#bdea75')
expect(graph.export().edges[2].attributes.color).to.equal('#86d780')
expect(graph.export().edges[0].attributes.color).to.equal('#fafa6eff')
expect(graph.export().edges[1].attributes.color).to.equal('#bdea75ff')
expect(graph.export().edges[2].attributes.color).to.equal('#86d780ff')
// Set Color as to Continious
await wrapper
.findAll('.test_edge_color_as .radio-block__option')[0]
.trigger('click')
expect(graph.export().edges[0].attributes.color).to.equal('#fafa6e')
expect(graph.export().edges[1].attributes.color).to.equal('#39b48d')
expect(graph.export().edges[2].attributes.color).to.equal('#2a4858')
expect(graph.export().edges[0].attributes.color).to.equal('#fafa6eff')
expect(graph.export().edges[1].attributes.color).to.equal('#39b48dff')
expect(graph.export().edges[2].attributes.color).to.equal('#2a4858ff')
await nextTick()
// Change colorscale direction
await wrapper
.findAll('.test_edge_color_colorscale_direction .radio-block__option')[1]
.trigger('click')
expect(graph.export().edges[0].attributes.color).to.equal('#2a4858')
expect(graph.export().edges[1].attributes.color).to.equal('#139f8e')
expect(graph.export().edges[2].attributes.color).to.equal('#fafa6e')
expect(graph.export().edges[0].attributes.color).to.equal('#2a4858ff')
expect(graph.export().edges[1].attributes.color).to.equal('#139f8eff')
expect(graph.export().edges[2].attributes.color).to.equal('#fafa6eff')
await nextTick()
// Clear color source
@@ -883,9 +907,9 @@ describe('GraphEditor', () => {
.find('.test_edge_color_mapping_mode .radio-block__option')
.trigger('click')
expect(graph.export().edges[0].attributes.color).to.equal('#ff0000')
expect(graph.export().edges[1].attributes.color).to.equal('#abcdff')
expect(graph.export().edges[2].attributes.color).to.equal('#123456')
expect(graph.export().edges[0].attributes.color).to.equal('#ff0000ff')
expect(graph.export().edges[1].attributes.color).to.equal('#abcdffff')
expect(graph.export().edges[2].attributes.color).to.equal('#123456ff')
// Switch to Constant
const constant = wrapper.findAll('.test_edge_color .radio-block__option')[0]

View File

@@ -2,7 +2,7 @@ import { expect } from 'chai'
import sinon from 'sinon'
import { mount, shallowMount } from '@vue/test-utils'
import { createStore } from 'vuex'
import MainMenu from '@/views/MainView/MainMenu'
import MainMenu from '@/components/MainMenu'
import storedInquiries from '@/lib/storedInquiries'
import { nextTick } from 'vue'
import eventBus from '@/lib/eventBus'

View File

@@ -1,11 +1,11 @@
import { expect } from 'chai'
import { mount, flushPromises } from '@vue/test-utils'
import Pivot from '@/views/MainView/Workspace/Tabs/Tab/DataView/Pivot/index.vue'
import Pivot from '@/components/Pivot/index.vue'
import chartHelper from '@/lib/chartHelper'
import fIo from '@/lib/utils/fileIo'
import $ from 'jquery'
import sinon from 'sinon'
import pivotHelper from '@/views/MainView/Workspace/Tabs/Tab/DataView/Pivot/pivotHelper'
import pivotHelper from '@/components/Pivot/pivotHelper'
describe('Pivot.vue', () => {
let container

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import PivotSortBtn from '@/views/MainView/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/PivotSortBtn'
import PivotSortBtn from '@/components/Pivot/PivotUi/PivotSortBtn'
describe('PivotSortBtn.vue', () => {
it('switches order', async () => {

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { mount } from '@vue/test-utils'
import PivotUi from '@/views/MainView/Workspace/Tabs/Tab/DataView/Pivot/PivotUi'
import PivotUi from '@/components/Pivot/PivotUi'
describe('PivotUi.vue', () => {
it('returns value when settings changed', async () => {

View File

@@ -3,7 +3,7 @@ import {
_getDataSources,
getPivotCanvas,
getPivotHtml
} from '@/views/MainView/Workspace/Tabs/Tab/DataView/Pivot/pivotHelper'
} from '@/components/Pivot/pivotHelper'
describe('pivotHelper.js', () => {
it('_getDataSources returns data sources', () => {

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { mount } from '@vue/test-utils'
import Record from '@/views/MainView/Workspace/Tabs/Tab/RunResult/Record'
import Record from '@/components/RunResult/Record'
describe('Record.vue', () => {
it('shows record with selected cell', async () => {

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { mount } from '@vue/test-utils'
import RunResult from '@/views/MainView/Workspace/Tabs/Tab/RunResult'
import RunResult from '@/components/RunResult'
import csv from '@/lib/csv'
import sinon from 'sinon'
import { nextTick } from 'vue'

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { mount } from '@vue/test-utils'
import ValueViewer from '@/views/MainView/Workspace/Tabs/Tab/RunResult/ValueViewer.vue'
import ValueViewer from '@/components/RunResult/ValueViewer.vue'
import sinon from 'sinon'
describe('ValueViewer.vue', () => {

View File

@@ -4,8 +4,8 @@ import { mount } from '@vue/test-utils'
import { createStore } from 'vuex'
import actions from '@/store/actions'
import mutations from '@/store/mutations'
import Schema from '@/views/MainView/Workspace/Schema'
import TableDescription from '@/views/MainView/Workspace/Schema/TableDescription'
import Schema from '@/components/Schema'
import TableDescription from '@/components/Schema/TableDescription'
import database from '@/lib/database'
import fIo from '@/lib/utils/fileIo'
import csv from '@/lib/csv'

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import TableDescription from '@/views/MainView/Workspace/Schema/TableDescription'
import TableDescription from '@/components/Schema/TableDescription'
describe('TableDescription.vue', () => {
it('Initially the columns are hidden and table name is rendered', () => {

View File

@@ -1,7 +1,7 @@
import { expect } from 'chai'
import { mount } from '@vue/test-utils'
import { createStore } from 'vuex'
import SqlEditor from '@/views/MainView/Workspace/Tabs/Tab/SqlEditor'
import SqlEditor from '@/components/SqlEditor'
import { nextTick } from 'vue'
describe('SqlEditor.vue', () => {

View File

@@ -1,9 +1,7 @@
import { expect } from 'chai'
import sinon from 'sinon'
import state from '@/store/state'
import showHint, {
getHints
} from '@/views/MainView/Workspace/Tabs/Tab/SqlEditor/hint'
import showHint, { getHints } from '@/components/SqlEditor/hint'
import CM from 'codemirror'
describe('hint.js', () => {

View File

@@ -3,7 +3,7 @@ import sinon from 'sinon'
import { mount } from '@vue/test-utils'
import mutations from '@/store/mutations'
import { createStore } from 'vuex'
import Tab from '@/views/MainView/Workspace/Tabs/Tab'
import Tab from '@/components/Tab'
import { nextTick } from 'vue'
let place

View File

@@ -3,7 +3,7 @@ import sinon from 'sinon'
import { shallowMount, mount } from '@vue/test-utils'
import mutations from '@/store/mutations'
import { createStore } from 'vuex'
import Tabs from '@/views/MainView/Workspace/Tabs'
import Tabs from '@/components/Tabs'
import eventBus from '@/lib/eventBus'
import { nextTick } from 'vue'
import cIo from '@/lib/utils/clipboardIo'

View File

@@ -533,7 +533,8 @@ describe('graphHelper.js', () => {
graphHelper.updateNodes(graph, {
color: {
type: 'constant',
value: '#a1b8c3'
value: '#a1b8c380',
opacity: 50
}
})
expect(graph.export().nodes).to.eql([
@@ -541,14 +542,14 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1 },
color: '#a1b8c3'
color: '#a1b8c340'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2 },
color: '#a1b8c3'
color: '#a1b8c340'
}
}
])
@@ -592,7 +593,7 @@ describe('graphHelper.js', () => {
doc: [
'{"type": 0, "node_id": 1, "color": "red", "points": 5}',
'{"type": 0, "node_id": 2, "color": "#abcdff", "points": 15}',
'{"type": 0, "node_id": 3, "color": "#123456", "points": 10}'
'{"type": 0, "node_id": 3, "color": "#12345680", "points": 10}'
]
}
const graph = new Graph()
@@ -609,7 +610,8 @@ describe('graphHelper.js', () => {
color: {
type: 'variable',
source: 'color',
sourceUsage: 'direct'
sourceUsage: 'direct',
opacity: 50
}
})
expect(graph.export().nodes).to.eql([
@@ -617,21 +619,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1, color: 'red', points: 5 },
color: '#ff0000'
color: '#ff000080'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
color: '#abcdff'
color: '#abcdff80'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3, color: '#123456', points: 10 },
color: '#123456'
data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
color: '#12345640'
}
}
])
@@ -644,7 +646,8 @@ describe('graphHelper.js', () => {
sourceUsage: 'map_to',
colorscale,
mode: 'categorical',
colorscaleDirection: 'normal'
colorscaleDirection: 'normal',
opacity: 50
}
})
expect(graph.export().nodes).to.eql([
@@ -652,21 +655,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1, color: 'red', points: 5 },
color: '#aaaaff'
color: '#aaaaff80'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
color: '#6666ff'
color: '#6666ff80'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3, color: '#123456', points: 10 },
color: '#8888ff'
data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
color: '#8888ff80'
}
}
])
@@ -678,7 +681,8 @@ describe('graphHelper.js', () => {
sourceUsage: 'map_to',
colorscale,
mode: 'categorical',
colorscaleDirection: 'reversed'
colorscaleDirection: 'reversed',
opacity: 50
}
})
@@ -687,21 +691,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1, color: 'red', points: 5 },
color: '#0000ff'
color: '#0000ff80'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
color: '#6666ff'
color: '#6666ff80'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3, color: '#123456', points: 10 },
color: '#4444ff'
data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
color: '#4444ff80'
}
}
])
@@ -713,7 +717,8 @@ describe('graphHelper.js', () => {
sourceUsage: 'map_to',
colorscale,
mode: 'continious',
colorscaleDirection: 'normal'
colorscaleDirection: 'normal',
opacity: 50
}
})
expect(graph.export().nodes).to.eql([
@@ -721,21 +726,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1, color: 'red', points: 5 },
color: '#aaaaff'
color: '#aaaaff80'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
color: '#0000ff'
color: '#0000ff80'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3, color: '#123456', points: 10 },
color: '#6666ff'
data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
color: '#6666ff80'
}
}
])
@@ -747,7 +752,8 @@ describe('graphHelper.js', () => {
sourceUsage: 'map_to',
colorscale,
mode: 'continious',
colorscaleDirection: 'reversed'
colorscaleDirection: 'reversed',
opacity: 50
}
})
@@ -756,21 +762,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1, color: 'red', points: 5 },
color: '#0000ff'
color: '#0000ff80'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
color: '#aaaaff'
color: '#aaaaff80'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3, color: '#123456', points: 10 },
color: '#6666ff'
data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
color: '#6666ff80'
}
}
])
@@ -782,7 +788,8 @@ describe('graphHelper.js', () => {
sourceUsage: 'map_to',
colorscale: ['#aaaaff', '#0000ff'],
mode: 'continious',
colorscaleDirection: 'normal'
colorscaleDirection: 'normal',
opacity: 50
}
})
@@ -791,21 +798,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1, color: 'red', points: 5 },
color: '#aaaaff'
color: '#aaaaff80'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2, color: '#abcdff', points: 15 },
color: '#0000ff'
color: '#0000ff80'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3, color: '#123456', points: 10 },
color: '#5555ff'
data: { type: 0, node_id: 3, color: '#12345680', points: 10 },
color: '#5555ff80'
}
}
])
@@ -834,7 +841,8 @@ describe('graphHelper.js', () => {
source: 'country',
sourceUsage: 'map_to',
mode: 'continious',
colorscaleDirection: 'normal'
colorscaleDirection: 'normal',
opacity: 100
}
})
expect(graph.export().nodes).to.eql([
@@ -842,14 +850,14 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1, country: 'NL' },
color: '#000000'
color: '#000000ff'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2, country: 'GB' },
color: '#000000'
color: '#000000ff'
}
}
])
@@ -887,15 +895,15 @@ describe('graphHelper.js', () => {
expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
{
data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
color: '#ff0000'
color: '#ff0000ff'
},
{
data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
color: '#ff0000'
color: '#ff0000ff'
},
{
data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
color: '#ff0000'
color: '#ff0000ff'
}
])
@@ -914,15 +922,15 @@ describe('graphHelper.js', () => {
expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
{
data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
color: '#aaaaff'
color: '#aaaaffff'
},
{
data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
color: '#6666ff'
color: '#6666ffff'
},
{
data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
color: '#8888ff'
color: '#8888ffff'
}
])
@@ -940,15 +948,15 @@ describe('graphHelper.js', () => {
expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
{
data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
color: '#0000ff'
color: '#0000ffff'
},
{
data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
color: '#6666ff'
color: '#6666ffff'
},
{
data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
color: '#4444ff'
color: '#4444ffff'
}
])
@@ -966,15 +974,15 @@ describe('graphHelper.js', () => {
expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
{
data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
color: '#aaaaff'
color: '#aaaaffff'
},
{
data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
color: '#0000ff'
color: '#0000ffff'
},
{
data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
color: '#6666ff'
color: '#6666ffff'
}
])
@@ -992,15 +1000,15 @@ describe('graphHelper.js', () => {
expect(graph.export().edges.map(edge => edge.attributes)).to.eql([
{
data: { type: 1, source: 1, target: 2, color: 'red', weight: 5 },
color: '#0000ff'
color: '#0000ffff'
},
{
data: { type: 1, source: 1, target: 3, color: 'red', weight: 15 },
color: '#aaaaff'
color: '#aaaaffff'
},
{
data: { type: 1, source: 2, target: 3, color: 'red', weight: 10 },
color: '#6666ff'
color: '#6666ffff'
}
])
})
@@ -1035,7 +1043,8 @@ describe('graphHelper.js', () => {
method: 'degree',
colorscale,
mode: 'categorical',
colorscaleDirection: 'normal'
colorscaleDirection: 'normal',
opacity: 50
}
})
expect(graph.export().nodes).to.eql([
@@ -1043,21 +1052,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1 },
color: '#aaaaff'
color: '#aaaaff80'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2 },
color: '#8888ff'
color: '#8888ff80'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3 },
color: '#8888ff'
color: '#8888ff80'
}
}
])
@@ -1068,7 +1077,8 @@ describe('graphHelper.js', () => {
method: 'outDegree',
colorscale,
mode: 'categorical',
colorscaleDirection: 'reversed'
colorscaleDirection: 'reversed',
opacity: 50
}
})
@@ -1077,21 +1087,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1 },
color: '#0000ff'
color: '#0000ff80'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2 },
color: '#4444ff'
color: '#4444ff80'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3 },
color: '#0000ff'
color: '#0000ff80'
}
}
])
@@ -1102,7 +1112,8 @@ describe('graphHelper.js', () => {
method: 'degree',
colorscale,
mode: 'continious',
colorscaleDirection: 'normal'
colorscaleDirection: 'normal',
opacity: 100
}
})
expect(graph.export().nodes).to.eql([
@@ -1110,21 +1121,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1 },
color: '#aaaaff'
color: '#aaaaffff'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2 },
color: '#0000ff'
color: '#0000ffff'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3 },
color: '#0000ff'
color: '#0000ffff'
}
}
])
@@ -1135,7 +1146,8 @@ describe('graphHelper.js', () => {
method: 'degree',
colorscale,
mode: 'continious',
colorscaleDirection: 'reversed'
colorscaleDirection: 'reversed',
opacity: 100
}
})
@@ -1144,21 +1156,21 @@ describe('graphHelper.js', () => {
key: '1',
attributes: {
data: { type: 0, node_id: 1 },
color: '#0000ff'
color: '#0000ffff'
}
},
{
key: '2',
attributes: {
data: { type: 0, node_id: 2 },
color: '#aaaaff'
color: '#aaaaffff'
}
},
{
key: '3',
attributes: {
data: { type: 0, node_id: 3 },
color: '#aaaaff'
color: '#aaaaffff'
}
}
])

View File

@@ -18,7 +18,7 @@ describe('storedInquiries.js', () => {
expect(inquiries).to.eql([])
})
it('getStoredInquiries migrate and returns inquiries of v1', () => {
it('getStoredInquiries migrates and returns inquiries of v1', () => {
localStorage.setItem(
'myQueries',
JSON.stringify([
@@ -55,6 +55,113 @@ describe('storedInquiries.js', () => {
])
})
it('getStoredInquiries migrates and returns inquiries of v2', () => {
localStorage.setItem(
'myInquiries',
JSON.stringify({
version: 2,
inquiries: [
{
id: 'Xh1Hc9v7P3mRPZVM59QiC',
query: 'SELECT * from doc',
viewType: 'graph',
viewOptions: {
structure: {
nodeId: 'node_id',
objectType: 'object_type',
edgeSource: 'source',
edgeTarget: 'target'
},
style: {
backgroundColor: 'white',
nodes: {
size: { type: 'constant', value: 10 },
color: {
type: 'calculated',
method: 'degree',
colorscale: null,
mode: 'continious',
colorscaleDirection: 'reversed'
},
label: { source: 'label', color: '#444444' }
},
edges: {
showDirection: true,
size: { type: 'constant', value: 2 },
color: { type: 'constant', value: '#a2b1c6' },
label: { source: null, color: '#a2b1c6' }
}
},
layout: { type: 'circular', options: null }
},
name: 'student graph',
updatedAt: '2026-01-19T21:49:40.708Z',
createdAt: '2026-01-19T21:46:13.899Z'
},
{
id: 'Yh1Hc9v7P3mRPZVM59QiD',
query: 'SELECT * from test',
viewType: 'chart',
viewOptions: 'some chart view options',
name: 'student chart',
updatedAt: '2026-01-19T21:49:40.708Z',
createdAt: '2026-01-19T21:46:13.899Z'
}
]
})
)
const inquiries = storedInquiries.getStoredInquiries()
expect(inquiries).to.eql([
{
id: 'Xh1Hc9v7P3mRPZVM59QiC',
query: 'SELECT * from doc',
viewType: 'graph',
viewOptions: {
structure: {
nodeId: 'node_id',
objectType: 'object_type',
edgeSource: 'source',
edgeTarget: 'target'
},
style: {
backgroundColor: 'white',
nodes: {
size: { type: 'constant', value: 10 },
color: {
type: 'calculated',
method: 'degree',
colorscale: null,
mode: 'continious',
colorscaleDirection: 'reversed',
opacity: 100
},
label: { source: 'label', color: '#444444' }
},
edges: {
showDirection: true,
size: { type: 'constant', value: 2 },
color: { type: 'constant', value: '#a2b1c6' },
label: { source: null, color: '#a2b1c6' }
}
},
layout: { type: 'circular', options: null }
},
name: 'student graph',
updatedAt: '2026-01-19T21:49:40.708Z',
createdAt: '2026-01-19T21:46:13.899Z'
},
{
id: 'Yh1Hc9v7P3mRPZVM59QiD',
query: 'SELECT * from test',
viewType: 'chart',
viewOptions: 'some chart view options',
name: 'student chart',
updatedAt: '2026-01-19T21:49:40.708Z',
createdAt: '2026-01-19T21:46:13.899Z'
}
])
})
it('updateStorage and getStoredInquiries', () => {
const data = [{ id: 1 }, { id: 2 }]
storedInquiries.updateStorage(data)
@@ -136,7 +243,7 @@ describe('storedInquiries.js', () => {
const str = storedInquiries.serialiseInquiries(inquiryList)
const parsedJson = JSON.parse(str)
expect(parsedJson.version).to.equal(2)
expect(parsedJson.version).to.equal(3)
expect(parsedJson.inquiries).to.have.lengthOf(2)
expect(parsedJson.inquiries[1]).to.eql(inquiryList[1])
expect(parsedJson.inquiries[0]).to.eql({
@@ -215,7 +322,7 @@ describe('storedInquiries.js', () => {
it('deserialiseInquiries generates new id to avoid duplication', () => {
storedInquiries.updateStorage([{ id: 1 }])
const str = `{
"version": 2,
"version": 3,
"inquiries": [
{
"id": 1,
@@ -275,7 +382,7 @@ describe('storedInquiries.js', () => {
it('importInquiries', async () => {
const str = `{
"version": 2,
"version": 3,
"inquiries": [{
"id": 1,
"name": "foo",
@@ -327,7 +434,7 @@ describe('storedInquiries.js', () => {
it('readPredefinedInquiries', async () => {
const str = `{
"version": 2,
"version": 3,
"inquiries": [
{
"id": 1,

View File

@@ -2,7 +2,7 @@ import { expect } from 'chai'
import sinon from 'sinon'
import { mount, shallowMount } from '@vue/test-utils'
import { createStore } from 'vuex'
import Inquiries from '@/views/MainView/Inquiries'
import Inquiries from '@/views/Inquiries'
import storedInquiries from '@/lib/storedInquiries'
import mutations from '@/store/mutations'
import actions from '@/store/actions'

View File

@@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils'
import actions from '@/store/actions'
import mutations from '@/store/mutations'
import { createStore } from 'vuex'
import Workspace from '@/views/MainView/Workspace'
import Workspace from '@/views/Workspace'
describe('Workspace.vue', () => {
it('Creates a tab with example if schema is empty', () => {