Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Vue3 drag and drop from: https://code.balkan.app/org-chart-js/draganddrop-from-another-element#JS
- const nodes = ref([
- {
- name: "IT",
- occupied: 11,
- available: 11,
- id: "4a14",
- },
- {
- name: "HR",
- occupied: 8,
- available: 12,
- id: "a58e",
- pid: "4a14",
- },
- {
- name: "Finance",
- occupied: 5,
- available: 10,
- id: "aff0",
- pid: "a58e",
- },
- ]);
- // elements to drag and drop in chart
- const departments = ref([
- {
- "name": "Marketing",
- "occupied": 7,
- "available": 14,
- "id": "2de7"
- },
- {
- "name": "Sales",
- "occupied": 12,
- "available": 8,
- "id": "8e40"
- },
- {
- "name": "Support",
- "occupied": 6,
- "available": 9,
- "id": "9cd4"
- },
- {
- "name": "R&D",
- "occupied": 4,
- "available": 6,
- "id": "2fc6"
- },
- {
- "name": "Operations",
- "occupied": 9,
- "available": 11,
- "id": "7c5a"
- },
- {
- "name": "Legal",
- "occupied": 3,
- "available": 5,
- "id": "7170"
- },
- {
- "name": "Administration",
- "occupied": 11,
- "available": 7,
- "id": "19f0"
- },
- {
- "id": "d017",
- "name": "test",
- "available": 123,
- "occupied": 321,
- },
- {
- "name": "Administration but long name",
- "available": 1,
- "occupied": 1,
- "slug": "slug602",
- "id": "Qj_uxGw"
- },
- {
- "name": "one two three four five six seven eight nine",
- "available": 1,
- "occupied": 1,
- "id": "soIv29Y"
- }
- ]);
- // chart declaration
- OrgChart.templates.customTemplate = Object.assign(
- {},
- OrgChart.templates.ana,
- {
- node: '<rect x="0" y="0" height="{h}" width="{auto}" fill="purple" stroke-width="1" stroke="#aeaeae" rx="12" ry="12"></rect>',
- link: '<path stroke-linejoin="round" stroke="#aeaeae" stroke-width="2px" fill="none" d="{rounded}" />',
- field_0:
- '<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>',
- field_1:
- '<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>',
- field_2:
- '<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>',
- link_field_0:
- '<text text-anchor="middle" fill="#aeaeae" data-width="{w}" x="0" y="0" style="font-size:10px;">{val}</text>',
- padding: [35, 20, 35, 20],
- nodeMenuButton: '<g style="cursor:pointer;" data-ctrl-n-menu-id="{id}">
- <rect x="-4" y="-10" fill="#000000" fill-opacity="0" width="22" height="22"></rect>
- <circle cx="0" cy="0" r="2" fill="#ffffff"></circle>
- <circle cx="7" cy="0" r="2" fill="#ffffff"></circle>
- <circle cx="14" cy="0" r="2" fill="#ffffff"></circle>
- </g>',
- }
- );
- const mytree = (domEl, x) => {
- OrgChart.RES.IT_IS_LONELY_HERE_LINK = "";
- OrgChart.templates.customTemplate = Object.assign(
- {},
- OrgChart.templates.ana,
- {
- node: '<rect x="0" y="0" height="{h}" width="{w}" fill="purple" stroke-width="1" stroke="#aeaeae" rx="12" ry="12"></rect>',
- link: '<path stroke-linejoin="round" stroke="#aeaeae" stroke-width="2px" fill="none" d="{rounded}" />',
- field_0:
- '<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>',
- field_1:
- '<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>',
- field_2:
- '<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>',
- link_field_0:
- '<text text-anchor="middle" fill="#aeaeae" data-width="{w}" x="0" y="0" style="font-size:10px;">{val}</text>',
- padding: [35, 20, 35, 20],
- nodeMenuButton: `<g style="cursor:pointer;" data-ctrl-n-menu-id="{id}">
- <rect x="-4" y="-10" fill="#000000" fill-opacity="0" width="22" height="22"></rect>
- <circle cx="0" cy="0" r="2" fill="#ffffff"></circle>
- <circle cx="7" cy="0" r="2" fill="#ffffff"></circle>
- <circle cx="14" cy="0" r="2" fill="#ffffff"></circle>
- </g>`,
- }
- );
- chart = new OrgChart(domEl, {
- nodes: x,
- enableSearch: false,
- nodeMouseClick: OrgChart.action.none,
- mouseScroll: OrgChart.action.zoom,
- scaleInitial: 1,
- template: "customTemplate",
- toolbar: {
- layout: true,
- zoom: true,
- fit: true,
- },
- nodeMenu: {
- remove: { text: "Remove" },
- redirect: {
- text: "Redirect",
- icon: OrgChart.icon.link(20, 20, "#039BE5"),
- // onClick: router.push(path.to.department)
- },
- details: {
- text: "Detalii",
- },
- },
- enableDragDrop: true,
- // movable: OrgChart.movable.node,
- nodeBinding: {
- field_0: "name",
- field_1: "occupied",
- field_2: "available",
- },
- });
- chart.on("redraw", function () {
- dynamicWidthNode();
- updateNodeMenuButtonPositions();
- let nodeElements = document.querySelectorAll("[data-n-id]");
- for (let i = 0; i < nodeElements.length; i++) {
- let nodeElement = nodeElements[i];
- nodeElement.ondrop = function (ev) {
- ev.preventDefault();
- let id = ev.dataTransfer.getData("id");
- const department = getDepartment(id);
- let targetNodeElement = ev.target;
- // while pentru a gasi data-n-id cand dai drop
- while (!targetNodeElement.hasAttribute("data-n-id")) {
- console.log("in while", targetNodeElement);
- targetNodeElement = targetNodeElement.parentNode;
- }
- let pid = targetNodeElement.getAttribute("data-n-id");
- if (nodeAlreadyInChart(id)) {
- // return;
- const index = getExistingNodeIndex(id);
- console.log(index, nodes.value[index]);
- // verifica daca elementul curent nu e radacina pentru a schimba parent id(radacina n-are pid)
- if (nodes.value[index].pid) {
- nodes.value[index].pid = pid;
- }
- } else {
- const newNode = {
- id: department.id,
- pid: pid,
- name: department.name,
- occupied: department.occupied,
- available: department.available,
- // movex: -120,
- // movey: -350,
- };
- nodes.value.push(newNode);
- console.log(nodes.value);
- // chart.addNode(newNode, null, true);
- }
- chart.load(nodes.value);
- // item.parentNode.removeChild(item)
- };
- nodeElement.ondragover = function (ev) {
- ev.preventDefault();
- };
- }
- });
- chart.on("add", function (sender, node) {
- chart.addNode(node);
- return false;
- });
- chart.on("click", handleNodeClick);
- chart.on("slink-click", handleSlinkClick);
- return chart;
- };
- // utility functions
- const nodeAlreadyInChart = (id) => {
- return nodes.value.find((node) => node.id === id) ? true : false;
- };
- const getExistingNodeIndex = (id) => {
- return nodes.value.findIndex((node) => node.id === id);
- };
- const getDepartment = (id) => {
- return departments.value.find((department) => department.id === id);
- };
- function extractLastTwoValues(transform) {
- const match = transform.match(/matrix\(([^)]+)\)/);
- if (match) {
- const values = match[1].split(",").map((value) => parseFloat(value.trim()));
- return values.slice(-2);
- }
- return [0, 0]; // Default value if the regex does not match
- }
- function dynamicWidthNode() {
- let allNodesRect = document.querySelectorAll("[data-n-id]");
- console.log("all nodes rect", allNodesRect);
- allNodesRect.forEach((node) => {
- let nodeText = node.querySelectorAll("text");
- let nodeRect = node.querySelector("rect");
- let maxWidth = 0;
- nodeText.forEach((node, index) => {
- console.log(index, node.getComputedTextLength());
- if (node.getComputedTextLength() > maxWidth) {
- maxWidth = node.getComputedTextLength();
- }
- });
- console.log("max width", maxWidth);
- if (maxWidth && nodeRect) {
- // let fieldWidth = nodeText.getComputedTextLength();
- nodeRect.setAttribute("width", maxWidth + 65);
- nodeRect.setAttribute("x", 100 - maxWidth / 2 - 10);
- }
- });
- }
- function updateNodeMenuButtonPositions() {
- const nodes = document.querySelectorAll("[data-n-id]");
- nodes.forEach((node) => {
- const rect = node.querySelector("rect");
- const menuButton = node.querySelector("[data-ctrl-n-menu-id]");
- const rectWidth = rect.getBBox().width;
- const rectHeight = rect.getBBox().height;
- const transformValue = node.getAttribute("transform");
- const [xStart, yStart] = extractLastTwoValues(transformValue);
- console.log(rectWidth, rectHeight, xStart, yStart);
- // Set the transform attribute to position the button at the bottom right
- const offsetX = 10; // Adjust these values as needed
- const offsetY = -15; // Adjust these values as needed
- const transform = `matrix(1,0,0,1,${rectWidth + offsetX},${
- rectHeight + offsetY
- })`;
- menuButton.setAttribute("transform", transform);
- });
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement