code browser
This commit is contained in:
229
src/components/FileFlowViewer.vue
Normal file
229
src/components/FileFlowViewer.vue
Normal file
@@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<Dialog v-model:visible="dialogCodeVisible" modal :header="'Class detail: '+selectionNode.fullyQualifiedClassName" class="change-modal":style="{ width: '70vw', minHeight:'75vh'}">
|
||||
<SingleClassViewer v-if="dialogCodeVisible" :className="selectionNode.fullyQualifiedClassName" />
|
||||
</Dialog>
|
||||
|
||||
<div>
|
||||
<VueFlow
|
||||
:nodes="nodes"
|
||||
:edges="edges"
|
||||
class=" basic-flow"
|
||||
:default-viewport="{ zoom: 1.5 }"
|
||||
:min-zoom="0.2"
|
||||
:max-zoom="4"
|
||||
@nodes-initialized="layoutGraph('LR')"
|
||||
>
|
||||
|
||||
|
||||
<template #node-class-node="props">
|
||||
<ClassNode v-bind="props" />
|
||||
</template>
|
||||
|
||||
<Background pattern-color="#aaa" :gap="16" />
|
||||
|
||||
<MiniMap />
|
||||
|
||||
<Controls position="top-left">
|
||||
</Controls>
|
||||
</VueFlow>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
|
||||
|
||||
import { Background } from '@vue-flow/background'
|
||||
import { Controls } from '@vue-flow/controls'
|
||||
import { VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import { MiniMap } from '@vue-flow/minimap'
|
||||
import Dialog from 'primevue/dialog'
|
||||
import { nextTick, onMounted, ref, toRefs, watch } from 'vue'
|
||||
import ClassNode from './ClassNode.vue'
|
||||
import { useLayout } from './useLayout'
|
||||
|
||||
import axios from 'axios'
|
||||
import { defineProps } from 'vue'
|
||||
import 'vue3-markdown/dist/style.css'
|
||||
|
||||
|
||||
const { onInit, onNodeDragStop, onConnect, addEdges, setViewport, toObject, onNodeClick,fitView } = useVueFlow()
|
||||
|
||||
const nodes = ref(null)
|
||||
const edges = ref(null)
|
||||
const dark = ref(false)
|
||||
const selectionNode = ref({fullyQualifiedClassName: '', description: ''})
|
||||
const { graph, layout, previousDirection } = useLayout()
|
||||
|
||||
const dialogCodeVisible = ref(false)
|
||||
const props = defineProps({
|
||||
file: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
application: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const { file } = toRefs(props);
|
||||
const fileDetails = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
//defineNodes()
|
||||
})
|
||||
|
||||
watch(() => props.file, (first, second) => {
|
||||
loadFileDetails(first)
|
||||
});
|
||||
|
||||
onInit((vueFlowInstance) => {
|
||||
vueFlowInstance.fitView()
|
||||
})
|
||||
|
||||
|
||||
function loadFileDetails(filename){
|
||||
|
||||
let fileInfo={
|
||||
filename: filename,
|
||||
applicationName: props.application
|
||||
}
|
||||
|
||||
axios.post("/source-module/getFileSimpleInfo",fileInfo).then(response => {
|
||||
fileDetails.value =response.data
|
||||
defineNodes()
|
||||
})
|
||||
}
|
||||
|
||||
onNodeClick(({ event, nodes, node }) => {
|
||||
console.log(node)
|
||||
if(node.type == 'class-node') {
|
||||
selectionNode.value = node.data.data
|
||||
dialogCodeVisible.value = true
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
function layoutGraph(direction) {
|
||||
nodes.value = layout(nodes.value, edges.value, direction)
|
||||
nextTick(() => {
|
||||
fitView()
|
||||
})
|
||||
}
|
||||
|
||||
function defineNodes() {
|
||||
|
||||
var tmpNode=[]
|
||||
var tmpEdges=[]
|
||||
var filename = fileDetails.value.filename.split("\\").slice(-1)[0].split("/").slice(-1)[0]
|
||||
|
||||
tmpNode.push({
|
||||
id: filename,
|
||||
data: { label: filename },
|
||||
position: { x: 250, y: 0 },
|
||||
class: 'light',
|
||||
},)
|
||||
|
||||
fileDetails.value.classes.forEach((c) => {
|
||||
tmpNode.push({
|
||||
id: c.name,
|
||||
data: { label:c.name.split(".").slice(-1)[0] , data:{ fullyQualifiedClassName:c.name} },
|
||||
position: { x: 250, y: 0 },
|
||||
class: 'light',
|
||||
type: 'class-node'
|
||||
})
|
||||
tmpEdges.push({
|
||||
id: filename + c.name,
|
||||
source: filename,
|
||||
target: c.name,
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
nodes.value = tmpNode
|
||||
edges.value = tmpEdges
|
||||
layoutGraph('LR')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@import '@vue-flow/core/dist/style.css';
|
||||
@import '@vue-flow/core/dist/theme-default.css';
|
||||
@import '@vue-flow/controls/dist/style.css';
|
||||
@import '@vue-flow/minimap/dist/style.css';
|
||||
|
||||
|
||||
|
||||
.basic-flow{
|
||||
height: 90vh;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.vue-flow__minimap {
|
||||
transform: scale(75%);
|
||||
transform-origin: bottom right;
|
||||
}
|
||||
|
||||
.basic-flow.dark {
|
||||
background:#2d3748;
|
||||
color:#fffffb
|
||||
}
|
||||
|
||||
.basic-flow.dark .vue-flow__node {
|
||||
background:#4a5568;
|
||||
color:#fffffb
|
||||
}
|
||||
|
||||
.basic-flow.dark .vue-flow__node.selected {
|
||||
background:#333;
|
||||
box-shadow:0 0 0 2px #2563eb
|
||||
}
|
||||
|
||||
.basic-flow .vue-flow__controls {
|
||||
display:flex;
|
||||
flex-wrap:wrap;
|
||||
justify-content:center
|
||||
}
|
||||
|
||||
.basic-flow.dark .vue-flow__controls {
|
||||
border:1px solid #FFFFFB
|
||||
}
|
||||
|
||||
.basic-flow .vue-flow__controls .vue-flow__controls-button {
|
||||
border:none;
|
||||
border-right:1px solid #eee
|
||||
}
|
||||
|
||||
.basic-flow.dark .vue-flow__controls .vue-flow__controls-button:hover {
|
||||
background:#4d4d4d
|
||||
}
|
||||
|
||||
.basic-flow.dark .vue-flow__edge-textbg {
|
||||
fill:#292524
|
||||
}
|
||||
|
||||
.basic-flow.dark .vue-flow__edge-text {
|
||||
fill:#fffffb
|
||||
}
|
||||
|
||||
|
||||
.vue-flow__node-class-node {
|
||||
border:1px solid #dc07bc;
|
||||
padding:10px;
|
||||
border-radius: 5px;
|
||||
background:#f5f5f5;
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
justify-content:space-between;
|
||||
align-items:center;
|
||||
gap:10px;
|
||||
max-width:250px;
|
||||
min-width: 200px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user