{"ast":null,"code":"var __jsx = React.createElement;\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { collectDagFacts } from '~/resource/graphs';\nimport { useTranslation } from '~/utils/i18n';\nimport NodeInfo from '~/components/GraphsPage/NodeInfo';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport Content from '~/components/Content';\nimport Field from '~/components/Field';\nimport Preloader from '~/components/Preloader';\nimport RawButton from '~/components/Button';\nimport RawRangeSlider from '~/components/RangeSlider';\nimport Title from '~/components/Title';\nimport isEmpty from 'lodash/isEmpty';\nimport { rem } from '~/utils/style';\nimport { saveSvgAsPng } from 'save-svg-as-png';\nimport styled from 'styled-components';\nimport useRequest from '~/hooks/useRequest'; // eslint-disable-next-line @typescript-eslint/no-empty-function\n\nconst dumbFn = () => {};\n\nconst SubSection = styled.div.withConfig({\n  displayName: \"graphs__SubSection\",\n  componentId: \"sc-10saymz-0\"\n})([\"margin-bottom:\", \";\"], rem(30));\nconst Button = styled(RawButton).withConfig({\n  displayName: \"graphs__Button\",\n  componentId: \"sc-10saymz-1\"\n})([\"width:100%;text-transform:uppercase;& + &{margin-top:\", \";}\"], rem(20));\nconst Empty = styled.div.withConfig({\n  displayName: \"graphs__Empty\",\n  componentId: \"sc-10saymz-2\"\n})([\"display:flex;justify-content:center;align-items:center;font-size:\", \";height:\", \";\"], rem(20), rem(150));\nconst RangeSlider = styled(RawRangeSlider).withConfig({\n  displayName: \"graphs__RangeSlider\",\n  componentId: \"sc-10saymz-3\"\n})([\"width:100%;\"]);\nconst GraphSvg = styled('svg').withConfig({\n  displayName: \"graphs__GraphSvg\",\n  componentId: \"sc-10saymz-4\"\n})([\"width:100%;cursor:grab;&.grabbing{cursor:grabbing;}.node{cursor:pointer;.label-container{stroke-width:3px;stroke:#e6e6e6;&.rect{rx:10;ry:10;}}&.operator{.label-container{fill:#cdd9da;}}&.output{.label-container{stroke-dasharray:5,5;stroke:#e6e6e6;fill:#cad2d0;}}&.input{.label-container{fill:#d5d3d8;}}&.active{.label-container{stroke:#25c9ff;}}}.edgePath path.path{stroke:#333;stroke-width:1.5px;}\"]);\nconst loadDagLibs = [import('d3'), import('dagre-d3')];\nconst MIN_SCALE = 0.1;\nconst MAX_SCALE = 4;\n\nconst useDag = graph => {\n  const {\n    0: displaySwitch,\n    1: setDisplaySwitch\n  } = useState({\n    detail: false,\n    input: false,\n    output: false\n  });\n  const facts = useMemo(() => collectDagFacts(graph), [graph]);\n  const dagInfo = useMemo(() => {\n    const {\n      inputLayer,\n      outputLayer,\n      briefLayer,\n      detailLayer,\n      findNode\n    } = facts;\n    const availableLayers = displaySwitch.detail ? [detailLayer] : [briefLayer];\n\n    if (displaySwitch.input) {\n      availableLayers.push(inputLayer);\n    }\n\n    if (displaySwitch.output) {\n      availableLayers.push(outputLayer);\n    }\n\n    return _objectSpread({}, availableLayers.reduce((memo, {\n      nodes,\n      edges\n    }) => ({\n      nodes: memo.nodes.concat(nodes),\n      edges: memo.edges.concat(edges)\n    }), {\n      nodes: [],\n      edges: []\n    }), {\n      findNode\n    });\n  }, [facts, displaySwitch]);\n  return {\n    dagInfo,\n    displaySwitch,\n    setDisplaySwitch\n  };\n};\n\nconst useDagreD3 = graph => {\n  const {\n    0: currentNode,\n    1: setCurrentNode\n  } = useState(undefined);\n  const {\n    dagInfo,\n    displaySwitch,\n    setDisplaySwitch\n  } = useDag(graph);\n  const {\n    0: downloadImage,\n    1: setDownloadImageFn\n  } = useState(() => dumbFn);\n  const {\n    0: fitScreen,\n    1: setFitScreenFn\n  } = useState(() => dumbFn);\n  const {\n    0: scale,\n    1: setScaleValue\n  } = useState(1);\n  const {\n    0: setScale,\n    1: setScaleFn\n  } = useState(() => dumbFn);\n  useEffect(() => {\n    Promise.all(loadDagLibs).then(([d3, {\n      default: dagre\n    }]) => {\n      if (!dagInfo.nodes.length || !dagInfo.edges.length) {\n        return;\n      }\n\n      const g = new dagre.graphlib.Graph();\n      g.setGraph({}).setDefaultEdgeLabel(() => ({}));\n      dagInfo.nodes.forEach(n => g.setNode(n.key, n));\n      dagInfo.edges.forEach(e => g.setEdge(e[0], e[1]));\n      const render = new dagre.render();\n      const svg = d3.select('svg'); // eslint-disable-line @typescript-eslint/no-explicit-any\n\n      const inner = svg.select('svg g');\n      render(inner, g);\n      const {\n        width,\n        height\n      } = g.graph();\n      const scaleFactor = 1;\n      svg.attr('height', Math.max(640, window.innerHeight + 40));\n      const zoom = d3.zoom() // eslint-disable-line @typescript-eslint/no-explicit-any\n      .scaleExtent([MIN_SCALE, MAX_SCALE]).on('zoom', function () {\n        setScaleValue(d3.event.transform.k / scaleFactor);\n        inner.attr('transform', d3.event.transform);\n      }).on('start', () => svg.classed('grabbing', true)).on('end', () => svg.classed('grabbing', false));\n      svg.call(zoom);\n      let prevDom; // install event listeners\n\n      svg.selectAll('g.node').on('click', v => {\n        const uid = v;\n        const {\n          type,\n          elem: dom\n        } = g.node(uid);\n\n        if (prevDom) {\n          prevDom.classList.remove('active');\n        }\n\n        dom.classList.add('active');\n        prevDom = dom;\n        const node = dagInfo.findNode(type, uid);\n\n        if (!node) {\n          setCurrentNode({\n            type: 'unknown',\n            guessType: type,\n            msg: uid\n          });\n          return;\n        }\n\n        setCurrentNode(_objectSpread({}, node, {\n          type\n        }));\n      });\n\n      const fitScreen = () => {\n        var _svg$node;\n\n        if (!svg) {\n          return;\n        }\n\n        const parent = (_svg$node = svg.node()) === null || _svg$node === void 0 ? void 0 : _svg$node.parentElement;\n\n        if (!parent) {\n          return;\n        }\n\n        const {\n          width: parentWidth\n        } = parent.getBoundingClientRect();\n        svg.call(zoom.transform, d3.zoomIdentity.translate((parentWidth - (width !== null && width !== void 0 ? width : 0) * scaleFactor) / 2, 20).scale(scaleFactor));\n      };\n\n      fitScreen();\n      setFitScreenFn(() => fitScreen);\n      setDownloadImageFn(() => {\n        let processing = false;\n        return async () => {\n          if (processing) {\n            return;\n          }\n\n          processing = true;\n          fitScreen();\n          const svgNode = svg.node();\n\n          if (!svgNode) {\n            return;\n          }\n\n          const originalHeight = +svg.attr('height');\n          svg.attr('height', (height !== null && height !== void 0 ? height : 0) + 40);\n          await saveSvgAsPng(svgNode, 'graph.png');\n          svg.attr('height', originalHeight);\n          processing = false;\n        };\n      });\n      setScaleFn(() => n => {\n        zoom.scaleTo(svg, scaleFactor * n);\n        setScaleValue(n);\n      });\n    });\n  }, [dagInfo]);\n  return {\n    currentNode,\n    displaySwitch,\n    setDisplaySwitch,\n    downloadImage,\n    fitScreen,\n    scale,\n    setScale\n  };\n};\n\nconst Graphs = () => {\n  const {\n    t\n  } = useTranslation(['graphs', 'common']);\n  const {\n    data,\n    error,\n    loading\n  } = useRequest('/graphs/graph');\n  const graph = useMemo(() => loading || isEmpty(data === null || data === void 0 ? void 0 : data.data) ? undefined : data === null || data === void 0 ? void 0 : data.data, [loading, data]);\n  const {\n    currentNode,\n    downloadImage,\n    fitScreen,\n    scale,\n    setScale\n  } = useDagreD3(graph);\n\n  const aside = __jsx(\"section\", null, __jsx(SubSection, null, __jsx(Button, {\n    icon: \"download\",\n    onClick: downloadImage\n  }, t('download-image')), __jsx(Button, {\n    icon: \"revert\",\n    onClick: fitScreen\n  }, t('restore-image'))), __jsx(SubSection, null, __jsx(Field, {\n    label: `${t('scale')}:`\n  }, __jsx(RangeSlider, {\n    min: MIN_SCALE,\n    max: MAX_SCALE,\n    step: 0.1,\n    value: scale,\n    onChange: setScale\n  }))), __jsx(SubSection, null, __jsx(Field, {\n    label: `${t('node-info')}:`\n  }), __jsx(NodeInfo, {\n    node: currentNode\n  })));\n\n  const ContentInner = useMemo(() => {\n    if (loading) {\n      return null;\n    }\n\n    if (error) {\n      return __jsx(Empty, null, t('common:error'));\n    }\n\n    if (!graph) {\n      return __jsx(Empty, null, t('common:empty'));\n    }\n\n    return __jsx(GraphSvg, null, __jsx(\"g\", null));\n  }, [loading, error, graph, t]);\n  return __jsx(React.Fragment, null, __jsx(Preloader, {\n    url: \"/graphs/graph\"\n  }), __jsx(Title, null, t('common:graphs')), __jsx(Content, {\n    aside: aside,\n    loading: loading\n  }, ContentInner));\n};\n\nGraphs.getInitialProps = () => ({\n  namespacesRequired: ['graphs', 'common']\n});\n\nexport default Graphs;","map":null,"metadata":{},"sourceType":"module"}