TKG-visualiser / temporal-graph-timestep.js
MikeDoes's picture
Upload 3 files
0cdd242 verified
raw
history blame
4.66 kB
/* ===========================================================
temporal-graph-timestep.js
=========================================================== */
class TemporalGraphTimestep extends HTMLElement {
constructor() {
super();
this._knowledge_graph = [];
this._timestep = 0;
this._cursorIndex = -1;
}
connectedCallback() {
this.className =
'mermaid w-[100%] h-[100%] flex items-center justify-center';
}
/** Accepts { knowledge_graph, timestep, cursorIndex } */
set data(v) {
this._knowledge_graph = v.knowledge_graph;
this._timestep = v.timestep;
this._cursorIndex = 'cursorIndex' in v ? v.cursorIndex : -1;
this.render();
}
generateMermaidDiagram() {
/* ---------- Mermaid init block: 36px with !important ---------- */
const initCSS = `%%{init:{
"themeCSS": ".node text{font-size:36px !important;} .edgeLabel text{font-size:36px !important;}"
}}%%`;
const first = this._knowledge_graph.find(r => r[3] === 0);
const title = first ? first[2] : 'Temporal Graph';
/* ---------- preprocess ---------- */
const unique = [];
const times = {};
const seq = {};
const firstOcc = {};
const allNodes = new Set();
this._knowledge_graph.forEach(([s,r,t,ts])=>{
const k=`${s}|${r}|${t}`;
allNodes.add(s); allNodes.add(t);
if(!times[k]){unique.push({s,r,t});times[k]=[];}
times[k].push(ts);
if(!seq[ts]) seq[ts]={cnt:1};
if(!seq[ts][k]){
seq[ts][k]=seq[ts].cnt++;
if(!firstOcc[k]) firstOcc[k]={ts,seq:seq[ts][k]};
}
});
const global=unique.map(o=>{
const k=`${o.s}|${o.r}|${o.t}`;return {...o,...firstOcc[k]};
}).sort((a,b)=>a.ts===b.ts? a.seq-b.seq : a.ts-b.ts);
// **FIXED HERE**: The bug from before was a typo in this line.
const orderIdx={}; global.forEach((o,i)=>orderIdx[`${o.s}|${o.r}|${o.t}`]=i);
/* ---------- build diagram ---------- */
let code = `${initCSS}
---
title: ${title}
---
graph LR
subgraph " "
direction LR
`;
let linkStyle='', nodeStyle='', linkIdx=0;
const activeNodes=new Set();
unique.forEach(({s,r,t})=>{
const k=`${s}|${r}|${t}`;
// **RESTORED**: Using original logic for node IDs.
const sId=s.replace(/\s+/g,'');
const tId=t.replace(/\s+/g,'');
const active=(this._timestep==='summary')||times[k].includes(this._timestep);
let lb=r, sq, stp;
if(active){
if(this._timestep==='summary'){sq=firstOcc[k].seq;stp=firstOcc[k].ts+1;}
else{sq=seq[this._timestep][k];stp=this._timestep+1;}
lb=`${stp}.${sq} ${r}`;
}
const highlight=
active && this._cursorIndex>=0 &&
(
(this._timestep==='summary' && orderIdx[k]===this._cursorIndex) ||
(this._timestep!=='summary' && sq-1===this._cursorIndex)
);
// **RESTORED**: Using original logic for creating nodes and links.
if(active){
code += ` ${sId}[${s}] -->|${lb}| ${tId}[${t}]\n`;
activeNodes.add(s); activeNodes.add(t);
if(highlight){
linkStyle+=` linkStyle ${linkIdx} stroke:#8590F8,stroke-width:4px,color:#8590F8\n`;
nodeStyle+=
` style ${sId} fill:#1A1A1A,stroke:#1A1A1A,color:#ffffff\n`+
` style ${tId} fill:#8590F8,stroke:#8590F8,color:#ffffff\n`;
}
} else {
code += ` ${sId}[${s}] -.-|${lb}| ${tId}[${t}]\n`;
linkStyle+=` linkStyle ${linkIdx} stroke:#ffffff,stroke-width:2px,color:#ffffff\n`;
}
linkIdx++;
});
// **RESTORED**: Using original logic for hiding inactive nodes.
allNodes.forEach(n=>{
if(!activeNodes.has(n)){
nodeStyle+=` style ${n.replace(/\s+/g,'')} fill:#ffffff,stroke:#ffffff,color:#ffffff\n`;
}
});
return code + nodeStyle + linkStyle + 'end\n';
}
// **RESTORED**: Using original, simple render method.
render() { this.textContent = this.generateMermaidDiagram(); }
}
customElements.define('temporal-graph-timestep', TemporalGraphTimestep);
/* All rights reserved Michael Anthony */