"use strict"; let lastCreatedNodeId = 1; let lastLargeNodeId = null; // Define node content mappings const nodeContents = { 'sendEmailNode': ` `, 'customerSignsUpNode': ` `, 'repliedToConversationNode': ` `, 'contactExitsNode': ` `, 'sendSurveyNode': ` ` }; // Function to show the popup with node information function showPopup(nodeId) { const popup = document.getElementById('popup-form'); const nodeInfoElement = document.getElementById('popup-form-fields'); const closeBtn = document.querySelector('.popup-close'); if (nodeContents[nodeId]) { nodeInfoElement.innerHTML = nodeContents[nodeId]; } else { return; } popup.classList.remove('hidden'); closeBtn.addEventListener('click', () => { popup.classList.add('hidden'); }); window.addEventListener('click', (event) => { if (event.target === popup) { popup.classList.add('hidden'); } }); } // Function to add click event listeners to nodes function addClickEventsToParentNodes() { document.querySelectorAll('.parent-node').forEach(parentNode => { parentNode.addEventListener('dblclick', (event) => { const drawflowNode = parentNode.querySelector('.node'); const nodeId = drawflowNode.getAttribute('data-node'); console.log(parentNode); if (nodeId) { showPopup(nodeId); } }); }); } // Initialize Drawflow editor var editor = new Drawflow(document.getElementById('drawflow')); editor.reroute = true; editor.line_path = 0.5; editor.start(); editor.createCurvature = function (start_x, start_y, end_x, end_y, curvature_value, type) { var center_y = ((end_y - start_y) / 2) + start_y; var default_round_radius = 10; var round_radius = Math.min(default_round_radius, Math.abs(start_x - end_x), Math.abs(start_y - end_y)); var isRight = end_x > start_x; var isDown = end_y > start_y; return `M ${start_x} ${start_y} L ${start_x} ${isDown ? center_y - round_radius : center_y + round_radius} A ${round_radius} ${round_radius} 0 0 ${isRight ^ !isDown ? 0 : 1} ${isRight ? start_x + round_radius : start_x - round_radius} ${center_y} L ${isRight ? end_x - round_radius : end_x + round_radius} ${center_y} A ${round_radius} ${round_radius} 0 0 ${isRight ^ !isDown ? 1 : 0} ${end_x} ${isDown ? center_y + round_radius : center_y - round_radius} L ${end_x} ${end_y}`; }; // Define nodes with HTML content const customerSignUp = `

Customer signs up for product updates

`; const sendEmail = `

Send email

`; const replyCheck = `

Replied to conversation?

`; const contactExits = `

Contact Exits

`; const sendSurvey = `

Send survey

`; const btnAddNote = `Thêm `; // Add nodes to the editor const customerSignsUpNode = editor.addNode('customerSignUp', 0, 1, 200, 50, 'customer-sign-up', {}, customerSignUp); const btn_add_note = editor.addNode('add-note', 1, 1, 200, 175, 'add-note', {}, btnAddNote); // const sendEmailNode = editor.addNode('sendEmail', 1, 1, 400, 175, 'send-email', {}, sendEmail.html); // const repliedToConversationNode = editor.addNode('replyCheck', 1, 2, 400, 300, 'reply-check', {}, replyCheck.html); // const contactExitsNode = editor.addNode('contactExits', 1, 0, 200, 450, 'contact-exits', {}, contactExits.html); // const sendSurveyNode = editor.addNode('sendSurvey', 1, 0, 600, 450, 'send-survey', {}, sendSurvey.html); editor.addConnection(customerSignsUpNode, btn_add_note, 'output_1', 'input_1'); // editor.addConnection(sendEmailNode, repliedToConversationNode, 'output_1', 'input_1'); // editor.addConnection(repliedToConversationNode, contactExitsNode, 'output_1', 'input_1'); // Đường "Yes" // editor.addConnection(repliedToConversationNode, sendSurveyNode, 'output_2', 'input_1'); // Đường "No" // Events! /* DRAG EVENT */ // Drag and drop functionality document.getElementById('drawflow')?.addEventListener('drop', drop); document.getElementById('drawflow')?.addEventListener('dragover', allowDrop); function allowDrop(ev) { ev.preventDefault(); } function drag(ev) { ev.dataTransfer?.setData("node", ev.target.getAttribute('data-node')); } function drop(ev) { ev.preventDefault(); const nodeName = ev.dataTransfer?.getData("node"); const x = ev.clientX - ev.target.getBoundingClientRect().left; const y = ev.clientY - ev.target.getBoundingClientRect().top; addNodeToDrawFlow(nodeName, x, y); } function addNodeToDrawFlow(element) { // Ẩn popup và xóa node hiện tại const popup = document.getElementById('popup-drawflow'); popup.classList.add('hidden'); const id_popup = popup.getAttribute('data-id'); editor.removeNodeId(id_popup); editor.updateConnectionNodes(id_popup); const pos_x = parseInt(element.getAttribute('data-pos_x')); const pos_y = parseInt(element.getAttribute('data-pos_y')); const nodeName = element.getAttribute('data-name'); const output = parseInt(element.getAttribute('data-out')); const input = parseInt(element.getAttribute('data-input')); const className = element.getAttribute('data-class'); const parent = element.getAttribute('data-parent'); const nodeHtml = document.querySelector(`.drag-drawflow[data-name="${nodeName}"]`); const contenthtml = nodeHtml.innerHTML; const newNodeId = editor.addNode(nodeName, input, output, pos_x, pos_y, className, {}, contenthtml); // Kết nối node mới với node cuối cùng nếu tồn tại if (lastLargeNodeId) { if (nodeName === 'sendSurvey') { editor.addConnection(lastLargeNodeId, newNodeId, 'output_2', 'input_1'); // Kết nối với output_2 của sendSurvey addLabelToConnection(lastLargeNodeId, newNodeId, 'No', 2); } else { editor.addConnection(lastLargeNodeId, newNodeId, 'output_1', 'input_1'); // Kết nối với output_1 của node trước đó addLabelToConnection(lastLargeNodeId, newNodeId, 'Yes', 1); } } else if (lastCreatedNodeId) { editor.addConnection(lastCreatedNodeId, newNodeId, 'output_1', 'input_1'); // Kết nối với output_1 của node trước đó } // Cập nhật node cuối cùng được tạo if (output === 2) { // Lưu node lớn (có Yes/No) lastLargeNodeId = newNodeId; } else { // Xóa lưu trữ khi không phải node lớn lastCreatedNodeId = newNodeId; } // Loại bỏ nhãn dán cũ nếu có if (nodeName === 'sendSurvey' || nodeName === 'contactExits') { const boxLabel = document.querySelector(`.connection-label`); if (boxLabel) { boxLabel.remove(); } } // Thêm nút "Add Note" nếu cần const new_pos_y = pos_y + 130; if (output === 2) { const btn_add_yes = editor.addNode('add-note', 1, 0, 25, 450, 'add-note', {}, btnAddNote); const btn_add_no = editor.addNode('add-note', 1, 0, 400, 450, 'add-note', {}, btnAddNote); editor.addConnection(newNodeId, btn_add_yes, 'output_1', 'input_1'); editor.addConnection(newNodeId, btn_add_no, 'output_2', 'input_1'); addLabelToConnection(newNodeId, btn_add_yes, 'Yes', 1); addLabelToConnection(newNodeId, btn_add_no, 'No', 2); } else if (output === 0 && parent === 'replyCheck') { // Do nothing in this case } else { const btn_add_note = editor.addNode('add-note', input, output, pos_x, new_pos_y, 'add-note', {}, btnAddNote); editor.addConnection(newNodeId, btn_add_note, 'output_1', 'input_1'); } } function ClickAddNote() { const btn = document.querySelector('.drawflow-node.add-note'); btn.addEventListener('dblclick', (event) => { const popup = document.getElementById('popup-drawflow'); popup.classList.remove('hidden'); // Lấy thuộc tính CSS của phần tử const computedStyle = window.getComputedStyle(btn); const top = computedStyle.getPropertyValue('top'); const left = computedStyle.getPropertyValue('left'); const new_left = parseFloat(left) + 690; popup.style.top = top; popup.style.left = `${new_left}px`; const id = btn.getAttribute('id'); popup.setAttribute('data-id', id); }); } // Function to add labels to connections function addLabelToConnection(nodeFrom, nodeTo, labelText, outputIndex) { // Lấy phần tử SVG và đường kẻ kết nối const connectionElement = document.querySelector(`.connection.node_in_node-${nodeTo}.node_out_node-${nodeFrom}.output_${outputIndex}`); const svg = connectionElement.closest('svg'); const path = svg?.querySelector('path'); if (!path) return console.error('Path element not found in SVG'); // Tạo và thêm nhãn const label = document.createElement('div'); label.className = `connection-label`; label.id = `label-${nodeTo}`; label.textContent = labelText; document.body.appendChild(label); if (labelText === 'No') { label.classList.add('no'); } // Cập nhật vị trí nhãn const updateLabelPosition = () => { const connectionBox = connectionElement.getBoundingClientRect(); const length = path.getTotalLength(); const { x, y } = path.getPointAtLength(length / 2); const svgPoint = svg.createSVGPoint(); svgPoint.x = x; svgPoint.y = y; const screenPoint = svgPoint.matrixTransform(svg.getScreenCTM()); label.style.position = 'absolute'; label.style.left = `${screenPoint.x}px`; label.style.top = `${screenPoint.y - 12}px`; }; updateLabelPosition(); editor.on('zoom', updateLabelPosition); window.addEventListener('resize', updateLabelPosition); window.addEventListener('mouseup', updateLabelPosition); window.addEventListener('mousemove', updateLabelPosition); } // Drawflow Events editor.on('connectionCreated', function (connection) { console.log('Connection created', connection); }); editor.on('connectionRemoved', function (connection) { console.log('Connection removed', connection); }); editor.on('nodeSelected', function (connection) { // Add click events to nodes addClickEventsToParentNodes(); }); const btn_clear = document.getElementById('btn-clear'); btn_clear.addEventListener('click', () => { const connectionLabels = document.querySelectorAll('.connection-label'); connectionLabels.forEach(label => { label.classList.add('hide'); }); });