computer-scienceangular-roadmapbackend-roadmapblockchain-roadmapdba-roadmapdeveloper-roadmapdevops-roadmapfrontend-roadmapgo-roadmaphactoberfestjava-roadmapjavascript-roadmapnodejs-roadmappython-roadmapqa-roadmapreact-roadmaproadmapstudy-planvue-roadmapweb3-roadmap
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
3.2 KiB
136 lines
3.2 KiB
import { wireframeJSONToSVG } from 'roadmap-renderer'; |
|
|
|
export class Renderer { |
|
constructor() { |
|
this.resourceId = ''; |
|
this.resourceType = ''; |
|
this.jsonUrl = ''; |
|
this.loaderNode = null; |
|
|
|
this.containerId = 'resource-svg-wrap'; |
|
this.loaderId = 'resource-loader'; |
|
|
|
this.init = this.init.bind(this); |
|
this.onDOMLoaded = this.onDOMLoaded.bind(this); |
|
this.jsonToSvg = this.jsonToSvg.bind(this); |
|
this.handleSvgClick = this.handleSvgClick.bind(this); |
|
this.prepareConfig = this.prepareConfig.bind(this); |
|
} |
|
|
|
get loaderEl() { |
|
return document.getElementById(this.loaderId); |
|
} |
|
|
|
get containerEl() { |
|
return document.getElementById(this.containerId); |
|
} |
|
|
|
prepareConfig() { |
|
if (!this.containerEl) { |
|
return false; |
|
} |
|
|
|
// Clone it so we can use it later |
|
this.loaderNode = this.loaderEl.cloneNode(); |
|
const dataset = this.containerEl.dataset; |
|
|
|
this.resourceType = dataset.resourceType; |
|
this.resourceId = dataset.resourceId; |
|
this.jsonUrl = dataset.jsonUrl; |
|
|
|
return true; |
|
} |
|
|
|
/** |
|
* @param { string } jsonUrl |
|
* @returns {Promise<SVGElement>} |
|
*/ |
|
jsonToSvg(jsonUrl) { |
|
if (!jsonUrl) { |
|
console.error('jsonUrl not defined in frontmatter'); |
|
return null; |
|
} |
|
|
|
this.containerEl.replaceChildren(this.loaderNode); |
|
|
|
return fetch(jsonUrl) |
|
.then((res) => { |
|
return res.json(); |
|
}) |
|
.then((json) => { |
|
return wireframeJSONToSVG(json, { |
|
fontURL: '/fonts/balsamiq.woff2', |
|
}); |
|
}) |
|
.then((svg) => { |
|
this.containerEl.replaceChildren(svg); |
|
}) |
|
.catch((error) => { |
|
const message = ` |
|
<strong>There was an error.</strong><br> |
|
|
|
Try loading the page again. or submit an issue on GitHub with following:<br><br> |
|
|
|
${error.message} <br /> ${error.stack} |
|
`; |
|
|
|
this.containerEl.innerHTML = `<div class="error py-5 text-center text-red-600 mx-auto">${message}</div>`; |
|
}); |
|
} |
|
|
|
onDOMLoaded() { |
|
if (!this.prepareConfig()) { |
|
return; |
|
} |
|
|
|
this.jsonToSvg(this.jsonUrl); |
|
} |
|
|
|
handleSvgClick(e) { |
|
const targetGroup = e.target.closest('g') || {}; |
|
const groupId = targetGroup.dataset ? targetGroup.dataset.groupId : ''; |
|
if (!groupId) { |
|
return; |
|
} |
|
|
|
e.stopImmediatePropagation(); |
|
|
|
if (/^ext_link/.test(groupId)) { |
|
window.open(`https://${groupId.replace('ext_link:', '')}`); |
|
return; |
|
} |
|
|
|
if (/^check:/.test(groupId)) { |
|
window.dispatchEvent( |
|
new CustomEvent(`${this.resourceType}.topic.toggle`, { |
|
detail: { |
|
topicId: groupId.replace('check:', ''), |
|
resourceType: this.resourceType, |
|
resourceId: this.resourceId, |
|
}, |
|
}) |
|
); |
|
return; |
|
} |
|
|
|
// Remove sorting prefix from groupId |
|
const normalizedGroupId = groupId.replace(/^\d+-/, ''); |
|
|
|
window.dispatchEvent( |
|
new CustomEvent(`${this.resourceType}.topic.click`, { |
|
detail: { |
|
topicId: normalizedGroupId, |
|
resourceId: this.resourceId, |
|
}, |
|
}) |
|
); |
|
} |
|
|
|
init() { |
|
window.addEventListener('DOMContentLoaded', this.onDOMLoaded); |
|
window.addEventListener('click', this.handleSvgClick); |
|
} |
|
} |
|
|
|
const renderer = new Renderer(); |
|
renderer.init();
|
|
|