Advertisement
Guest User

Untitled

a guest
Jun 26th, 2024
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Vue3 drag and drop from: https://code.balkan.app/org-chart-js/draganddrop-from-another-element#JS
  2. const nodes = ref([
  3.   {
  4.     name: "IT",
  5.     occupied: 11,
  6.     available: 11,
  7.     id: "4a14",
  8.   },
  9.   {
  10.     name: "HR",
  11.     occupied: 8,
  12.     available: 12,
  13.     id: "a58e",
  14.     pid: "4a14",
  15.   },
  16.   {
  17.     name: "Finance",
  18.     occupied: 5,
  19.     available: 10,
  20.     id: "aff0",
  21.     pid: "a58e",
  22.   },
  23. ]);
  24.  
  25. // elements to drag and drop in chart
  26. const departments = ref([
  27.     {
  28.      
  29.       "name": "Marketing",
  30.       "occupied": 7,
  31.       "available": 14,
  32.       "id": "2de7"
  33.     },
  34.     {
  35.      
  36.       "name": "Sales",
  37.       "occupied": 12,
  38.       "available": 8,
  39.       "id": "8e40"
  40.     },
  41.     {
  42.      
  43.       "name": "Support",
  44.       "occupied": 6,
  45.       "available": 9,
  46.       "id": "9cd4"
  47.     },
  48.     {
  49.      
  50.       "name": "R&D",
  51.       "occupied": 4,
  52.       "available": 6,
  53.       "id": "2fc6"
  54.     },
  55.     {
  56.      
  57.       "name": "Operations",
  58.       "occupied": 9,
  59.       "available": 11,
  60.       "id": "7c5a"
  61.     },
  62.     {
  63.      
  64.       "name": "Legal",
  65.       "occupied": 3,
  66.       "available": 5,
  67.       "id": "7170"
  68.     },
  69.     {
  70.      
  71.       "name": "Administration",
  72.       "occupied": 11,
  73.       "available": 7,
  74.       "id": "19f0"
  75.     },
  76.     {
  77.       "id": "d017",
  78.       "name": "test",
  79.       "available": 123,
  80.       "occupied": 321,
  81.      
  82.     },
  83.     {
  84.       "name": "Administration but long name",
  85.       "available": 1,
  86.       "occupied": 1,
  87.       "slug": "slug602",
  88.       "id": "Qj_uxGw"
  89.     },
  90.     {
  91.       "name": "one two three four five six seven eight nine",
  92.       "available": 1,
  93.       "occupied": 1,
  94.       "id": "soIv29Y"
  95.     }
  96. ]);
  97.  
  98. // chart declaration
  99. OrgChart.templates.customTemplate = Object.assign(
  100.     {},
  101.     OrgChart.templates.ana,
  102.     {
  103.       node: '<rect x="0" y="0" height="{h}" width="{auto}" fill="purple" stroke-width="1" stroke="#aeaeae" rx="12" ry="12"></rect>',
  104.       link: '<path stroke-linejoin="round" stroke="#aeaeae" stroke-width="2px" fill="none" d="{rounded}" />',
  105.       field_0:
  106.         '<text data-width="{auto} " style="font-size: 16px; font-weight: 500; text-align: center;" fill="#ffffff" x="125" y="40" text-anchor="middle">{val}</text>',
  107.       field_1:
  108.         '<text data-width="{auto}" style="font-size: 12px; font-weight: 500; text-align: center;" fill="#ffffff" x="125" y="60" text-anchor="middle">Locuri ocupate: {val}</text>',
  109.       field_2:
  110.         '<text data-width="{auto}" style="font-size: 12px; font-weight: 500; text-align: center;" fill="#ffffff" x="125" y="80" text-anchor="middle">Locuri libere: {val}</text>',
  111.       link_field_0:
  112.         '<text text-anchor="middle" fill="#aeaeae" data-width="{w}" x="0" y="0" style="font-size:10px;">{val}</text>',
  113.       padding: [35, 20, 35, 20],
  114.       nodeMenuButton: '<g style="cursor:pointer;" data-ctrl-n-menu-id="{id}">
  115.        <rect x="-4" y="-10" fill="#000000" fill-opacity="0" width="22" height="22"></rect>
  116.        <circle cx="0" cy="0" r="2" fill="#ffffff"></circle>
  117.        <circle cx="7" cy="0" r="2" fill="#ffffff"></circle>
  118.        <circle cx="14" cy="0" r="2" fill="#ffffff"></circle>
  119.      </g>',
  120.     }
  121.   );
  122.  
  123. const mytree = (domEl, x) => {
  124.   OrgChart.RES.IT_IS_LONELY_HERE_LINK = "";
  125.  
  126.   OrgChart.templates.customTemplate = Object.assign(
  127.     {},
  128.     OrgChart.templates.ana,
  129.     {
  130.       node: '<rect x="0" y="0" height="{h}" width="{w}" fill="purple" stroke-width="1" stroke="#aeaeae" rx="12" ry="12"></rect>',
  131.       link: '<path stroke-linejoin="round" stroke="#aeaeae" stroke-width="2px" fill="none" d="{rounded}" />',
  132.       field_0:
  133.         '<text data-width="{auto} " style="font-size: 16px; font-weight: 500; text-align: center;" fill="#ffffff" x="125" y="40" text-anchor="middle">{val}</text>',
  134.       field_1:
  135.         '<text data-width="{auto}" style="font-size: 12px; font-weight: 500; text-align: center;" fill="#ffffff" x="125" y="60" text-anchor="middle">Locuri ocupate: {val}</text>',
  136.       field_2:
  137.         '<text data-width="{auto}" style="font-size: 12px; font-weight: 500; text-align: center;" fill="#ffffff" x="125" y="80" text-anchor="middle">Locuri libere: {val}</text>',
  138.       link_field_0:
  139.         '<text text-anchor="middle" fill="#aeaeae" data-width="{w}" x="0" y="0" style="font-size:10px;">{val}</text>',
  140.       padding: [35, 20, 35, 20],
  141.       nodeMenuButton: `<g style="cursor:pointer;" data-ctrl-n-menu-id="{id}">
  142.         <rect x="-4" y="-10" fill="#000000" fill-opacity="0" width="22" height="22"></rect>
  143.         <circle cx="0" cy="0" r="2" fill="#ffffff"></circle>
  144.         <circle cx="7" cy="0" r="2" fill="#ffffff"></circle>
  145.         <circle cx="14" cy="0" r="2" fill="#ffffff"></circle>
  146.       </g>`,
  147.     }
  148.   );
  149.  
  150.   chart = new OrgChart(domEl, {
  151.     nodes: x,
  152.     enableSearch: false,
  153.     nodeMouseClick: OrgChart.action.none,
  154.     mouseScroll: OrgChart.action.zoom,
  155.     scaleInitial: 1,
  156.     template: "customTemplate",
  157.     toolbar: {
  158.       layout: true,
  159.       zoom: true,
  160.       fit: true,
  161.     },
  162.     nodeMenu: {
  163.       remove: { text: "Remove" },
  164.       redirect: {
  165.         text: "Redirect",
  166.         icon: OrgChart.icon.link(20, 20, "#039BE5"),
  167.         // onClick: router.push(path.to.department)
  168.       },
  169.       details: {
  170.         text: "Detalii",
  171.       },
  172.     },
  173.     enableDragDrop: true,
  174.     // movable: OrgChart.movable.node,
  175.     nodeBinding: {
  176.       field_0: "name",
  177.       field_1: "occupied",
  178.       field_2: "available",
  179.     },
  180.   });
  181.  
  182.   chart.on("redraw", function () {
  183.     dynamicWidthNode();
  184.  
  185.     updateNodeMenuButtonPositions();
  186.  
  187.     let nodeElements = document.querySelectorAll("[data-n-id]");
  188.  
  189.     for (let i = 0; i < nodeElements.length; i++) {
  190.       let nodeElement = nodeElements[i];
  191.       nodeElement.ondrop = function (ev) {
  192.         ev.preventDefault();
  193.         let id = ev.dataTransfer.getData("id");
  194.  
  195.         const department = getDepartment(id);
  196.  
  197.         let targetNodeElement = ev.target;
  198.         // while pentru a gasi data-n-id cand dai drop
  199.         while (!targetNodeElement.hasAttribute("data-n-id")) {
  200.           console.log("in while", targetNodeElement);
  201.           targetNodeElement = targetNodeElement.parentNode;
  202.         }
  203.         let pid = targetNodeElement.getAttribute("data-n-id");
  204.  
  205.         if (nodeAlreadyInChart(id)) {
  206.           // return;
  207.           const index = getExistingNodeIndex(id);
  208.           console.log(index, nodes.value[index]);
  209.  
  210.           // verifica daca elementul curent nu e radacina pentru a schimba parent id(radacina n-are pid)
  211.           if (nodes.value[index].pid) {
  212.             nodes.value[index].pid = pid;
  213.           }
  214.         } else {
  215.           const newNode = {
  216.             id: department.id,
  217.             pid: pid,
  218.             name: department.name,
  219.             occupied: department.occupied,
  220.             available: department.available,
  221.             // movex: -120,
  222.             // movey: -350,
  223.           };
  224.  
  225.           nodes.value.push(newNode);
  226.           console.log(nodes.value);
  227.  
  228.           // chart.addNode(newNode, null, true);
  229.         }
  230.         chart.load(nodes.value);
  231.         // item.parentNode.removeChild(item)
  232.       };
  233.  
  234.       nodeElement.ondragover = function (ev) {
  235.         ev.preventDefault();
  236.       };
  237.     }
  238.   });
  239.  
  240.   chart.on("add", function (sender, node) {
  241.     chart.addNode(node);
  242.     return false;
  243.   });
  244.  
  245.   chart.on("click", handleNodeClick);
  246.   chart.on("slink-click", handleSlinkClick);
  247.   return chart;
  248. };
  249.  
  250. // utility functions
  251. const nodeAlreadyInChart = (id) => {
  252.   return nodes.value.find((node) => node.id === id) ? true : false;
  253. };
  254.  
  255. const getExistingNodeIndex = (id) => {
  256.   return nodes.value.findIndex((node) => node.id === id);
  257. };
  258.  
  259. const getDepartment = (id) => {
  260.   return departments.value.find((department) => department.id === id);
  261. };
  262.  
  263. function extractLastTwoValues(transform) {
  264.   const match = transform.match(/matrix\(([^)]+)\)/);
  265.   if (match) {
  266.     const values = match[1].split(",").map((value) => parseFloat(value.trim()));
  267.     return values.slice(-2);
  268.   }
  269.   return [0, 0]; // Default value if the regex does not match
  270. }
  271.  
  272. function dynamicWidthNode() {
  273.   let allNodesRect = document.querySelectorAll("[data-n-id]");
  274.   console.log("all nodes rect", allNodesRect);
  275.   allNodesRect.forEach((node) => {
  276.     let nodeText = node.querySelectorAll("text");
  277.     let nodeRect = node.querySelector("rect");
  278.  
  279.     let maxWidth = 0;
  280.     nodeText.forEach((node, index) => {
  281.       console.log(index, node.getComputedTextLength());
  282.       if (node.getComputedTextLength() > maxWidth) {
  283.         maxWidth = node.getComputedTextLength();
  284.       }
  285.     });
  286.     console.log("max width", maxWidth);
  287.     if (maxWidth && nodeRect) {
  288.       // let fieldWidth = nodeText.getComputedTextLength();
  289.       nodeRect.setAttribute("width", maxWidth + 65);
  290.       nodeRect.setAttribute("x", 100 - maxWidth / 2 - 10);
  291.     }
  292.   });
  293. }
  294.  
  295. function updateNodeMenuButtonPositions() {
  296.   const nodes = document.querySelectorAll("[data-n-id]");
  297.   nodes.forEach((node) => {
  298.     const rect = node.querySelector("rect");
  299.     const menuButton = node.querySelector("[data-ctrl-n-menu-id]");
  300.     const rectWidth = rect.getBBox().width;
  301.     const rectHeight = rect.getBBox().height;
  302.     const transformValue = node.getAttribute("transform");
  303.     const [xStart, yStart] = extractLastTwoValues(transformValue);
  304.     console.log(rectWidth, rectHeight, xStart, yStart);
  305.  
  306.     // Set the transform attribute to position the button at the bottom right
  307.     const offsetX = 10; // Adjust these values as needed
  308.     const offsetY = -15; // Adjust these values as needed
  309.     const transform = `matrix(1,0,0,1,${rectWidth + offsetX},${
  310.       rectHeight + offsetY
  311.     })`;
  312.     menuButton.setAttribute("transform", transform);
  313.   });
  314. }
  315.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement