Skip to content

Commit d4233e5

Browse files
committed
import and waypoints actions
1 parent b3c5182 commit d4233e5

13 files changed

+524
-13
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ An Open Source alternative to dbdiagram.io, aiming to have the same basic featur
2828
+ 14. Shifts of header color bug repaired
2929
+ 15. Added touch screen support (hover table header = hold touch) (without gestures)
3030
+ 16. Added PNG resolution change in export form (default is better quality)
31+
+ 17. Added import json files
32+
+ 18. Added actions for refs control points (add, reset, delete)
33+
3134

3235
## Architecture - Solution
3336

web/src/components/DbmlGraph.vue

+32
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import VDbChart from './VDbChart/VDbChart'
6262
import { useChartStore } from '../store/chart'
6363
import VDbStructure from './VDbStructure'
64+
import { store } from 'quasar/wrappers'
6465
6566
const props = defineProps({
6667
schema: {
@@ -84,6 +85,7 @@
8485
console.log
8586
chart.hideTooltip();
8687
if ((Date.now() - chart.panel.datetime) > 500) chart.hidePanel();
88+
if ((Date.now() - chart.panel.datetime) > 500) chart.hideRefPanel();
8789
}
8890
8991
const scale = computed({
@@ -202,7 +204,37 @@
202204
return cross_vector;
203205
}
204206
207+
function getBounds(bounds, objects,isRef = false){
208+
for (let item in objects){
209+
if (objects[item].x < bounds.l) {
210+
bounds.l = objects[item].x
211+
}
212+
if (objects[item].y < bounds.t) {
213+
bounds.t = objects[item].y
214+
}
215+
if (!isRef){
216+
if (objects[item].x+objects[item].width > bounds.r) {
217+
bounds.r = objects[item].x+objects[item].width
218+
}
219+
if (objects[item].y+objects[item].height > bounds.b) {
220+
bounds.b = objects[item].y+objects[item].height
221+
}
222+
}
223+
224+
}
225+
return bounds;
226+
}
227+
205228
const applyScaleToFit = () => {
229+
let bounds = getBounds({l:0, r:0, t:0, b:0},chart.getTables);
230+
let zoom = chart.getZoom;
231+
let curPan = chart.getPan;
232+
let newPan = {
233+
x: zoom*((bounds.r-bounds.l)/2),
234+
y: zoom*((bounds.t-bounds.b)/2)
235+
}
236+
console.log(newPan,bounds,chart.getPan)
237+
chart.updatePan(newPan)
206238
// do nothing
207239
}
208240

web/src/components/VDbChart/VDbChart.vue

+36-2
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@
6464
:key="ref.id"
6565
v-bind="ref"
6666
:container-ref="root"
67+
@click:ref="dblclickHelper(onRefDblClick, $event, ref)"
6768
@click.passive="dblclickHelper(onRefDblClick, $event, ref)"
6869
@mouseenter.passive="onRefMouseEnter"
6970
@mouseleave.passive="onRefMouseLeave"
71+
7072
/>
7173
</g>
7274
<g id="tables-layer"
@@ -90,7 +92,15 @@
9092
<g id="panel-overlays-layer"
9193
v-if="store.loaded">
9294
<v-db-panel
93-
@click:color="onColorClick" @touchend.passive="onColorClick"/>
95+
@click:color="onColorClick"
96+
@touchend.passive="onColorClick"/>
97+
98+
</g>
99+
<g id="panel-ref-overlays-layer"
100+
v-if="store.loaded">
101+
<v-db-ref-panel
102+
@click:cp="onCpClick"
103+
@touchend.passive="onCpClick"/>
94104
</g>
95105

96106
</g>
@@ -132,10 +142,11 @@
132142
import { computed, nextTick, onMounted, reactive, ref, watch, watchEffect } from 'vue'
133143
import VDbTable from './VDbTable'
134144
import VDbRef from './VDbRef'
135-
import svgPanZoom from 'svg-pan-zoom'
145+
import svgPanZoom, { pan } from 'svg-pan-zoom'
136146
import { useChartStore } from '../../store/chart'
137147
import VDbTooltip from './VDbTooltip'
138148
import VDbPanel from './VDbPanel.vue'
149+
import VDbRefPanel from './VDbRefPanel.vue'
139150
import VDbTableGroup from './VDbTableGroup'
140151
141152
const store = useChartStore()
@@ -339,11 +350,34 @@
339350
panZoom.value.zoom(newZoom)
340351
})
341352
353+
354+
355+
342356
function onRefDblClick (e, ref) {
343357
console.log("onRefDblClick", e, ref);
344358
emit('dblclick:ref', e, ref);
345359
}
346360
361+
function onCpClick (e,operation,points,wpid,refid) {
362+
363+
let rl = store.getRef(refid);
364+
if (operation == 'RESET'){
365+
rl.vertices = [];
366+
}
367+
if (operation == 'ADD'){
368+
rl.vertices.splice(rl.vertices.length-1,0,{x:points.x, y:points.y});
369+
//rl.vertices.push({x:points.x, y:points.y});
370+
}
371+
if (operation == 'DEL'){
372+
if (rl.vertices.length > 2){
373+
rl.vertices.splice(Number(wpid),1);
374+
}
375+
376+
}
377+
store.updateRef(refid,rl)
378+
store.hideRefPanel();
379+
}
380+
347381
function onColorClick (e, id,name, color) {
348382
349383
store.updateTableColor(name,id,color);

web/src/components/VDbChart/VDbPanel.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<svg v-if="panel.show"
33
:x="panel.x"
44
:y="panel.y"
5-
class="db-tooltip"
5+
class="db-tooltip db-tooltip_panel"
66
>
77
<foreignObject x="0" y="0" width="100%" height="100%" class="db-tooltip__content">
88
<q-card class="db-tooltip__content-card" >
@@ -18,7 +18,7 @@
1818
1919
const store = useChartStore()
2020
const emit = defineEmits([
21-
'click:color'
21+
'click:color',
2222
])
2323
2424
function onClick(e, ...args){

web/src/components/VDbChart/VDbRef.vue

+22-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
@mousedown.passive="controlPoint_startDrag"
5252
@mouseenter.passive="controlPoint_onMouseEnter"
5353
@mouseleave.passive="controlPoint_onMouseLeave"
54+
@contextmenu.prevent="showTooltip"
5455
/>
5556
</g>
5657

@@ -61,6 +62,7 @@
6162
import { computed, nextTick, onBeforeUnmount, onMounted, onUpdated, reactive, ref, watch, watchEffect } from 'vue'
6263
import { useChartStore } from '../../store/chart'
6364
import { snap } from '../../utils/MathUtil'
65+
import VDbRefActions from './VDbRefActions.vue'
6466
6567
const props = defineProps({
6668
id: Number,
@@ -75,6 +77,9 @@
7577
containerRef: Object
7678
})
7779
80+
const emit = defineEmits([
81+
'click:ref',
82+
])
7883
const store = useChartStore()
7984
let s = store.getRef(props.id)
8085
@@ -204,7 +209,7 @@
204209
const directions = getDirection(startAnchors.value,endAnchors.value);
205210
const cpstart_direction = getDirection(startAnchors.value,controlPoints.value[0]);
206211
const cpend_direction = getDirection(endAnchors.value,controlPoints.value[1]);
207-
console.log('direction',directions);
212+
//console.log('direction',directions);
208213
let corelations = {
209214
x0: 0,
210215
y0: 0,
@@ -357,6 +362,22 @@
357362
v.y = snap((p.y - controlPoint_dragOffset.y), gridSnap)
358363
359364
}
365+
366+
const showTooltip = (e) => {
367+
const p = store.inverseCtm.transformPoint({
368+
x: e.offsetX,
369+
y: e.offsetY
370+
})
371+
const tooltipPosition = {
372+
x: p.x + 10,
373+
y: p.y,
374+
}
375+
// console.log(e.target)
376+
store.showRefPanel(tooltipPosition, VDbRefActions, {click:p, wpid:e.target.dataset.id, data:props})
377+
emit('click:ref', e, s);
378+
379+
}
380+
360381
const controlPoint_drop = (e) => {
361382
controlPoint_dragOffset.x = 0
362383
controlPoint_dragOffset.y = 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<template>
2+
3+
<q-card-section style="padding: 8px 8px;">
4+
<div class="text-subtitle2">Ref actions</div>
5+
<div class="row">
6+
<q-list dense class="db-tooltip_panel__list">
7+
<q-item clickable v-ripple @click.passive="act($event,'RESET')">
8+
<q-item-section avatar>
9+
<q-icon color="primary" name="refresh" />
10+
</q-item-section>
11+
12+
<q-item-section>Reset waypoints</q-item-section>
13+
</q-item>
14+
<q-item clickable v-ripple @click.passive="act($event,'ADD')">
15+
<q-item-section avatar>
16+
<q-icon color="primary" name="add" />
17+
</q-item-section>
18+
19+
<q-item-section>Add waypoint</q-item-section>
20+
</q-item>
21+
<q-item clickable v-ripple @click.passive="act($event,'DEL')">
22+
<q-item-section avatar>
23+
<q-icon color="primary" name="delete" />
24+
</q-item-section>
25+
26+
<q-item-section>Remove waypoint</q-item-section>
27+
</q-item>
28+
</q-list>
29+
</div>
30+
</q-card-section>
31+
</template>
32+
33+
<script setup>
34+
35+
const props = defineProps({
36+
data: Object,
37+
wpid: Number,
38+
click:Object
39+
});
40+
41+
function act(e,option) {
42+
console.log(e,option,props)
43+
emit('click:ref-cp',e,option,props.click,props.wpid,props.data.id)
44+
}
45+
46+
const emit = defineEmits([
47+
'click:ref-cp'
48+
])
49+
50+
</script>
51+
52+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<template>
2+
<svg v-if="refspanel.show"
3+
:x="refspanel.x"
4+
:y="refspanel.y"
5+
class="db-tooltip db-tooltip_panel"
6+
>
7+
<foreignObject x="0" y="0" width="100%" height="100%" class="db-tooltip__content">
8+
<q-card class="db-tooltip__content-card" >
9+
<component :is="refspanel.component" v-bind="refspanel.binds" @click:ref-cp="onClickRefCp"/>
10+
</q-card>
11+
</foreignObject>
12+
</svg>
13+
</template>
14+
15+
<script setup>
16+
import { useChartStore } from '../../store/chart'
17+
import { computed } from 'vue'
18+
19+
const store = useChartStore()
20+
const emit = defineEmits([
21+
'click:cp'
22+
])
23+
24+
function onClickRefCp(e, ...args){
25+
26+
emit("click:cp",e, ...args)
27+
}
28+
29+
30+
const refspanel = computed(() => store.refspanel)
31+
</script>

web/src/components/VDbExportDialog.vue

+20-3
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,41 @@ const props = defineProps({
7272
a.setAttribute('download',props.file_name);
7373
a.click();
7474
URL.revokeObjectURL(url);
75+
document.removeChild(a);
7576
7677
}
7778
7879
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
7980
8081
function onOKClick () {
81-
const fstore = useFilesStore();
82+
83+
$q.notify({
84+
caption:"Export",
85+
message:`Saving file...`,
86+
multiLine:true,
87+
timeout:2000,
88+
color: 'indigo-7',
89+
spinner:true,
90+
position: "center"})
91+
92+
saveFile();
93+
94+
onDialogOK()
95+
}
96+
97+
function saveFile(){
98+
const fstore = useFilesStore();
8299
const filesfs = localforage.createInstance({
83100
name: "dbdiagram-oss",
84101
storeName: "files"
85102
});
103+
86104
87105
88106
if (props.id == 'json'){
89107
filesfs.getItem(fstore.getCurrentFile).then(
90108
(file) => {
91-
saveAs(new Blob([JSON.stringify(file)], {type:"image/svg+xml"}));
109+
saveAs(new Blob([JSON.stringify(file)], {type:"application/json"}));
92110
}
93111
)
94112
@@ -132,7 +150,6 @@ const props = defineProps({
132150
icon: 'task',
133151
position: 'bottom-right'
134152
})
135-
onDialogOK()
136153
}
137154
138155
function saveSvg(){

0 commit comments

Comments
 (0)