Closed tarasowski closed 2 years ago
Hi! Have you made any changes to the library?
What does the event that displays "updateState" do? It seems that after it breaks.
Thanks for your reply!
I haven't made any changes to the lib.
Actually I'm listening to the following events and update internal state (and save the data to my db):
editor.on("nodeCreated", async () => await saveData())
editor.on("nodeRemoved", async () => await saveData())
editor.on("nodeMoved", async () => await saveData())
editor.on("connectionCreated", async () => await saveData())
editor.on("connectionRemoved", async () => await saveData())
here is another example. I have loaded the data from my db. Now I'm trying to move the card.
How do you add nodes? I see in your picture that it is different from normal.
I'm using the following function:
const handleAddObjective = e => {
const objective = e.detail
const objectiveId = e.detail.objectiveId
editor.addNode(
objective.objectiveId, 1, 1, 300, 200, "github", {},
createHTML(objective.objectiveId));
}
{
"drawflow": {
"Home": {
"data": {
"1": {
"typenode": false,
"outputs": {
"output_1": {
"connections": []
}
},
"pos_y": 270,
"pos_x": 526.4285714285714,
"data": {},
"inputs": {
"input_1": {
"connections": []
}
},
"name": "78ca9029-96d1-4624-ab3a-f63bfdfbad4c",
"html": "\n <div class=\"\">\n<!-- ARCHIVED -->\n <h5 class=\"text-tint-300 font-bold text-base mb-2\">Create content repository for marketing</h5>\n <p class=\"text-tint-600 mb-2\">Updated 2022-05-26</p>\n <ul class=\"\">\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Dimitri Test3\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>DT</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Run 5 two-hour workshops for max. 10 employees on how to use / add content to the repository\">Run 5 two-hour workshops for max. 10 employees on ...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 38%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">38%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Test User\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>TU</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Establish a dashboard to measure the number of new ideas and run a contest among our employees\">Establish a dashboard to measure the number of new...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 49%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">49%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Dimitri Test3\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>DT</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Create a trello board as a content repository and submit 100 potential content ideas\">Create a trello board as a content repository and ...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 0%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">0%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul>\n </div>\n ",
"id": 2,
"class": "github"
},
"2": {
"typenode": false,
"outputs": {
"output_1": {
"connections": []
}
},
"pos_y": -43.42857142857143,
"pos_x": 920.4285714285714,
"data": {},
"inputs": {
"input_1": {
"connections": []
}
},
"name": "850d5c6a-aef6-4ce2-9e59-a0f127b0b01f",
"html": "\n <div class=\"\">\n<!-- ARCHIVED -->\n <h5 class=\"text-tint-300 font-bold text-base mb-2\">Increase company brand awareness and engagement</h5>\n <p class=\"text-tint-600 mb-2\">Updated 2022-05-26</p>\n <ul class=\"\">\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Dimitri Test3\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>DT</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Create 1 content calendar and assign team members\">Create 1 content calendar and assign team members</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 50%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">50%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"undefined undefined\" class='rounded-full bg-tint-800 w-8 h-8'></button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Design 5 TikTok campaigns and run brand awareness surveys\">Design 5 TikTok campaigns and run brand awareness ...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 20%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">20%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Test User\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>TU</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Increase media spendings by 50% on Facebook in Q3\">Increase media spendings by 50% on Facebook in Q3</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 30%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">30%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul>\n </div>\n ",
"id": 4,
"class": "github"
},
"3": {
"typenode": false,
"outputs": {
"output_1": {
"connections": []
}
},
"pos_y": 592.4285714285714,
"pos_x": 284.42857142857144,
"data": {},
"inputs": {
"input_1": {
"connections": []
}
},
"name": "9ec383eb-92b0-4320-aee2-c9b6ac33038d",
"html": "\n <div class=\"\">\n<!-- ARCHIVED -->\n <h5 class=\"text-tint-300 font-bold text-base mb-2\">Develop a plan to introduce state of the art technology</h5>\n <p class=\"text-tint-600 mb-2\">Updated 2022-05-24</p>\n <ul class=\"\">\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"undefined undefined\" class='rounded-full bg-tint-800 w-8 h-8'></button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Create strategy, vision, roadmap and digital product portfolio\">Create strategy, vision, roadmap and digital produ...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 0%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">0%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"undefined undefined\" class='rounded-full bg-tint-800 w-8 h-8'></button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Manage to launch 3 POCs to show improvement to the current state\">Manage to launch 3 POCs to show improvement to the...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 0%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">0%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"undefined undefined\" class='rounded-full bg-tint-800 w-8 h-8'></button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Hold strategy workshops across 5 divisions\">Hold strategy workshops across 5 divisions</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 0%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">0%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul>\n </div>\n ",
"id": 6,
"class": "github"
}
}
}
}
}
{
"drawflow": {
"Home": {
"data": {
"1": {
"id": 1,
"name": "9ec383eb-92b0-4320-aee2-c9b6ac33038d",
"data": {},
"class": "github",
"html": "\n <div class=\"\">\n <h5 class=\"text-tint-300 font-bold text-base mb-2\">Develop a plan to introduce state of the art technology</h5>\n <p class=\"text-tint-600 mb-2\">Updated 2022-05-24</p>\n <ul class=\"\">\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"undefined undefined\" class='rounded-full bg-tint-800 w-8 h-8'></button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Create strategy, vision, roadmap and digital product portfolio\">Create strategy, vision, roadmap and digital produ...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 0%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">0%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"undefined undefined\" class='rounded-full bg-tint-800 w-8 h-8'></button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Manage to launch 3 POCs to show improvement to the current state\">Manage to launch 3 POCs to show improvement to the...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 0%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">0%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"undefined undefined\" class='rounded-full bg-tint-800 w-8 h-8'></button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Hold strategy workshops across 5 divisions\">Hold strategy workshops across 5 divisions</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 0%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">0%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul>\n </div>\n ",
"typenode": false,
"inputs": {
"input_1": {
"connections": []
}
},
"outputs": {
"output_1": {
"connections": []
}
},
"pos_x": -161.42857142857142,
"pos_y": 222.42857142857142
},
"2": {
"id": 2,
"name": "78ca9029-96d1-4624-ab3a-f63bfdfbad4c",
"data": {},
"class": "github",
"html": "\n <div class=\"\">\n <h5 class=\"text-tint-300 font-bold text-base mb-2\">Create content repository for marketing</h5>\n <p class=\"text-tint-600 mb-2\">Updated 2022-05-26</p>\n <ul class=\"\">\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Dimitri Test3\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>DT</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Run 5 two-hour workshops for max. 10 employees on how to use / add content to the repository\">Run 5 two-hour workshops for max. 10 employees on ...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 38%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">38%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Test User\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>TU</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Establish a dashboard to measure the number of new ideas and run a contest among our employees\">Establish a dashboard to measure the number of new...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 49%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">49%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Dimitri Test3\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>DT</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Create a trello board as a content repository and submit 100 potential content ideas\">Create a trello board as a content repository and ...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 0%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">0%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul>\n </div>\n ",
"typenode": false,
"inputs": {
"input_1": {
"connections": []
}
},
"outputs": {
"output_1": {
"connections": []
}
},
"pos_x": 481,
"pos_y": 538
},
"3": {
"id": 3,
"name": "850d5c6a-aef6-4ce2-9e59-a0f127b0b01f",
"data": {},
"class": "github",
"html": "\n <div class=\"\">\n <h5 class=\"text-tint-300 font-bold text-base mb-2\">Increase company brand awareness and engagement</h5>\n <p class=\"text-tint-600 mb-2\">Updated 2022-05-26</p>\n <ul class=\"\">\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Dimitri Test3\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>DT</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Create 1 content calendar and assign team members\">Create 1 content calendar and assign team members</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 50%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">50%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"undefined undefined\" class='rounded-full bg-tint-800 w-8 h-8'></button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Design 5 TikTok campaigns and run brand awareness surveys\">Design 5 TikTok campaigns and run brand awareness ...</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 20%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">20%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul class=\"\">\n <li class=\"flex items-center gap-3 mb-3\">\n <button title=\"Test User\" class='text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500'>TU</button>\n <div>\n <p class=\"text-tint-300 text-sm\" title=\"Increase media spendings by 50% on Facebook in Q3\">Increase media spendings by 50% on Facebook in Q3</p>\n <div class=\"flex gap-4 items-center\">\n <div class=\"bg-neutural-000 min-h-[12px] min-w-[12rem]\">\n <div style=\"width: 30%\" class=\"bg-accent-green min-h-[12px]\"></div>\n </div>\n <p class=\"\">30%</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n \n <ul>\n </div>\n ",
"typenode": false,
"inputs": {
"input_1": {
"connections": []
}
},
"outputs": {
"output_1": {
"connections": []
}
},
"pos_x": 860.1428571428571,
"pos_y": 247.85714285714286
}
}
}
}
}
You don't have to use the editor.load
function.
You have to use the editor.import(JSON)
function.
editor.start();
editor.import(jsonfile);
I see you are using uuid. If you are interested you can use:
editor.useuuid = true;
Yes, I'm using editor.import(), was a mistake above. I'm doing it exactly as you described above
editor.start()
editor.import(json)
Loading works great etc. The error occurs on some nodes, usually after deletion of other nodes.
The problem is the id:2 It would have to be a number 1
Could you show your code?
Yes, sure.
<script>
export let boards
export let alignment
import Drawflow from "drawflow";
import { onMount, onDestroy } from "svelte";
import "drawflow/dist/drawflow.min.css";
import Magnify from "svelte-material-icons/Magnify.svelte";
import SearchModal from "./SearchModal.svelte"
import {matchSorter} from 'match-sorter'
import { error } from "../error/state.js"
import { updateAlignment } from "../../graphql/mutations.js"
import { callAPI } from "../../io.js"
let showSearch = false
let container;
let editor;
let loaded = false
const flatBoards = boards => {
let objectives = []
boards.forEach(board =>
board.views.items.forEach(view =>
objectives.push(view.objectives.items)
))
return objectives.flat()
}
const calculateProgress = data => {
try {
const val = ((data.currentValue - data.startValue) * 100) / (data.targetValue - data.startValue)
if (val === Infinity) {
return 0
} else {
return val.toFixed(0)
}
} catch(e) {}
}
const generateOwnerInitials = (user) => {
try {
if (user !== undefined) {
return ((user || {}).firstName || "").charAt(0)
+ ((user || {}).lastName || "").charAt(0)
} else {
return undefined
}
} catch(e) {
console.log(e)
return ""
}
}
const keyResultHTML = keyResult => {
const name = keyResult.name
const owners = keyResult?.owners?.items?.map(v => v.owner)
const owner = owners && head(owners)
const initials = owner && generateOwnerInitials(owner)
const percentage = calculateProgress(keyResult)
return `
<ul class="">
<li class="flex items-center gap-3 mb-3">
<button title="${owner?.firstName} ${owner?.lastName}" class='${initials
? "text-white w-8 h-8 rounded-full flex items-center justify-center bg-tint-800 bg-gradient-to-r from-cyan-500 to-blue-500"
: "rounded-full bg-tint-800 w-8 h-8"}'>${initials ? initials : ""}</button>
<div>
<p class="text-tint-300 text-sm" title="${name}">${name.substring(0, 50)}${name.length >50 ? "..." : ""}</p>
<div class="flex gap-4 items-center">
<div class="bg-neutural-000 min-h-[12px] min-w-[12rem]">
<div style="width: ${percentage}%" class="bg-accent-green min-h-[12px]"></div>
</div>
<p class="">${percentage}%</p>
</div>
</div>
</div>
</div>
</div>
</li>
</ul>
`
}
const createHTMLLoad = objective => {
return objective.html
const objectiveId = objective.name
const data = objective.data
const o = flatBoards(boards)
const obj = o.filter(obj => obj.id === objectiveId)
if (obj.length > 0) {
const first = head(obj)
const updatedAt = first?.keyResults?.items?.map(kr => kr.updatedAt)
const sorted = updatedAt && head(sortByDate(updatedAt))
const lastUpdate = sorted && sorted.substring(0, 10)
return `
<div class="">
<!-- ARCHIVED -->
<h5 class="text-tint-300 font-bold text-base mb-2">${first.name}</h5>
<p class="text-tint-600 mb-2">Updated ${lastUpdate}</p>
<ul class="">
${first.keyResults.items.map(keyResultHTML).join("")}
<ul>
</div>
`
} else {
const archived = `
<div class="text-right">
<span title="The current objective is archvied or deleted" class="w-4 h-4 bg-accent-rose text-white p-1 rounded-full font-bold px-2">Archived</span>
</div>
`
return objective.html.replace("<!-- ARCHIVED -->", archived)
}
}
const updateNodes = data => {
const modified = Object.keys(data).map(key => ({
...data[key],
html: createHTMLLoad(data[key])}))
const reduced = modified.reduce((a, v, i) => ({ ...a, [i+1]: v}), {})
return reduced
}
const loadJSON = (alignment) => {
let json = JSON.parse(alignment.data)
try {
let data = (((json || {}).drawflow || {}).Home || {}).data
json.drawflow.Home.data = updateNodes(data)
editor && editor.import(json)
loaded = true
} catch(e) {
console.log("error message", e.message)
$error = e.message
}
}
const saveData = async (e, d) => {
const data = editor.export()
alignment.data = JSON.stringify(data)
try {
return await callAPI(updateAlignment, {input: {
organizationId: window.user.profile,
id: alignment.id,
data: JSON.stringify(data)
}})
} catch(e) {
console.log(e.message)
$error = e.message
}
}
onMount(async () => {
try {
editor = new Drawflow(container);
editor.reroute = true;
editor.start();
editor.zoom_max = 1.6;
editor.zoom_min = 0.5;
editor.zoom_value = 0.1;
editor.zoom = alignment.lastZoomValue || 0.7
editor.force_first_input = true;
editor.zoom_refresh()
editor.on("nodeCreated", async () => await saveData())
editor.on("nodeRemoved", async () => await saveData())
editor.on("nodeMoved", async () => await saveData())
editor.on("connectionCreated", async () => await saveData())
editor.on("connectionRemoved", async () => await saveData())
} catch(e) {
console.log(e.message)
}
});
$: alignment.data && boards.length > 0 && editor && !loaded && loadJSON(alignment)
const handleZoomOut = () => {
editor.zoom_out();
alignment.lastZoomValue = editor.zoom_last_value
};
const handleZoomIn = () => {
editor.zoom_in();
alignment.lastZoomValue = editor.zoom_last_value
};
const sortByDate = xs =>
xs.sort((a, b) => new Date(b) - new Date(b))
const head = xs => {
try {
return xs[0]
} catch(e) {
return null
}
}
const createHTML = objectiveId => {
const o = flatBoards(boards)
const obj = o.filter(obj => obj.id === objectiveId)
if (obj.length > 0) {
const first = head(obj)
const updatedAt = first?.keyResults?.items?.map(kr => kr.updatedAt)
const sorted = updatedAt && head(sortByDate(updatedAt))
const lastUpdate = sorted && sorted.substring(0, 10)
console.log("lastUpdate", lastUpdate)
return `
<div class="">
<h5 class="text-tint-300 font-bold text-base mb-2">${first.name}</h5>
<p class="text-tint-600 mb-2">Updated ${lastUpdate}</p>
<ul class="">
${first.keyResults.items.map(keyResultHTML).join("")}
<ul>
</div>
`
} else {
console.log("return archived")
}
}
const handleAddObjective = e => {
const objective = e.detail
const objectiveId = e.detail.objectiveId
editor.addNode(
objective.objectiveId, 1, 1, 300, 200, "github", {},
createHTML(objective.objectiveId));
}
const handleLoad = () => {
console.log(editor.drawflow)
}
</script>
{#if showSearch}
<SearchModal bind:showSearch {boards} on:add-objective={handleAddObjective} />
{/if}
<div class="drawflow max-h-[90%]" bind:this="{container}"></div>
<div
class="absolute bottom-10 right-10 text-base text-tint-300 shadow-zoombtn right-0 py-2.5 px-6 flex items-center gap-5 justify-center bg-white rounded s-o2zHGApCCFOx"
>
<button on:click="{handleZoomOut}" class="zoom s-o2zHGApCCFOx" id="zoomMinus">
<svg width="1em" height="1em" viewBox="0 0 24 24">
<path d="M19,13H5V11H19V13Z" fill="currentColor"></path></svg
><!--<Minus>-->
</button>
<p id="zoomVal" class="s-o2zHGApCCFOx">{(alignment?.lastZoomValue ? alignment.lastZoomValue * 100 : 70).toFixed(0)}%</p>
<button on:click="{handleZoomIn}" class="zoom s-o2zHGApCCFOx" id="zoomPlus">
<svg width="1em" height="1em" viewBox="0 0 24 24">
<path
d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z"
fill="currentColor"
></path></svg
><!--<Plus>-->
</button>
</div>
<div
class="absolute bottom-10 right-[250px] text-base text-tint-300 shadow-zoombtn right-0 py-2.5 px-6 flex items-center gap-5 justify-center bg-white rounded s-o2zHGApCCFOx"
>
<button on:click={handleLoad}>Print State</button>
<button on:click={saveData}>Save State</button>
<button on:click={() => showSearch = !showSearch} class="flex gap-2 w-[150px] text-tint-500 items-center" type="" placeholder="Quick search...">
<!-- Tailwind style search for key results / objectives -->
<Magnify width={20} height={20} />
Quick search...
</button>
</div>
<style>
#drawflow {
position: relative;
border: 1px solid green;
}
:global(.drawflow) {
user-select: none;
}
:global(.drawflow_content_node) {
/*border: 1px solid green !important;*/
min-width: 400px;
}
:global(.drawflow_content_node > * > .title ) {
font-family: 'Roboto';
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 121.19%;
color: #5E6370;
margin-bottom: 0.5rem;
}
:global(.drawflow_content_node > * > .updated ) {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 121.19%;
color: #A3A6AD;
margin-bottom: 0.5rem;
}
:global(.drawflow .drawflow-node) {
background: white !important;
border: none !important;
/*border: 1px solid red !important;*/
min-width: 450px;
background: #FFFFFF;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.15);
border-radius: 3px;
}
:global(.drawflow .drawflow-node .input) {
width: 1.5rem;
height: 1.5rem;
background: #FFFFFF;
/* Primary/Tint/800 */
border: 2px solid #E8E9EB;
margin-left: 0px;
}
:global(.drawflow .drawflow-node .output) {
background: #FFFFFF;
/* Primary/Tint/800 */
border: 2px solid #E8E9EB;
width: 1.5rem;
height: 1.5rem;
margin-left: 0px;
}
:global(.bar-zoom) {
float: right;
position: absolute;
bottom: 10px;
right: 10px;
display: flex;
font-size: 24px;
color: white;
padding: 5px 10px;
background: #555555;
border-radius: 4px;
border-right: 1px solid var(--border-color);
z-index: 5;
}
:global(.bar-zoom svg) {
cursor: pointer;
padding-left: 10px;
}
:global(.bar-zoom svg:nth-child(1)) {
padding-left: 0px;
}
:global(.drawflow-delete) {
background-color: white;
border: 1px solid #D1D2D6;
color: #5E6370;
text-align: center;
font-size: 16px;
}
:global(.drawflow .connection .arrow) {
transform: translate(-10005px,-9999px);
}
</style>
I haven't played Svelte. Is the "alignment" variable reactive?
Could it be that every time "saveData" is called, the flow is being imported again? Remove all events to discard:
editor.on("nodeCreated", async () => await saveData())
editor.on("nodeRemoved", async () => await saveData())
editor.on("nodeMoved", async () => await saveData())
editor.on("connectionCreated", async () => await saveData())
editor.on("connectionRemoved", async () => await saveData())
You can put a console.log in the "loadJSON" function like so:
json.drawflow.Home.data = updateNodes(data)
console.log(json);
editor && editor.import(json)
I think I have figured out the issue.
It looks like the id of the node has to be the same as the key on the data object.
Once the node gets deleted, the node id and the key on the data object doesn't match anymore.
This is what actually causing the issue, it can't find the node anymore after loading. So I changed the updateNode fn, to match the key on the data object with the node id. It is working now!
const updateNodes = data =>
Object.keys(data).map(key => ({
...data[key],
html: createHTMLLoad(data[key])}))
.reduce((a, v, i) => ({ ...a, [v.id]: v}), {})
Thank you very much for your help! Dimi
Hey Jero,
i'm having issues integrating drawflow into svelte.
Actually everything is working so far, but once the node is deleted (with connections), some strange behavior happens. Once the error occurs, I can't delete the node and the connections anymore.