trippykat commited on
Commit
42abb87
·
verified ·
1 Parent(s): 7d85583

undefined - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +777 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Graph
3
- emoji: 😻
4
- colorFrom: indigo
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: graph
3
+ emoji: 🐳
4
+ colorFrom: purple
5
+ colorTo: green
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,777 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Legal Case Graph Visualization</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
10
+ <style>
11
+ .pulse {
12
+ animation: pulse 2s infinite;
13
+ }
14
+ @keyframes pulse {
15
+ 0% { opacity: 1; }
16
+ 50% { opacity: 0.4; }
17
+ 100% { opacity: 1; }
18
+ }
19
+ .edgehighlight {
20
+ stroke: #3b82f6;
21
+ stroke-width: 4px;
22
+ }
23
+ .node-tooltip {
24
+ position: absolute;
25
+ visibility: hidden;
26
+ background: white;
27
+ border: 1px solid #e5e7eb;
28
+ border-radius: 0.5rem;
29
+ padding: 0.75rem;
30
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
31
+ max-width: 300px;
32
+ z-index: 100;
33
+ pointer-events: none;
34
+ }
35
+ #graph-container {
36
+ height: calc(100vh - 180px);
37
+ border: 1px solid #e5e7eb;
38
+ border-radius: 0.5rem;
39
+ background: #f9fafb;
40
+ }
41
+ .evidence-badge {
42
+ transition: all 0.3s ease;
43
+ }
44
+ .evidence-badge:hover {
45
+ transform: scale(1.1);
46
+ }
47
+ .document-preview {
48
+ max-height: 300px;
49
+ overflow-y: auto;
50
+ }
51
+ /* Custom scrollbar */
52
+ .document-preview::-webkit-scrollbar {
53
+ width: 6px;
54
+ }
55
+ .document-preview::-webkit-scrollbar-track {
56
+ background: #f1f1f1;
57
+ }
58
+ .document-preview::-webkit-scrollbar-thumb {
59
+ background: #c7d2fe;
60
+ border-radius: 10px;
61
+ }
62
+ .document-preview::-webkit-scrollbar-thumb:hover {
63
+ background: #a5b4fc;
64
+ }
65
+ </style>
66
+ </head>
67
+ <body class="bg-gray-50 font-sans">
68
+ <div class="container mx-auto px-4 py-6">
69
+ <!-- Header -->
70
+ <header class="flex justify-between items-center mb-6">
71
+ <div>
72
+ <h1 class="text-2xl font-bold text-gray-800">Legal Case Graph Analysis</h1>
73
+ <p class="text-gray-600">Visualizing complex legal relationships for defense strategy</p>
74
+ </div>
75
+ <div class="flex space-x-3">
76
+ <button id="presentation-mode" class="px-4 py-2 bg-blue-50 text-blue-600 rounded-lg border border-blue-200 hover:bg-blue-100 transition flex items-center">
77
+ <i class="fas fa-tv mr-2"></i> Presentation Mode
78
+ </button>
79
+ <button class="px-4 py-2 bg-white text-gray-700 rounded-lg border border-gray-200 hover:bg-gray-50 transition flex items-center">
80
+ <i class="fas fa-file-export mr-2"></i> Export
81
+ </button>
82
+ </div>
83
+ </header>
84
+
85
+ <!-- Main Content -->
86
+ <div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
87
+ <!-- Left Sidebar - Filters -->
88
+ <div class="lg:col-span-3 bg-white rounded-lg border border-gray-200 p-4">
89
+ <h2 class="text-lg font-semibold mb-4 text-gray-800">Case Filters</h2>
90
+
91
+ <div class="mb-6">
92
+ <label class="block text-sm font-medium text-gray-700 mb-1">Quick Search</label>
93
+ <div class="relative">
94
+ <input type="text" id="search-box" class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500" placeholder="Search people/documents...">
95
+ <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
96
+ <i class="fas fa-search text-gray-400"></i>
97
+ </div>
98
+ </div>
99
+ </div>
100
+
101
+ <div class="mb-6">
102
+ <label class="block text-sm font-medium text-gray-700 mb-2">Entity Types</label>
103
+ <div class="space-y-2">
104
+ <label class="flex items-center space-x-2">
105
+ <input type="checkbox" class="rounded text-blue-600" checked data-type="officer">
106
+ <span class="text-gray-700">Officers</span>
107
+ </label>
108
+ <label class="flex items-center space-x-2">
109
+ <input type="checkbox" class="rounded text-blue-600" checked data-type="witness">
110
+ <span class="text-gray-700">Witnesses</span>
111
+ </label>
112
+ <label class="flex items-center space-x-2">
113
+ <input type="checkbox" class="rounded text-blue-600" checked data-type="defendant">
114
+ <span class="text-gray-700">Defendants</span>
115
+ </label>
116
+ <label class="flex items-center space-x-2">
117
+ <input type="checkbox" class="rounded text-blue-600" checked data-type="document">
118
+ <span class="text-gray-700">Documents</span>
119
+ </label>
120
+ <label class="flex items-center space-x-2">
121
+ <input type="checkbox" class="rounded text-blue-600" checked data-type="location">
122
+ <span class="text-gray-700">Locations</span>
123
+ </label>
124
+ </div>
125
+ </div>
126
+
127
+ <div class="mb-6">
128
+ <label class="block text-sm font-medium text-gray-700 mb-2">Legal Issues</label>
129
+ <div class="space-y-2">
130
+ <label class="flex items-center space-x-2">
131
+ <input type="checkbox" class="rounded text-blue-600" checked data-issue="violation">
132
+ <span class="text-gray-700">Constitutional Violations</span>
133
+ </label>
134
+ <label class="flex items-center space-x-2">
135
+ <input type="checkbox" class="rounded text-blue-600" data-issue="bias">
136
+ <span class="text-gray-700">Bias Indicators</span>
137
+ </label>
138
+ <label class="flex items-center space-x-2">
139
+ <input type="checkbox" class="rounded text-blue-600" data-issue="credibility">
140
+ <span class="text-gray-700">Credibility Issues</span>
141
+ </label>
142
+ <label class="flex items-center space-x-2">
143
+ <input type="checkbox" class="rounded text-blue-600" data-issue="procedure">
144
+ <span class="text-gray-700">Procedural Errors</span>
145
+ </label>
146
+ </div>
147
+ </div>
148
+
149
+ <div>
150
+ <label class="block text-sm font-medium text-gray-700 mb-2">Time Range</label>
151
+ <div class="grid grid-cols-2 gap-2">
152
+ <input type="time" class="border border-gray-300 rounded px-2 py-1" value="06:00">
153
+ <input type="time" class="border border-gray-300 rounded px-2 py-1" value="07:00">
154
+ </div>
155
+ <div class="mt-2">
156
+ <input type="range" min="0" max="100" value="100" class="w-full h-2 bg-blue-100 rounded-lg appearance-none cursor-pointer">
157
+ </div>
158
+ </div>
159
+ </div>
160
+
161
+ <!-- Main Graph Area -->
162
+ <div class="lg:col-span-9">
163
+ <!-- Toolbar -->
164
+ <div class="bg-white rounded-lg border border-gray-200 p-3 mb-4 flex flex-wrap items-center justify-between">
165
+ <div class="flex space-x-2 mb-2 sm:mb-0">
166
+ <button id="relationship-view" class="px-3 py-1 bg-blue-600 text-white rounded-md text-sm font-medium hover:bg-blue-700 transition active:bg-blue-800">
167
+ <i class="fas fa-project-diagram mr-1"></i> Relationships
168
+ </button>
169
+ <button id="timeline-view" class="px-3 py-1 bg-white text-gray-700 rounded-md text-sm font-medium border border-gray-300 hover:bg-gray-50 transition">
170
+ <i class="fas fa-clock mr-1"></i> Timeline
171
+ </button>
172
+ <button id="hierarchy-view" class="px-3 py-1 bg-white text-gray-700 rounded-md text-sm font-medium border border-gray-300 hover:bg-gray-50 transition">
173
+ <i class="fas fa-sitemap mr-1"></i> Hierarchy
174
+ </button>
175
+ </div>
176
+ <div class="flex space-x-2">
177
+ <button id="zoom-fit" class="p-1.5 bg-gray-100 text-gray-600 rounded hover:bg-gray-200 transition">
178
+ <i class="fas fa-expand"></i>
179
+ </button>
180
+ <div class="relative">
181
+ <button id="view-options" class="flex items-center px-3 py-1 bg-white text-gray-700 rounded-md text-sm font-medium border border-gray-300 hover:bg-gray-50 transition">
182
+ <i class="fas fa-sliders-h mr-1"></i> View Options
183
+ </button>
184
+ <div id="view-dropdown" class="hidden absolute right-0 mt-1 w-48 bg-white rounded-md shadow-lg z-10">
185
+ <div class="py-1">
186
+ <label class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
187
+ <input type="checkbox" class="mr-2 rounded text-blue-600" checked> Show Connection Strength
188
+ </label>
189
+ <label class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
190
+ <input type="checkbox" class="mr-2 rounded text-blue-600" checked> Show Timeline Indicators
191
+ </label>
192
+ <div class="border-t border-gray-200"></div>
193
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Reset View</a>
194
+ </div>
195
+ </div>
196
+ </div>
197
+ </div>
198
+ </div>
199
+
200
+ <!-- Graph Visualization -->
201
+ <div id="graph-container"></div>
202
+
203
+ <!-- Bottom Panel -->
204
+ <div class="mt-4 bg-white rounded-lg border border-gray-200">
205
+ <div class="flex border-b border-gray-200">
206
+ <button id="info-tab" class="px-4 py-2 border-b-2 border-blue-500 font-medium text-blue-600">Entity Details</button>
207
+ <button id="connections-tab" class="px-4 py-2 font-medium text-gray-600 hover:text-blue-600">Connections</button>
208
+ <button id="timeline-tab" class="px-4 py-2 font-medium text-gray-600 hover:text-blue-600">Timeline</button>
209
+ <button id="evidence-tab" class="px-4 py-2 font-medium text-gray-600 hover:text-blue-600">Evidence Chains</button>
210
+ </div>
211
+ <div id="info-content" class="p-4">
212
+ <div class="flex flex-col md:flex-row">
213
+ <div class="md:w-1/3 mb-4 md:mb-0 md:pr-4">
214
+ <div class="h-full border border-gray-200 rounded-lg p-4 bg-gray-50">
215
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">Selected Entity</h3>
216
+ <div class="flex items-center mb-3">
217
+ <div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center mr-3">
218
+ <i class="fas fa-user-shield text-blue-600 text-xl"></i>
219
+ </div>
220
+ <div>
221
+ <h4 class="font-medium">Officer James Smith</h4>
222
+ <p class="text-sm text-gray-600">Badge #4572, 5th Precinct</p>
223
+ </div>
224
+ </div>
225
+ <div class="space-y-3">
226
+ <div>
227
+ <p class="text-sm text-gray-500">Role in Case</p>
228
+ <p>Primary arresting officer, search execution</p>
229
+ </div>
230
+ <div>
231
+ <p class="text-sm text-gray-500">Documents</p>
232
+ <div class="flex flex-wrap gap-2 mt-1">
233
+ <span class="bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs">Search Warrant #245</span>
234
+ <span class="bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs">Arrest Report</span>
235
+ <span class="bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs">Body Cam Transcript</span>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </div>
241
+ <div class="md:w-2/3 md:pl-4">
242
+ <div class="h-full border border-gray-200 rounded-lg p-4">
243
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">Legal Analysis</h3>
244
+ <div class="space-y-4">
245
+ <div>
246
+ <div class="flex justify-between items-center mb-1">
247
+ <span class="font-medium">Constitutional Violations</span>
248
+ <span class="text-xs bg-red-100 text-red-800 px-2 py-0.5 rounded-full">High Priority</span>
249
+ </div>
250
+ <div class="bg-gray-100 rounded p-3 text-sm">
251
+ <p class="mb-1"><i class="fas fa-exclamation-triangle text-red-500 mr-1"></i> Search may have exceeded warrant scope based on comparison with warrant document</p>
252
+ <p><i class="fas fa-exclamation-triangle text-red-500 mr-1"></i> Inconsistent statements about probable cause between arrest report and testimony</p>
253
+ </div>
254
+ </div>
255
+ <div>
256
+ <div class="flex justify-between items-center mb-1">
257
+ <span class="font-medium">Credibility Indicators</span>
258
+ <span class="text-xs bg-yellow-100 text-yellow-800 px-2 py-0.5 rounded-full">Medium Priority</span>
259
+ </div>
260
+ <div class="bg-gray-100 rounded p-3 text-sm">
261
+ <p class="mb-1"><i class="fas fa-search text-blue-500 mr-1"></i> Discrepancy in time logs between officer's report and body cam timestamps</p>
262
+ <p><i class="fas fa-search text-blue-500 mr-1"></i> Multiple officers provide conflicting accounts about who initiated the search</p>
263
+ </div>
264
+ </div>
265
+ <div class="flex space-x-2">
266
+ <button class="px-3 py-1 bg-blue-600 text-white rounded-md text-sm hover:bg-blue-700 transition">
267
+ Add to Motion to Suppress
268
+ </button>
269
+ <button class="px-3 py-1 bg-white text-gray-700 rounded-md text-sm border border-gray-300 hover:bg-gray-50 transition">
270
+ Flag for Cross-Examination
271
+ </button>
272
+ </div>
273
+ </div>
274
+ </div>
275
+ </div>
276
+ </div>
277
+ </div>
278
+ <div id="connections-content" class="p-4 hidden">
279
+ <!-- Connections content would go here -->
280
+ </div>
281
+ <div id="timeline-content" class="p-4 hidden">
282
+ <!-- Timeline content would go here -->
283
+ </div>
284
+ <div id="evidence-content" class="p-4 hidden">
285
+ <!-- Evidence content would go here -->
286
+ </div>
287
+ </div>
288
+ </div>
289
+ </div>
290
+ </div>
291
+
292
+ <div id="node-tooltip" class="node-tooltip"></div>
293
+
294
+ <script>
295
+ document.addEventListener('DOMContentLoaded', function() {
296
+ // Initialize the network visualization
297
+ const container = document.getElementById('graph-container');
298
+
299
+ // Sample data for the visualization
300
+ const nodes = new vis.DataSet([
301
+ // Officers
302
+ { id: 1, label: "Officer\nSmith",
303
+ title: "Badge #4572\n5th Precinct\nPrimary arresting officer",
304
+ group: "officer", color: { background: "#3b82f6", border: "#1d4ed8" },
305
+ shape: "box", margin: 10, font: { size: 14 },
306
+ image: "https://cdn-icons-png.flaticon.com/512/1865/1865250.png",
307
+ shapeProperties: { borderRadius: 6 } },
308
+
309
+ { id: 2, label: "Officer\nJohnson",
310
+ title: "Badge #3214\n5th Precinct\nAssisting officer",
311
+ group: "officer", color: { background: "#3b82f6", border: "#1d4ed8" },
312
+ shape: "box", margin: 10, font: { size: 14 },
313
+ shapeProperties: { borderRadius: 6 } },
314
+
315
+ // Defendants
316
+ { id: 3, label: "Marcus\nGreen",
317
+ title: "Defendant\nPrimary subject of investigation",
318
+ group: "defendant", color: { background: "#ef4444", border: "#b91c1c" },
319
+ shape: "ellipse", margin: 10, font: { size: 14 } },
320
+
321
+ // Witnesses
322
+ { id: 4, label: "Sarah\nWilliams",
323
+ title: "Neighbor witness\nSaw initial encounter",
324
+ group: "witness", color: { background: "#10b981", border: "#047857" },
325
+ shape: "circle", margin: 10, font: { size: 14 } },
326
+
327
+ // Documents
328
+ { id: 5, label: "Search\nWarrant #245",
329
+ title: "Issued 04/15/2023\nJudge Martinez\nValid 04/16 from 12AM-8AM",
330
+ group: "document", color: { background: "#f59e0b", border: "#d97706" },
331
+ shape: "box", margin: 10, font: { size: 14 },
332
+ image: "https://cdn-icons-png.flaticon.com/512/2991/2991112.png",
333
+ shapeProperties: { borderRadius: 6 } },
334
+
335
+ { id: 6, label: "Arrest\nReport",
336
+ title: "Filed 04/16/2023\nOfficer Smith",
337
+ group: "document", color: { background: "#f59e0b", border: "#d97706" },
338
+ shape: "box", margin: 10, font: { size: 14 },
339
+ shapeProperties: { borderRadius: 6 } },
340
+
341
+ // Locations
342
+ { id: 7, label: "123 Main St\nApt 4B",
343
+ title: "Defendant's residence\nSearch executed here at 6:12AM",
344
+ group: "location", color: { background: "#8b5cf6", border: "#7c3aed" },
345
+ shape: "box", margin: 10, font: { size: 14 },
346
+ image: "https://cdn-icons-png.flaticon.com/512/484/484541.png",
347
+ shapeProperties: { borderRadius: 6 } }
348
+ ]);
349
+
350
+ const edges = new vis.DataSet([
351
+ { from: 1, to: 3, label: "arrested", width: 3, color: { color: "#3b82f6", highlight: "#2563eb" } },
352
+ { from: 1, to: 5, label: "executed", width: 2, color: { color: "#3b82f6", highlight: "#2563eb" } },
353
+ { from: 5, to: 7, label: "authorized", width: 4, color: { color: "#f59e0b", highlight: "#d97706" } },
354
+ { from: 1, to: 7, label: "searched 6:12AM", width: 3, color: { color: "#3b82f6", highlight: "#2563eb" }, dashes: true },
355
+ { from: 3, to: 7, label: "resides", width: 2, color: { color: "#ef4444", highlight: "#b91c1c" } },
356
+ { from: 4, to: 1, label: "interacted", width: 1, color: { color: "#10b981", highlight: "#047857" } },
357
+ { from: 4, to: 3, label: "saw", width: 1, color: { color: "#10b981", highlight: "#047857" } },
358
+ { from: 1, to: 6, label: "filed", width: 2, color: { color: "#3b82f6", highlight: "#2563eb" } }
359
+ ]);
360
+
361
+ const data = {
362
+ nodes: nodes,
363
+ edges: edges
364
+ };
365
+
366
+ const options = {
367
+ nodes: {
368
+ borderWidth: 2,
369
+ shadow: {
370
+ enabled: true,
371
+ color: 'rgba(0,0,0,0.2)',
372
+ size: 10,
373
+ x: 5,
374
+ y: 5
375
+ }
376
+ },
377
+ edges: {
378
+ arrows: {
379
+ to: { enabled: true, scaleFactor: 0.5 },
380
+ middle: { enabled: false },
381
+ from: { enabled: false }
382
+ },
383
+ color: {
384
+ inherit: 'to'
385
+ },
386
+ font: {
387
+ size: 12,
388
+ align: 'middle'
389
+ },
390
+ smooth: {
391
+ type: 'cubicBezier',
392
+ roundness: 0.4
393
+ },
394
+ selectionWidth: 3
395
+ },
396
+ physics: {
397
+ enabled: true,
398
+ solver: 'forceAtlas2Based',
399
+ forceAtlas2Based: {
400
+ gravitationalConstant: -50,
401
+ centralGravity: 0.01,
402
+ springLength: 200,
403
+ springConstant: 0.08,
404
+ damping: 0.4
405
+ },
406
+ stabilization: {
407
+ iterations: 250
408
+ }
409
+ },
410
+ groups: {
411
+ officer: {
412
+ color: {
413
+ border: '#1d4ed8',
414
+ background: '#3b82f6',
415
+ highlight: {
416
+ border: '#1e40af',
417
+ background: '#2563eb'
418
+ },
419
+ hover: {
420
+ border: '#1e40af',
421
+ background: '#2563eb'
422
+ }
423
+ },
424
+ font: { color: 'white' },
425
+ shape: 'box',
426
+ size: 20
427
+ },
428
+ defendant: {
429
+ color: {
430
+ border: '#b91c1c',
431
+ background: '#ef4444',
432
+ highlight: {
433
+ border: '#991b1b',
434
+ background: '#dc2626'
435
+ },
436
+ hover: {
437
+ border: '#991b1b',
438
+ background: '#dc2626'
439
+ }
440
+ },
441
+ font: { color: 'white' },
442
+ shape: 'ellipse',
443
+ size: 25
444
+ },
445
+ witness: {
446
+ color: {
447
+ border: '#047857',
448
+ background: '#10b981',
449
+ highlight: {
450
+ border: '#065f46',
451
+ background: '#059669'
452
+ },
453
+ hover: {
454
+ border: '#065f46',
455
+ background: '#059669'
456
+ }
457
+ },
458
+ font: { color: 'white' },
459
+ shape: 'circle',
460
+ size: 20
461
+ },
462
+ document: {
463
+ color: {
464
+ border: '#d97706',
465
+ background: '#f59e0b',
466
+ highlight: {
467
+ border: '#b45309',
468
+ background: '#d97706'
469
+ },
470
+ hover: {
471
+ border: '#b45309',
472
+ background: '#d97706'
473
+ }
474
+ },
475
+ font: { color: 'white' },
476
+ shape: 'box',
477
+ size: 20
478
+ },
479
+ location: {
480
+ color: {
481
+ border: '#7c3aed',
482
+ background: '#8b5cf6',
483
+ highlight: {
484
+ border: '#6d28d9',
485
+ background: '#7c3aed'
486
+ },
487
+ hover: {
488
+ border: '#6d28d9',
489
+ background: '#7c3aed'
490
+ }
491
+ },
492
+ font: { color: 'white' },
493
+ shape: 'box',
494
+ size: 20
495
+ }
496
+ },
497
+ interaction: {
498
+ hover: true,
499
+ tooltipDelay: 100,
500
+ hideEdgesOnDrag: false,
501
+ multiselect: true,
502
+ selectable: true,
503
+ selectConnectedEdges: true
504
+ },
505
+ layout: {
506
+ randomSeed: 42
507
+ }
508
+ };
509
+
510
+ const network = new vis.Network(container, data, options);
511
+
512
+ // Handle node clicks to update the details panel
513
+ network.on("selectNode", function(params) {
514
+ // In a real app, you would fetch more detailed data based on the node ID
515
+ console.log("Selected node:", params.nodes[0]);
516
+ });
517
+
518
+ // Handle edge clicks
519
+ network.on("selectEdge", function(params) {
520
+ console.log("Selected edge:", params.edges[0]);
521
+ });
522
+
523
+ // Handle double click for zooming
524
+ network.on("doubleClick", function(params) {
525
+ if (params.nodes.length > 0) {
526
+ network.focus(params.nodes[0], { scale: 1.5 });
527
+ }
528
+ });
529
+
530
+ // Custom node tooltip
531
+ const tooltip = document.getElementById('node-tooltip');
532
+ network.on("hoverNode", function(params) {
533
+ const nodeId = params.node;
534
+ const node = nodes.get(nodeId);
535
+
536
+ tooltip.innerHTML = `
537
+ <div class="font-medium text-gray-800">${node.label.replace('\n', ' ')}</div>
538
+ <div class="text-sm text-gray-600">${node.title.replace('\n', '<br>')}</div>
539
+ `;
540
+
541
+ const position = network.getPositions([nodeId])[nodeId];
542
+ const canvasPosition = network.canvasToDOM(position);
543
+
544
+ tooltip.style.left = (canvasPosition.x + 20) + 'px';
545
+ tooltip.style.top = (canvasPosition.y - 20) + 'px';
546
+ tooltip.style.visibility = 'visible';
547
+ });
548
+
549
+ network.on("blurNode", function() {
550
+ tooltip.style.visibility = 'hidden';
551
+ });
552
+
553
+ // Tab switching functionality
554
+ document.getElementById('info-tab').addEventListener('click', function() {
555
+ document.getElementById('info-content').classList.remove('hidden');
556
+ document.getElementById('connections-content').classList.add('hidden');
557
+ document.getElementById('timeline-content').classList.add('hidden');
558
+ document.getElementById('evidence-content').classList.add('hidden');
559
+
560
+ this.classList.add('border-blue-500', 'text-blue-600');
561
+ document.getElementById('connections-tab').classList.remove('border-blue-500', 'text-blue-600');
562
+ document.getElementById('timeline-tab').classList.remove('border-blue-500', 'text-blue-600');
563
+ document.getElementById('evidence-tab').classList.remove('border-blue-500', 'text-blue-600');
564
+ });
565
+
566
+ document.getElementById('connections-tab').addEventListener('click', function() {
567
+ document.getElementById('info-content').classList.add('hidden');
568
+ document.getElementById('connections-content').classList.remove('hidden');
569
+ document.getElementById('timeline-content').classList.add('hidden');
570
+ document.getElementById('evidence-content').classList.add('hidden');
571
+
572
+ this.classList.add('border-blue-500', 'text-blue-600');
573
+ document.getElementById('info-tab').classList.remove('border-blue-500', 'text-blue-600');
574
+ document.getElementById('timeline-tab').classList.remove('border-blue-500', 'text-blue-600');
575
+ document.getElementById('evidence-tab').classList.remove('border-blue-500', 'text-blue-600');
576
+ });
577
+
578
+ document.getElementById('timeline-tab').addEventListener('click', function() {
579
+ document.getElementById('info-content').classList.add('hidden');
580
+ document.getElementById('connections-content').classList.add('hidden');
581
+ document.getElementById('timeline-content').classList.remove('hidden');
582
+ document.getElementById('evidence-content').classList.add('hidden');
583
+
584
+ this.classList.add('border-blue-500', 'text-blue-600');
585
+ document.getElementById('info-tab').classList.remove('border-blue-500', 'text-blue-600');
586
+ document.getElementById('connections-tab').classList.remove('border-blue-500', 'text-blue-600');
587
+ document.getElementById('evidence-tab').classList.remove('border-blue-500', 'text-blue-600');
588
+ });
589
+
590
+ document.getElementById('evidence-tab').addEventListener('click', function() {
591
+ document.getElementById('info-content').classList.add('hidden');
592
+ document.getElementById('connections-content').classList.add('hidden');
593
+ document.getElementById('timeline-content').classList.add('hidden');
594
+ document.getElementById('evidence-content').classList.remove('hidden');
595
+
596
+ this.classList.add('border-blue-500', 'text-blue-600');
597
+ document.getElementById('info-tab').classList.remove('border-blue-500', 'text-blue-600');
598
+ document.getElementById('connections-tab').classList.remove('border-blue-500', 'text-blue-600');
599
+ document.getElementById('timeline-tab').classList.remove('border-blue-500', 'text-blue-600');
600
+ });
601
+
602
+ // Layout switching
603
+ document.getElementById('relationship-view').addEventListener('click', function() {
604
+ network.setOptions({
605
+ physics: {
606
+ solver: 'forceAtlas2Based',
607
+ forceAtlas2Based: {
608
+ gravitationalConstant: -50,
609
+ centralGravity: 0.01,
610
+ springLength: 200,
611
+ springConstant: 0.08,
612
+ damping: 0.4
613
+ }
614
+ }
615
+ });
616
+
617
+ this.classList.remove('bg-white', 'text-gray-700', 'border-gray-300');
618
+ this.classList.add('bg-blue-600', 'text-white');
619
+
620
+ document.getElementById('timeline-view').classList.remove('bg-blue-600', 'text-white');
621
+ document.getElementById('timeline-view').classList.add('bg-white', 'text-gray-700', 'border-gray-300');
622
+
623
+ document.getElementById('hierarchy-view').classList.remove('bg-blue-600', 'text-white');
624
+ document.getElementById('hierarchy-view').classList.add('bg-white', 'text-gray-700', 'border-gray-300');
625
+ });
626
+
627
+ document.getElementById('timeline-view').addEventListener('click', function() {
628
+ // In a real app, this would adjust node positions along a timeline axis
629
+ network.setOptions({
630
+ physics: {
631
+ solver: 'forceAtlas2Based',
632
+ forceAtlas2Based: {
633
+ gravitationalConstant: -50,
634
+ centralGravity: 0.01,
635
+ springLength: 200,
636
+ springConstant: 0.08,
637
+ damping: 0.4
638
+ }
639
+ }
640
+ });
641
+
642
+ this.classList.remove('bg-white', 'text-gray-700', 'border-gray-300');
643
+ this.classList.add('bg-blue-600', 'text-white');
644
+
645
+ document.getElementById('relationship-view').classList.remove('bg-blue-600', 'text-white');
646
+ document.getElementById('relationship-view').classList.add('bg-white', 'text-gray-700', 'border-gray-300');
647
+
648
+ document.getElementById('hierarchy-view').classList.remove('bg-blue-600', 'text-white');
649
+ document.getElementById('hierarchy-view').classList.add('bg-white', 'text-gray-700', 'border-gray-300');
650
+ });
651
+
652
+ document.getElementById('hierarchy-view').addEventListener('click', function() {
653
+ // In a real app, this would arrange nodes hierarchically
654
+ network.setOptions({
655
+ physics: {
656
+ solver: 'hierarchicalRepulsion',
657
+ hierarchicalRepulsion: {
658
+ nodeDistance: 120
659
+ }
660
+ }
661
+ });
662
+
663
+ this.classList.remove('bg-white', 'text-gray-700', 'border-gray-300');
664
+ this.classList.add('bg-blue-600', 'text-white');
665
+
666
+ document.getElementById('relationship-view').classList.remove('bg-blue-600', 'text-white');
667
+ document.getElementById('relationship-view').classList.add('bg-white', 'text-gray-700', 'border-gray-300');
668
+
669
+ document.getElementById('timeline-view').classList.remove('bg-blue-600', 'text-white');
670
+ document.getElementById('timeline-view').classList.add('bg-white', 'text-gray-700', 'border-gray-300');
671
+ });
672
+
673
+ // Zoom to fit
674
+ document.getElementById('zoom-fit').addEventListener('click', function() {
675
+ network.fit({ animation: { duration: 1000, easingFunction: 'easeInOutQuad' } });
676
+ });
677
+
678
+ // View options dropdown
679
+ document.getElementById('view-options').addEventListener('click', function() {
680
+ document.getElementById('view-dropdown').classList.toggle('hidden');
681
+ });
682
+
683
+ // Close dropdown when clicking outside
684
+ document.addEventListener('click', function(event) {
685
+ if (!event.target.closest('#view-options') && !event.target.closest('#view-dropdown')) {
686
+ document.getElementById('view-dropdown').classList.add('hidden');
687
+ }
688
+ });
689
+
690
+ // Search functionality
691
+ document.getElementById('search-box').addEventListener('input', function(e) {
692
+ const searchTerm = e.target.value.toLowerCase();
693
+
694
+ if (searchTerm.length > 0) {
695
+ const matchedNodes = nodes.get({
696
+ filter: function(node) {
697
+ return node.label.toLowerCase().includes(searchTerm) ||
698
+ (node.title && node.title.toLowerCase().includes(searchTerm));
699
+ }
700
+ });
701
+
702
+ const matchedNodeIds = matchedNodes.map(node => node.id);
703
+ network.selectNodes(matchedNodeIds);
704
+
705
+ if (matchedNodeIds.length > 0) {
706
+ network.focus(matchedNodeIds[0], { scale: 1.2 });
707
+ }
708
+ } else {
709
+ network.unselectAll();
710
+ }
711
+ });
712
+
713
+ // Filter by entity type
714
+ document.querySelectorAll('[data-type]').forEach(checkbox => {
715
+ checkbox.addEventListener('change', function() {
716
+ const type = this.getAttribute('data-type');
717
+ const visible = this.checked;
718
+
719
+ nodes.update({
720
+ id: nodes.getIds({
721
+ filter: function(node) {
722
+ return node.group === type;
723
+ }
724
+ }),
725
+ hidden: !visible
726
+ });
727
+ });
728
+ });
729
+
730
+ // Filter by legal issue
731
+ document.querySelectorAll('[data-issue]').forEach(checkbox => {
732
+ checkbox.addEventListener('change', function() {
733
+ const issue = this.getAttribute('data-issue');
734
+ const visible = this.checked;
735
+
736
+ // In a real app, you would filter nodes and edges based on legal issues
737
+ console.log(`Filter ${issue} to ${visible}`);
738
+ });
739
+ });
740
+
741
+ // Presentation mode
742
+ document.getElementById('presentation-mode').addEventListener('click', function() {
743
+ document.body.classList.toggle('bg-gray-800');
744
+ document.querySelectorAll('.bg-white, .border-gray-200').forEach(el => {
745
+ el.classList.toggle('bg-gray-900');
746
+ el.classList.toggle('border-gray-700');
747
+ });
748
+ document.querySelectorAll('.text-gray-600, .text-gray-700, .text-gray-800').forEach(el => {
749
+ el.classList.toggle('text-gray-300');
750
+ });
751
+
752
+ network.setOptions({
753
+ nodes: {
754
+ color: {
755
+ background: '#3b82f6',
756
+ border: '#1d4ed8',
757
+ highlight: {
758
+ border: '#1e40af',
759
+ background: '#2563eb'
760
+ }
761
+ }
762
+ }
763
+ });
764
+
765
+ this.classList.toggle('text-white');
766
+ });
767
+
768
+ // Add some pulse effect for important nodes (demo purposes)
769
+ setTimeout(() => {
770
+ const importantNode = nodes.get(1);
771
+ const el = document.querySelector(`[data-node-id="${importantNode.id}"]`);
772
+ if (el) el.classList.add('pulse');
773
+ }, 1000);
774
+ });
775
+ </script>
776
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=trippykat/graph" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
777
+ </html>