feat: display tag in graph view (#466)
* feat: tags in graph view * fix: revert changing graph forces * fix: run prettier
This commit is contained in:
parent
0a6e9c3f86
commit
4b177ed03e
@ -13,6 +13,8 @@ export interface D3Config {
|
|||||||
linkDistance: number
|
linkDistance: number
|
||||||
fontSize: number
|
fontSize: number
|
||||||
opacityScale: number
|
opacityScale: number
|
||||||
|
removeTags: string[]
|
||||||
|
showTags: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GraphOptions {
|
interface GraphOptions {
|
||||||
@ -31,6 +33,8 @@ const defaultOptions: GraphOptions = {
|
|||||||
linkDistance: 30,
|
linkDistance: 30,
|
||||||
fontSize: 0.6,
|
fontSize: 0.6,
|
||||||
opacityScale: 1,
|
opacityScale: 1,
|
||||||
|
showTags: true,
|
||||||
|
removeTags: [],
|
||||||
},
|
},
|
||||||
globalGraph: {
|
globalGraph: {
|
||||||
drag: true,
|
drag: true,
|
||||||
@ -42,6 +46,8 @@ const defaultOptions: GraphOptions = {
|
|||||||
linkDistance: 30,
|
linkDistance: 30,
|
||||||
fontSize: 0.6,
|
fontSize: 0.6,
|
||||||
opacityScale: 1,
|
opacityScale: 1,
|
||||||
|
showTags: true,
|
||||||
|
removeTags: [],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,20 +42,38 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
|
|||||||
linkDistance,
|
linkDistance,
|
||||||
fontSize,
|
fontSize,
|
||||||
opacityScale,
|
opacityScale,
|
||||||
|
removeTags,
|
||||||
|
showTags,
|
||||||
} = JSON.parse(graph.dataset["cfg"]!)
|
} = JSON.parse(graph.dataset["cfg"]!)
|
||||||
|
|
||||||
const data = await fetchData
|
const data = await fetchData
|
||||||
|
|
||||||
const links: LinkData[] = []
|
const links: LinkData[] = []
|
||||||
|
const tags: SimpleSlug[] = []
|
||||||
|
|
||||||
const validLinks = new Set(Object.keys(data).map((slug) => simplifySlug(slug as FullSlug)))
|
const validLinks = new Set(Object.keys(data).map((slug) => simplifySlug(slug as FullSlug)))
|
||||||
|
|
||||||
for (const [src, details] of Object.entries<ContentDetails>(data)) {
|
for (const [src, details] of Object.entries<ContentDetails>(data)) {
|
||||||
const source = simplifySlug(src as FullSlug)
|
const source = simplifySlug(src as FullSlug)
|
||||||
const outgoing = details.links ?? []
|
const outgoing = details.links ?? []
|
||||||
|
|
||||||
for (const dest of outgoing) {
|
for (const dest of outgoing) {
|
||||||
if (validLinks.has(dest)) {
|
if (validLinks.has(dest)) {
|
||||||
links.push({ source, target: dest })
|
links.push({ source, target: dest })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showTags) {
|
||||||
|
const localTags = details.tags
|
||||||
|
.filter((tag) => !removeTags.includes(tag))
|
||||||
|
.map((tag) => simplifySlug(("tags/" + tag) as FullSlug))
|
||||||
|
|
||||||
|
tags.push(...localTags.filter((tag) => !tags.includes(tag)))
|
||||||
|
|
||||||
|
for (const tag of localTags) {
|
||||||
|
links.push({ source, target: tag })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const neighbourhood = new Set<SimpleSlug>()
|
const neighbourhood = new Set<SimpleSlug>()
|
||||||
@ -76,14 +94,18 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Object.keys(data).forEach((id) => neighbourhood.add(simplifySlug(id as FullSlug)))
|
Object.keys(data).forEach((id) => neighbourhood.add(simplifySlug(id as FullSlug)))
|
||||||
|
if (showTags) tags.forEach((tag) => neighbourhood.add(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
const graphData: { nodes: NodeData[]; links: LinkData[] } = {
|
const graphData: { nodes: NodeData[]; links: LinkData[] } = {
|
||||||
nodes: [...neighbourhood].map((url) => ({
|
nodes: [...neighbourhood].map((url) => {
|
||||||
|
const text = url.startsWith("tags/") ? "#" + url.substring(5) : data[url]?.title ?? url
|
||||||
|
return {
|
||||||
id: url,
|
id: url,
|
||||||
text: data[url]?.title ?? url,
|
text: text,
|
||||||
tags: data[url]?.tags ?? [],
|
tags: data[url]?.tags ?? [],
|
||||||
})),
|
}
|
||||||
|
}),
|
||||||
links: links.filter((l) => neighbourhood.has(l.source) && neighbourhood.has(l.target)),
|
links: links.filter((l) => neighbourhood.has(l.source) && neighbourhood.has(l.target)),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +149,7 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
|
|||||||
const isCurrent = d.id === slug
|
const isCurrent = d.id === slug
|
||||||
if (isCurrent) {
|
if (isCurrent) {
|
||||||
return "var(--secondary)"
|
return "var(--secondary)"
|
||||||
} else if (visited.has(d.id)) {
|
} else if (visited.has(d.id) || d.id.startsWith("tags/")) {
|
||||||
return "var(--tertiary)"
|
return "var(--tertiary)"
|
||||||
} else {
|
} else {
|
||||||
return "var(--gray)"
|
return "var(--gray)"
|
||||||
@ -231,11 +253,7 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
|
|||||||
.attr("dx", 0)
|
.attr("dx", 0)
|
||||||
.attr("dy", (d) => -nodeRadius(d) + "px")
|
.attr("dy", (d) => -nodeRadius(d) + "px")
|
||||||
.attr("text-anchor", "middle")
|
.attr("text-anchor", "middle")
|
||||||
.text(
|
.text((d) => d.text)
|
||||||
(d) =>
|
|
||||||
data[d.id]?.title ||
|
|
||||||
(d.id.charAt(0).toUpperCase() + d.id.slice(1, d.id.length - 1)).replace("-", " "),
|
|
||||||
)
|
|
||||||
.style("opacity", (opacityScale - 1) / 3.75)
|
.style("opacity", (opacityScale - 1) / 3.75)
|
||||||
.style("pointer-events", "none")
|
.style("pointer-events", "none")
|
||||||
.style("font-size", fontSize + "em")
|
.style("font-size", fontSize + "em")
|
||||||
|
Loading…
Reference in New Issue
Block a user