import '../analysis/graph-viewer.js'
import gql from 'graphql-tag'
import { css, html, nothing } from 'lit'
import { customElement, query, state } from 'lit/decorators.js'
import { client } from '@operato/graphql'
import { i18next, localize } from '@operato/i18n'
import { PageView } from '@operato/shell'
import { ScrollbarStyles } from '@operato/styles'
import { GraphData, Node, Relationship } from '../analysis/graph-data.js'
import { GraphViewer } from '../analysis/graph-viewer.js'
import { GraphViewerStyles } from '../analysis/graph-viewer-style'
@customElement('integration-analysis')
export class IntegrationAnalysis extends localize(i18next)(PageView) {
static styles = [
GraphViewerStyles,
ScrollbarStyles,
css`
:host {
position: relative;
display: flex;
flex-direction: column;
overflow: hidden;
background-color: var(--md-sys-color-background);
padding: 0;
}
[graph-container] {
flex: 1;
margin: 0;
padding: 0;
}
.graph-info {
position: absolute;
top: 10px;
left: 10px;
opacity: 0.8;
}
`
]
@state() private graphViewer?: GraphViewer
@state() private analysis?: { nodes: Node[]; relationships: Relationship[] }
@state() private info?: { cls: string; property: string; value: string } | null
@query('[graph-container]') container!: HTMLDivElement
@query('[node-info]') nodeInfo!: HTMLAnchorElement
get context() {
return {
title: i18next.t('text.integration analysis'),
search: {
handler: search => this.onSearch(search)
},
help: 'integration/ui/integration-analysis'
}
}
render() {
const info = this.info
return html`
console.log(e.detail)}
@node-mouseleave=${(e: CustomEvent) => console.log(e.detail)}
>
`
}
updated(changes) {
if (changes.has('analysis')) {
if (!this.graphViewer) {
this.graphViewer = new GraphViewer(this.container, {
highlight: [
{
class: 'Connection',
property: 'missing',
value: true
},
{
class: 'Scenario',
property: 'missing',
value: true
},
{
class: 'Tag',
property: 'missing',
value: true
}
],
minCollision: 60,
graphData: {
results: [
{
columns: [],
data: [
{
graph: this.analysis
}
]
}
],
errors: []
},
nodeRadius: 25,
onNodeDoubleClick: node => {
switch (node.id) {
case '25':
// Google
window.open(node.properties.url, '_blank')
break
default:
break
}
},
zoomFit: true
})
} else {
this.graphViewer.updateWithGraphData({
results: [{ columns: [], data: [{ graph: this.analysis! }] }],
errors: []
})
}
}
if (changes.has('info') && this.info) {
}
}
async pageUpdated(changes) {
if ('active' in changes) {
if (this.active) {
await this.fetchIntegrationAnalysis()
this.graphViewer?.simulation.restart()
} else {
this.graphViewer?.simulation.stop()
}
}
}
async fetchIntegrationAnalysis() {
const response = await client.query({
query: gql`
query {
integrationAnalysis
}
`
})
this.analysis = response.data.integrationAnalysis
}
async onSearch(search: string) {
if (!this.graphViewer) {
return
}
if (!search) {
this.graphViewer.updateWithGraphData({
results: [{ columns: [], data: [{ graph: this.analysis! }] }],
errors: []
})
return
}
const { nodes = [], relationships = [] } = this.analysis || {}
// 검색어와 일치하는 노드를 필터링
const matchingNodes = nodes.filter(node => {
return node.properties.name && node.properties.name.toLowerCase().includes(search.toLowerCase())
})
if (matchingNodes.length === 0) {
this.graphViewer.updateWithGraphData({
results: [{ columns: [], data: [{ graph: { nodes: [], relationships: [] } }] }],
errors: []
})
return
}
// 1차로 연결된 노드와 관계를 찾기 위해 관련된 노드 ID를 추적
const relatedNodeIds = new Set()
const filteredNodes = [] as Node[]
const filteredRelationships = [] as Relationship[]
matchingNodes.forEach(node => {
relatedNodeIds.add(node.id)
filteredNodes.push(node)
relationships.forEach(relationship => {
const { source, target } = relationship || {}
if (source!.id === node.id || target!.id === node.id) {
relatedNodeIds.add(source!.id)
relatedNodeIds.add(target!.id)
filteredRelationships.push(relationship!)
}
})
})
// 관련된 노드 추가
relatedNodeIds.forEach(nodeId => {
const node = nodes.find(n => n.id === nodeId)
if (node) {
filteredNodes.push(node)
}
})
// 새로운 GraphData 구성
const filteredGraphData: GraphData = {
results: [
{
columns: [],
data: [
{
graph: {
nodes: filteredNodes,
relationships: filteredRelationships
}
}
]
}
],
errors: []
}
// GraphViewer 업데이트
this.graphViewer.updateWithGraphData(filteredGraphData)
}
}