Untitled

 avatar
unknown
plain_text
2 years ago
4.4 kB
6
Indexable
export function SetKnowledgeGraph({
  graphRef,
  graphComponentRef,
  data,
  containerId,
  zoomValues
}: IProps) {
  const graph = graphRef.current;
  const graphComponent = graphComponentRef.current;
  if (!graph || !graphComponent) {
    return;
  }
  graph.clear();

  const { width, height } = CalculateLayoutOptions(containerId, zoomValues);
  graph.nodeDefaults.style = new HtmlEditableNodeStyle(PerspectiveItem);
  graph.nodeDefaults.size = [width, height];

  graph.edgeDefaults.style = new PolylineEdgeStyle({
    stroke: '1px #3F3F46',
    targetArrow: new Arrow({
      fill: '#3F3F46',
      stroke: '#3F3F46',
      type: ArrowType.TRIANGLE
    })
  });

  const topics: Array<any> = data.items.filter(i => hasItemLabel(i, 'Topic'));
  const documents: Array<any> = data.documents.map(doc =>
    Object.assign({ graph }, doc, {
      relations: data.relations.filter(d => d.documentId === doc.id)
    })
  );

  let edges: Array<any> = data.relations
    .map(item => ({
      from: item.documentId,
      to: item.itemId,
      label: ''
    }))
    .filter(item => item.from !== item.to);

  const filtered = filteredItem.get();
  const itemId = showItemModal.get()?.item?.id ?? filtered;

  if (filtered || itemId) {
    //remove other edges that are not related to selected item
    edges = edges.filter(item => item.from === itemId || item.to === itemId);
  }

  const graphBuilder = new GraphBuilder(graph);
  graphBuilder.createNodesSource(topics, 'id');
  graphBuilder.createNodesSource(documents, 'id');
  graphBuilder.createNodesSource(data.subPerspectives, 'id');
  graphBuilder.createEdgesSource(edges, 'from', 'to');
  graphBuilder.buildGraph();

  graphComponent.inputMode = new GraphViewerInputMode({});
  const layout = new HierarchicLayout();
  const layoutData = new HierarchicLayoutData();
  layout.orthogonalRouting = true;
  layout.automaticEdgeGrouping = true;
  layout.backLoopRouting = false;

  const layering = layoutData.layerConstraints;
  const graphNodes = graphComponent.graph.nodes.toArray();
  const documentLayer = 0;
  const parentTopicLayer = 1;
  const activeTopicLayer = 2;
  let topicLayer = 3;
  let index = 0;
  if (itemId || filtered) {
    graphNodes.forEach(node => {
      if (hasItemLabel(node.tag, 'Document')) {
        node.tag.layer = documentLayer;
      } else if (hasItemLabel(node.tag, 'Topic')) {
        if (node.tag.id === itemId) {
          node.tag.layer = activeTopicLayer;
        } else {
          const incomingEdge = edges.find(e => e.from === node.tag.id);
          const outgoingEdge = edges.find(e => e.to === node.tag.id);
          if (incomingEdge) {
            node.tag.layer = parentTopicLayer;
          } else if (outgoingEdge) {
            node.tag.layer = topicLayer;
            index++;
            if (index % 5 === 0) {
              topicLayer++;
            }
          }
        }
      } else {
        node.tag.layer = 0;
      }
    });

    graphNodes.forEach(node => {
      layering.nodeComparables.mapper.set(node, node.tag.layer);
    });
  }

  const busDescriptor = new HierarchicLayoutBusDescriptor();
  const busIncomingEdges = graphComponent.graph.edges.filter(e => e.tag.to === itemId).toArray();
  if (busIncomingEdges.length > 0) {
    const docDescriptor = new HierarchicLayoutBusDescriptor();
    const topicDescriptor = new HierarchicLayoutBusDescriptor();
    const docEdges: any = [];
    const topicEdges: any = [];
    busIncomingEdges.forEach(e => {
      const id = e.tag.from;
      if (
        graphComponent.graph.nodes.find(n => n.tag.id === id && hasItemLabel(n.tag, 'Document'))
      ) {
        docEdges.push(e);
      } else if (
        graphComponent.graph.nodes.find(n => n.tag.id === id && hasItemLabel(n.tag, 'Topic'))
      ) {
        topicEdges.push(e);
      }
    });

    if (docEdges) {
      layoutData.buses.add(docDescriptor).items = docEdges;
    }
    if (topicEdges) {
      layoutData.buses.add(topicDescriptor).items = topicEdges;
    }
  }
  const busEdges = graphComponent.graph.edges.filter(e => e.tag.from === itemId).toArray();
  if (busEdges.length > 0) {
    layoutData.buses.add(busDescriptor).items = busEdges;
  }

  graphComponent.graph.applyLayout(layout, layoutData);

  const limiter = graphComponent.viewportLimiter;
  limiter.honorBothDimensions = true;
  limiter.bounds = null;
  graphComponent.fitGraphBounds();
}
Editor is loading...