Skip to content
Snippets Groups Projects
Commit 6fefbedd authored by Leah Tacke genannt Unterberg's avatar Leah Tacke genannt Unterberg
Browse files

improved DBOverview a bit

parent a8f01de1
No related branches found
No related tags found
No related merge requests found
Pipeline #477252 skipped
<script setup>
import {useAPI} from "@/services/api";
import {computed, onMounted, onUnmounted, ref} from "vue";
import {computed, onMounted, onUnmounted, ref, useTemplateRef} from "vue";
import VueMermaidString from "vue-mermaid-string";
import QueryDBSchemaView from "@/components/subcomponents/view/QueryDBSchemaView.vue";
import {useConstantsStore} from "@/services/constantsStore";
import SourceDBSelector from "@/components/helpers/SourceDBSelector.vue";
import MarkFK from "@/components/subcomponents/view/MarkFK.vue";
import * as d3 from "d3"
import {useSelectionStore} from "@/services/selectionStore";
const api = useAPI()
const mermaidText = ref("")
const loading = ref(false)
const constants = useConstantsStore()
const selection = useSelectionStore()
const sourceDB = ref(constants.dbSources[0])
......@@ -25,14 +27,20 @@ async function getMermaid(selection) {
const params = {source: sourceDB.value, version: "mermaid"};
const r = selection == null ? await api.makeERD(params) : await api.makeERD(params, {selection})
if (r?.data) {
console.log('updated mermaid text', r.data.mermaid)
mermaidText.value = r.data.mermaid
new Promise(() => setTimeout(unlockSVG, 500)) // never do this again
// new Promise(() => setTimeout(unlockSVG, 500)) // never do this again
}
loading.value = false
}
function nodeClick(nodeId) {
console.log(nodeId)
function classLabelClick(nodeId) {
const source = sourceDB.value
if (!!source && !!nodeId) {
const [schema, name] = nodeId.split("_")
selection.toggleFavorite({source, schema, name})
}
}
......@@ -50,24 +58,102 @@ window.addEventListener('load', function () {
});
});
*/
const mermaidSVG = ref(null)
function unlockSVG() {
d3.select(".make-zoomy div svg").attr("height", "100vh").attr("preserveAspectRatio", "xMidYMin meet")
const mermaidSVG = useTemplateRef("mermaidSVG")
const zoomyDiv = useTemplateRef("zoomyDiv")
function injectStuff() {
const svgElement = mermaidSVG.value?.$el.querySelector('svg')
if (svgElement) {
//const nodes = svgElement.querySelectorAll('g g.root g.nodes g.node')
const classTitles = svgElement.querySelectorAll('g g.root g.nodes g.node g.label .classTitle div span.nodeLabel')
//classTitles.forEach(el => {
// const className = el.innerHTML
// el.innerHTML = `<a>${className}</a>`
// //el.innerHTML = `<a>${className}</a>`
// el.addEventListener('click', e => {
// console.log('clicked on title of', className, e)
// })
// el.classList.add('clickable')
// console.log('inserted some html in', el)
//})
//const Cls = Vue.extend(CheckboxButton)
//const instance = new Cls({vuetify, propsData: {trueIcon: "mdi-star", falseIcon: "mdi-star-outline"}})
//instance.$mount()
//const favBtn = '<v-checkbox-btn density="compact" true-icon="mdi-star" false-icon="mdi-star-outline"></v-checkbox-btn>' //'<v-checkbox-btn density="compact" true-icon="mdi-star" false-icon="mdi-star-outline" v-model="selectionStore.favoritedTables" :value="item.tableIdentifier" @click.stop=""></v-checkbox-btn>'
classTitles.forEach((el) => {
const className = el.innerHTML
el.classList.add('makeClickable')
//const a = document.createElement("a", {href: "#"})
//a.innerHTML = "fav"
el.addEventListener('click', e => {
classLabelClick(className)
console.log('clicked on title of', className, e)
})
console.log('inserted some html in', el)
})
}
}
onUnmounted(() => {
var g = d3.select(".make-zoomy");
g.on(".zoom", null)
const resizeSVG = () => {
const svgElement = mermaidSVG.value?.$el.querySelector('svg')
const container = zoomyDiv.value
if (svgElement && container) {
const width = container.clientWidth
const height = container.clientHeight
// Set the width and height of the SVG to match the container's dimensions
d3.select(svgElement)
.attr('width', width)
.attr('height', height)
.attr('viewBox', `0 0 ${width} ${height}`)
.attr('preserveAspectRatio', 'xMidYMin meet')
}
}
const observer = new MutationObserver((mr, mo) => {
const svgElement = mermaidSVG.value?.$el.querySelector('svg')
if (svgElement) {
// Reapply zoom behavior and resize the SVG after each diagram update
injectStuff()
initializeZoom(svgElement)
resizeSVG()
}
})
onMounted(() => {
var g = d3.select(".make-zoomy");
//gs.each(g => {
var zoom = d3.zoom().on("zoom", function (event) {
g.select("div svg g").attr("transform", event.transform);
const initializeZoom = (svgElement) => {
const gElement = d3.select(svgElement.querySelector('g'))
// Define zoom behavior
const zoom = d3.zoom().on('zoom', (event) => {
gElement.attr('transform', event.transform) // Apply zoom/pan transformation to the <g> element
});
g.call(zoom);
//})
// Apply the zoom behavior to the SVG
d3.select(svgElement).call(zoom)
}
onMounted(() => {
// var g = d3.select(".make-zoomy")
// //gs.each(g => {
// var zoom = d3.zoom().on("zoom", function (event) {
// g.select("div svg g").attr("transform", event.transform)
// });
// g.call(zoom)
// //})
observer.observe(mermaidSVG.value.$el, {childList: true})
window.addEventListener("resize", resizeSVG)
})
onUnmounted(() => {
// var g = d3.select(".make-zoomy")
// g.on(".zoom", null)
window.removeEventListener("resize", resizeSVG)
observer.disconnect()
})
async function applyFilter(selection) {
......@@ -104,9 +190,9 @@ async function applyFilter(selection) {
<v-divider></v-divider>
<v-row class="flex-grow-1 fill-height">
<v-col>
<div class="make-zoomy">
<vue-mermaid-string :value="mermaidText" :options="{securityLevel: 'loose'}"
@node-click="nodeClick" ref="mermaidSVG"></vue-mermaid-string>
<div class="make-zoomy" style="height: 100%;" ref="zoomyDiv">
<vue-mermaid-string :value="mermaidText" :options="{securityLevel: 'loose', er: {useMaxWidth: false}}"
ref="mermaidSVG"></vue-mermaid-string>
</div>
</v-col>
</v-row>
......@@ -122,6 +208,7 @@ async function applyFilter(selection) {
</template>
<style scoped>
.make-zoomy {
.v-container >>> .makeClickable {
cursor: pointer;
}
</style>
......@@ -34,7 +34,7 @@ async function onResetAction() {
<v-app-bar-title>MitM Exporter</v-app-bar-title>
<v-select class="pa-2 align-self-center" :items="mitms" v-model="selectedMitM" variant="plain" hide-details>
<v-select class="pa-2 align-self-center flex-grow-0" :items="mitms" v-model="selectedMitM" variant="plain" hide-details>
</v-select>
<v-spacer></v-spacer>
......
......@@ -2,6 +2,7 @@ import {defineStore} from "pinia";
import {computed, ref} from "vue";
import {MitM, MitMDefinition, TableIdentifier, useAPI} from "@/services/api";
import {useConstantsStore} from "@/services/constantsStore";
import {isSameTID} from "@/services/utils";
export const useSelectionStore = defineStore('selection', () => {
......@@ -20,17 +21,19 @@ export const useSelectionStore = defineStore('selection', () => {
function toggleFavorite(table: TableIdentifier) {
const favs = favoritedTables.value
if (favs.includes(table))
favs.splice(favs.indexOf(table), 1)
const idx = favs.findIndex(tid => isSameTID(tid, table))
if (idx >= 0)
favs.splice(idx, 1)
else
favs.push(table)
}
function updateFavorite(table: TableIdentifier, newState: boolean = true) {
const favs = favoritedTables.value
if (favs.includes(table)) {
const idx = favs.findIndex(tid => isSameTID(tid, table))
if (idx >= 0) {
if (!newState)
favs.splice(favs.indexOf(table), 1)
favs.splice(idx, 1)
} else if (newState)
favs.push(table)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment