1+ <!DOCTYPE html>
2+ < html >
3+ < head >
4+ < title > Cashflow Model - Variable Dependencies</ title >
5+ < script src ="https://d3js.org/d3.v5.min.js "> </ script >
6+ < script src ="https://unpkg.com/dagre-d3@0.6.4/dist/dagre-d3.min.js "> </ script >
7+ < style >
8+ body {
9+ font-family : Arial, sans-serif;
10+ margin : 0 ;
11+ padding : 20px ;
12+ background-color : # f5f5f5 ;
13+ }
14+
15+ .main-container {
16+ display : flex;
17+ gap : 20px ;
18+ height : 90vh ;
19+ }
20+
21+ .graph-container {
22+ flex : 1 ;
23+ background : white;
24+ border : 1px solid # ddd ;
25+ border-radius : 5px ;
26+ overflow : auto;
27+ position : relative;
28+ }
29+
30+ .graph-container svg {
31+ width : 100% ;
32+ height : 100% ;
33+ }
34+
35+ .code-panel {
36+ width : 400px ;
37+ background : white;
38+ border : 1px solid # ddd ;
39+ border-radius : 5px ;
40+ display : flex;
41+ flex-direction : column;
42+ }
43+
44+ .code-header {
45+ padding : 15px ;
46+ border-bottom : 1px solid # ddd ;
47+ background-color : # f8f9fa ;
48+ border-radius : 5px 5px 0 0 ;
49+ }
50+
51+ .code-content {
52+ flex : 1 ;
53+ overflow : auto;
54+ padding : 0 ;
55+ }
56+
57+ .code-content pre {
58+ margin : 0 ;
59+ padding : 15px ;
60+ background-color : # f8f9fa ;
61+ border : none;
62+ font-family : 'Courier New' , monospace;
63+ font-size : 12px ;
64+ line-height : 1.4 ;
65+ white-space : pre-wrap;
66+ word-wrap : break-word;
67+ }
68+
69+ .node rect {
70+ stroke : # 333 ;
71+ fill : # fff ;
72+ stroke-width : 1.5px ;
73+ cursor : pointer;
74+ }
75+
76+ .node rect : hover {
77+ fill : # e3f2fd ;
78+ stroke : # 1976d2 ;
79+ stroke-width : 2px ;
80+ }
81+
82+ .node .selected rect {
83+ fill : # bbdefb ;
84+ stroke : # 1976d2 ;
85+ stroke-width : 2px ;
86+ }
87+
88+ .edgePath path {
89+ stroke : # 333 ;
90+ fill : none;
91+ stroke-width : 1.5px ;
92+ }
93+
94+ .controls {
95+ position : absolute;
96+ top : 10px ;
97+ right : 10px ;
98+ background : rgba (255 , 255 , 255 , 0.9 );
99+ padding : 10px ;
100+ border-radius : 5px ;
101+ border : 1px solid # ddd ;
102+ }
103+
104+ .instructions {
105+ margin-bottom : 20px ;
106+ padding : 10px ;
107+ background-color : # e3f2fd ;
108+ border-radius : 5px ;
109+ border-left : 4px solid # 1976d2 ;
110+ }
111+ </ style >
112+ </ head >
113+ < body >
114+ < div class ="instructions ">
115+ < strong > Instructions:</ strong > Click on any variable node to view its source code. Use mouse wheel to zoom, drag to pan.
116+ </ div >
117+
118+ < div class ="main-container ">
119+ < div class ="graph-container ">
120+ < svg id ="svg-canvas "> </ svg >
121+ </ div >
122+
123+ < div class ="code-panel ">
124+ < div class ="code-header ">
125+ < h3 id ="variable-name "> Select a variable to view its code</ h3 >
126+ </ div >
127+ < div class ="code-content ">
128+ < pre id ="variable-code "> Click on a variable node in the graph to see its source code here.</ pre >
129+ </ div >
130+ </ div >
131+ </ div >
132+
133+ < script >
134+ // Store node data for easy access
135+ var nodeData = { } ;
136+ var selectedNode = null ;
137+
138+ // Create a new directed graph
139+ var g = new dagreD3 . graphlib . Graph ( )
140+ . setGraph ( { } )
141+ . setDefaultEdgeLabel ( function ( ) { return { } ; } ) ;
142+
143+ // Add nodes
144+ var nodes = { { NODES_DATA } } ;
145+ nodes . forEach ( function ( node ) {
146+ g . setNode ( node . id , { label : node . label } ) ;
147+ nodeData [ node . id ] = node ;
148+ } ) ;
149+
150+ // Add edges
151+ var edges = { { EDGES_DATA } } ;
152+ edges . forEach ( function ( edge ) {
153+ g . setEdge ( edge . source , edge . target ) ;
154+ } ) ;
155+
156+ // Create the renderer
157+ var render = new dagreD3 . render ( ) ;
158+
159+ // Set up an SVG group so that we can translate the final graph.
160+ var svg = d3 . select ( "#svg-canvas" ) ;
161+ var svgGroup = svg . append ( "g" ) ;
162+
163+ // Run the renderer
164+ render ( svgGroup , g ) ;
165+
166+ // Add click handlers to nodes
167+ svgGroup . selectAll ( ".node" )
168+ . on ( "click" , function ( d ) {
169+ // Remove previous selection
170+ svgGroup . selectAll ( ".node" ) . classed ( "selected" , false ) ;
171+
172+ // Add selection to current node
173+ d3 . select ( this ) . classed ( "selected" , true ) ;
174+
175+ // Update code panel
176+ var nodeInfo = nodeData [ d ] ;
177+ if ( nodeInfo ) {
178+ document . getElementById ( "variable-name" ) . textContent = nodeInfo . label ;
179+ document . getElementById ( "variable-code" ) . textContent = nodeInfo . source ;
180+ selectedNode = d ;
181+ }
182+ } ) ;
183+
184+ // Set up zoom support
185+ var zoom = d3 . zoom ( )
186+ . scaleExtent ( [ 0.1 , 3 ] )
187+ . on ( "zoom" , function ( ) {
188+ svgGroup . attr ( "transform" , d3 . event . transform ) ;
189+ } ) ;
190+
191+ svg . call ( zoom ) ;
192+
193+ // Initial centering
194+ var initialScale = 0.8 ;
195+ var svgWidth = svg . node ( ) . getBoundingClientRect ( ) . width ;
196+ var svgHeight = svg . node ( ) . getBoundingClientRect ( ) . height ;
197+ var graphWidth = g . graph ( ) . width ;
198+ var graphHeight = g . graph ( ) . height ;
199+
200+ var translateX = ( svgWidth - graphWidth * initialScale ) / 2 ;
201+ var translateY = ( svgHeight - graphHeight * initialScale ) / 2 ;
202+
203+ svg . call ( zoom . transform , d3 . zoomIdentity
204+ . translate ( translateX , translateY )
205+ . scale ( initialScale ) ) ;
206+ </ script >
207+ </ body >
208+ </ html >
0 commit comments