rajkhanke commited on
Commit
b0da134
·
verified ·
1 Parent(s): 3c0dc67

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +483 -18
index.html CHANGED
@@ -1,19 +1,484 @@
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
+ <title>Enhanced Interactive D3.js Dashboard</title>
6
+ <!-- Load D3.js -->
7
+ <script src="https://d3js.org/d3.v7.min.js"></script>
8
+ <style>
9
+ /* General Page Styling */
10
+ body {
11
+ background: #f0f0f0;
12
+ font-family: 'Segoe UI', sans-serif;
13
+ margin: 0;
14
+ padding: 20px;
15
+ }
16
+ .container {
17
+ max-width: 1300px;
18
+ margin: auto;
19
+ }
20
+ /* Upload Section */
21
+ .upload-container {
22
+ background: #fff;
23
+ padding: 40px;
24
+ border-radius: 10px;
25
+ box-shadow: 0 5px 15px rgba(0,0,0,0.15);
26
+ text-align: center;
27
+ margin-bottom: 30px;
28
+ transition: transform 0.3s;
29
+ }
30
+ .upload-container:hover {
31
+ transform: scale(1.02);
32
+ }
33
+ .upload-container input[type="file"] {
34
+ margin-top: 20px;
35
+ padding: 12px 20px;
36
+ border: none;
37
+ background: #3498db;
38
+ color: #fff;
39
+ border-radius: 5px;
40
+ font-size: 16px;
41
+ cursor: pointer;
42
+ transition: background 0.3s;
43
+ }
44
+ .upload-container input[type="file"]:hover {
45
+ background: #2980b9;
46
+ }
47
+ /* Headings */
48
+ h1,h2, h3 {
49
+ text-align: center;
50
+ margin-top: 20px;
51
+ color: #333;
52
+ }
53
+ /* Top Cards Styling */
54
+ .card-container {
55
+ display: flex;
56
+ flex-wrap: wrap;
57
+ justify-content: space-between;
58
+ margin-bottom: 20px;
59
+ }
60
+ .card {
61
+ flex: 1 1 calc(33% - 20px);
62
+ margin: 10px;
63
+ padding: 20px;
64
+ border-radius: 10px;
65
+ text-align: center;
66
+ color: #fff;
67
+ box-shadow: 0 4px 8px rgba(0,0,0,0.15);
68
+ transition: transform 0.3s;
69
+ cursor: pointer;
70
+ }
71
+ .card:hover {
72
+ transform: scale(1.05);
73
+ }
74
+ /* Chart Containers */
75
+ .chart-container {
76
+ display: flex;
77
+ flex-wrap: wrap;
78
+ justify-content: space-around;
79
+ margin: 20px 10px;
80
+ background: #fff;
81
+ border-radius: 10px;
82
+ padding: 15px;
83
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
84
+ }
85
+ .chart-box {
86
+ margin: 10px;
87
+ }
88
+ /* Circular Cards (Enlarged) */
89
+ .circular-card {
90
+ width: 200px;
91
+ height: 200px;
92
+ border-radius: 50%;
93
+ background: linear-gradient(135deg, #ff416c, #ff4b2b);
94
+ color: #fff;
95
+ display: flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ font-size: 18px;
99
+ font-weight: bold;
100
+ margin: 10px;
101
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
102
+ transition: transform 0.3s;
103
+ text-align: center;
104
+ padding: 10px;
105
+ }
106
+ .circular-card:hover {
107
+ transform: rotate(10deg) scale(1.1);
108
+ }
109
+ /* Line Chart Container */
110
+ .line-chart {
111
+ background: #fff;
112
+ border-radius: 10px;
113
+ padding: 15px;
114
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
115
+ margin: 20px 10px;
116
+ position: relative;
117
+ }
118
+ /* Tooltip for Charts */
119
+ .tooltip {
120
+ position: absolute;
121
+ text-align: center;
122
+ padding: 6px;
123
+ font: 12px sans-serif;
124
+ background: lightsteelblue;
125
+ border: 0;
126
+ border-radius: 4px;
127
+ pointer-events: none;
128
+ opacity: 0;
129
+ transition: opacity 0.3s;
130
+ }
131
+ </style>
132
+ </head>
133
+ <body>
134
+ <div class="container">
135
+ <!-- File Upload UI -->
136
+ <div class="upload-container" id="uploadContainer">
137
+ <h2>Upload Your JSON File</h2>
138
+ <p>Please select a JSON file with your dashboard data.</p>
139
+ <input type="file" id="fileInput" accept=".json">
140
+ </div>
141
+
142
+ <!-- Dashboard (hidden until file is loaded) -->
143
+ <div id="dashboard" style="display: none;">
144
+ <!-- Top Cards -->
145
+ <h1>Visualization Dashboard</h1>
146
+ <div class="card-container" id="cards"></div>
147
+
148
+ <!-- Charts: Histogram and Pie Chart Side-by-Side -->
149
+ <h2>Charts</h2>
150
+ <div class="chart-container">
151
+ <div class="chart-box" id="histogramContainer">
152
+ <h3>Histogram of Similarity Scores</h3>
153
+ <svg id="histogram"></svg>
154
+ </div>
155
+ <div class="chart-box" id="pieChartContainer">
156
+ <h3>Matches Distribution Pie Chart</h3>
157
+ <svg id="pieChart"></svg>
158
+ </div>
159
+ </div>
160
+
161
+ <!-- Interactive Line Chart -->
162
+ <h3>Interactive Line Chart of Similarity Scores</h3>
163
+ <div id="lineChart" class="line-chart"></div>
164
+
165
+ <!-- Circular Cards for Similarity Statistics -->
166
+ <h2>Similarity Statistics</h2>
167
+ <div class="card-container" id="circularCards" style="justify-content: center;"></div>
168
+ </div>
169
+ </div>
170
+
171
+ <!-- Tooltip (used by both histogram and line chart) -->
172
+ <div id="tooltip" class="tooltip"></div>
173
+
174
+ <script>
175
+ // Listen for file input changes and parse JSON
176
+ document.getElementById('fileInput').addEventListener('change', function(event) {
177
+ const file = event.target.files[0];
178
+ if (!file) return;
179
+ const reader = new FileReader();
180
+ reader.onload = function(e) {
181
+ let jsonData;
182
+ try {
183
+ jsonData = JSON.parse(e.target.result);
184
+ } catch(err) {
185
+ alert("Invalid JSON file!");
186
+ return;
187
+ }
188
+ // Hide the upload container and display the dashboard
189
+ document.getElementById('uploadContainer').style.display = 'none';
190
+ document.getElementById('dashboard').style.display = 'block';
191
+ updateDashboard(jsonData);
192
+ }
193
+ reader.readAsText(file);
194
+ });
195
+
196
+ function updateDashboard(data) {
197
+ // Clear previous content
198
+ d3.select("#cards").html("");
199
+ d3.select("#histogram").html("");
200
+ d3.select("#pieChart").html("");
201
+ d3.select("#lineChart").html("");
202
+ d3.select("#circularCards").html("");
203
+
204
+ // ---- Top Cards (Key Metrics) ----
205
+ const cardData = [
206
+ { label: "Total Records", value: data.total_rows, bg: "linear-gradient(135deg, #6a11cb, #2575fc)" },
207
+ { label: "Exact Matches", value: data.total_exact_match, bg: "linear-gradient(135deg, #ff416c, #ff4b2b)" },
208
+ { label: "Partial Matches", value: data.total_partial_match, bg: "linear-gradient(135deg, #1abc9c, #16a085)" },
209
+ { label: "Unmatched", value: data.total_unmatched, bg: "linear-gradient(135deg, #f39c12, #d35400)" },
210
+ { label: "Edited", value: data.total_no_review_needed, bg: "linear-gradient(135deg, #3498db, #2980b9)" },
211
+ { label: "Not Edited", value: data.total_needs_review, bg: "linear-gradient(135deg, #9b59b6, #8e44ad)" }
212
+ ];
213
+
214
+ d3.select("#cards")
215
+ .selectAll(".card")
216
+ .data(cardData)
217
+ .enter()
218
+ .append("div")
219
+ .attr("class", "card")
220
+ .style("background", d => d.bg)
221
+ .html(d => `<h3>${d.label}</h3><p>${d.value}</p>`);
222
+
223
+ // ---- Histogram of Similarity Scores ----
224
+ const histogramWidth = 500, histogramHeight = 350,
225
+ margin = {top: 20, right: 20, bottom: 50, left: 50};
226
+
227
+ const svgHist = d3.select("#histogram")
228
+ .attr("width", histogramWidth)
229
+ .attr("height", histogramHeight)
230
+ .append("g");
231
+
232
+ // Define a gradient for a 3D effect on bars
233
+ const defs = svgHist.append("defs");
234
+ const gradient = defs.append("linearGradient")
235
+ .attr("id", "barGradient")
236
+ .attr("x1", "0%")
237
+ .attr("y1", "0%")
238
+ .attr("x2", "0%")
239
+ .attr("y2", "100%");
240
+ gradient.append("stop")
241
+ .attr("offset", "0%")
242
+ .attr("stop-color", "#3498db")
243
+ .attr("stop-opacity", 1);
244
+ gradient.append("stop")
245
+ .attr("offset", "100%")
246
+ .attr("stop-color", "#2980b9")
247
+ .attr("stop-opacity", 1);
248
+
249
+ const scores = data.similarity_scores;
250
+ const x = d3.scaleLinear()
251
+ .domain([0, 100])
252
+ .range([margin.left, histogramWidth - margin.right]);
253
+
254
+ const bins = d3.bin()
255
+ .domain(x.domain())
256
+ .thresholds(x.ticks(20))
257
+ (scores);
258
+
259
+ const y = d3.scaleLinear()
260
+ .domain([0, d3.max(bins, d => d.length)])
261
+ .nice()
262
+ .range([histogramHeight - margin.bottom, margin.top]);
263
+
264
+ // Create groups for each bin and add interactivity (no static count labels)
265
+ const bar = svgHist.selectAll(".bar")
266
+ .data(bins)
267
+ .enter().append("g")
268
+ .attr("class", "bar")
269
+ .attr("transform", d => `translate(${x(d.x0)}, ${y(0)})`)
270
+ .on("mouseover", function(event, d) {
271
+ d3.select(this).select("rect")
272
+ .transition().duration(200)
273
+ .attr("fill", "#1abc9c");
274
+ d3.select("#tooltip")
275
+ .style("opacity", 1)
276
+ .html(`Range: ${d.x0.toFixed(2)} - ${d.x1.toFixed(2)}<br>Count: ${d.length}`)
277
+ .style("left", (event.pageX + 10) + "px")
278
+ .style("top", (event.pageY - 30) + "px");
279
+ })
280
+ .on("mouseout", function(event, d) {
281
+ d3.select(this).select("rect")
282
+ .transition().duration(200)
283
+ .attr("fill", "url(#barGradient)");
284
+ d3.select("#tooltip").style("opacity", 0);
285
+ });
286
+
287
+ bar.append("rect")
288
+ .attr("x", 1)
289
+ .attr("width", d => Math.max(0, x(d.x1) - x(d.x0) - 1))
290
+ .attr("height", 0)
291
+ .attr("fill", "url(#barGradient)")
292
+ .transition()
293
+ .duration(1000)
294
+ .attr("height", d => histogramHeight - margin.bottom - y(d.length))
295
+ .attr("transform", d => `translate(0, ${y(d.length) - y(0)})`);
296
+
297
+ // Add x-axis
298
+ const xAxis = d3.axisBottom(x);
299
+ svgHist.append("g")
300
+ .attr("transform", `translate(0, ${histogramHeight - margin.bottom})`)
301
+ .call(xAxis);
302
+ // x-axis label
303
+ svgHist.append("text")
304
+ .attr("class", "x label")
305
+ .attr("text-anchor", "middle")
306
+ .attr("x", histogramWidth / 2)
307
+ .attr("y", histogramHeight - 10)
308
+ .text("Similarity Score (0-100)");
309
+
310
+ // Add y-axis
311
+ const yAxis = d3.axisLeft(y);
312
+ svgHist.append("g")
313
+ .attr("transform", `translate(${margin.left},0)`)
314
+ .call(yAxis);
315
+ // y-axis label
316
+ svgHist.append("text")
317
+ .attr("class", "y label")
318
+ .attr("text-anchor", "middle")
319
+ .attr("transform", "rotate(-90)")
320
+ .attr("x", -histogramHeight / 2)
321
+ .attr("y", 15)
322
+ .text("Frequency");
323
+
324
+ // ---- Interactive Pie Chart for Matches Distribution ----
325
+ const pieWidth = 500, pieHeight = 350;
326
+ const radius = Math.min(pieWidth, pieHeight) / 2 - 20;
327
+
328
+ const svgPie = d3.select("#pieChart")
329
+ .attr("width", pieWidth)
330
+ .attr("height", pieHeight)
331
+ .append("g")
332
+ .attr("transform", `translate(${pieWidth/2}, ${pieHeight/2})`);
333
+
334
+ // Prepare pie chart data: Exact, Partial, and Unmatched
335
+ const pieData = [
336
+ { category: "Exact Matches", value: data.total_exact_match },
337
+ { category: "Partial Matches", value: data.total_partial_match },
338
+ { category: "Unmatched", value: data.total_unmatched }
339
+ ];
340
+ const totalMatches = d3.sum(pieData, d => d.value);
341
+
342
+ const color = d3.scaleOrdinal()
343
+ .domain(pieData.map(d => d.category))
344
+ .range(["#ff4b2b", "#16a085", "#d35400"]);
345
+
346
+ const pie = d3.pie()
347
+ .sort(null)
348
+ .value(d => d.value);
349
+ const arc = d3.arc()
350
+ .innerRadius(0)
351
+ .outerRadius(radius);
352
+ const arcHover = d3.arc()
353
+ .innerRadius(0)
354
+ .outerRadius(radius + 10);
355
+
356
+ const arcs = svgPie.selectAll(".arc")
357
+ .data(pie(pieData))
358
+ .enter()
359
+ .append("g")
360
+ .attr("class", "arc");
361
+
362
+ arcs.append("path")
363
+ .attr("d", arc)
364
+ .attr("fill", d => color(d.data.category))
365
+ .on("mouseover", function(event, d) {
366
+ d3.select(this)
367
+ .transition().duration(200)
368
+ .attr("d", arcHover);
369
+ })
370
+ .on("mouseout", function(event, d) {
371
+ d3.select(this)
372
+ .transition().duration(200)
373
+ .attr("d", arc);
374
+ });
375
+
376
+ // Add combined labels: category and percentage in each slice
377
+ arcs.append("text")
378
+ .attr("transform", d => `translate(${arc.centroid(d)})`)
379
+ .attr("dy", "0.35em")
380
+ .attr("text-anchor", "middle")
381
+ .style("fill", "#fff")
382
+ .style("font-size", "14px")
383
+ .text(d => {
384
+ let percent = ((d.data.value / totalMatches) * 100).toFixed(0);
385
+ return `${d.data.category}: ${percent}%`;
386
+ });
387
+
388
+ // ---- Interactive Line Chart of Similarity Scores ----
389
+ const lineChartWidth = 1000, lineChartHeight = 400;
390
+ const svgLine = d3.select("#lineChart")
391
+ .append("svg")
392
+ .attr("width", lineChartWidth)
393
+ .attr("height", lineChartHeight);
394
+
395
+ const xLine = d3.scaleLinear()
396
+ .domain([0, scores.length - 1])
397
+ .range([margin.left, lineChartWidth - margin.right]);
398
+ const yLine = d3.scaleLinear()
399
+ .domain([0, 100])
400
+ .range([lineChartHeight - margin.bottom, margin.top]);
401
+
402
+ const line = d3.line()
403
+ .x((d, i) => xLine(i))
404
+ .y(d => yLine(d))
405
+ .curve(d3.curveCatmullRom.alpha(0.5));
406
+
407
+ // Draw the line
408
+ svgLine.append("path")
409
+ .datum(scores)
410
+ .attr("fill", "none")
411
+ .attr("stroke", "#27ae60")
412
+ .attr("stroke-width", 3)
413
+ .attr("d", line);
414
+
415
+ // Draw interactive circles at data points
416
+ svgLine.selectAll("circle")
417
+ .data(scores)
418
+ .enter()
419
+ .append("circle")
420
+ .attr("cx", (d, i) => xLine(i))
421
+ .attr("cy", d => yLine(d))
422
+ .attr("r", 4)
423
+ .attr("fill", "#27ae60")
424
+ .on("mouseover", function(event, d) {
425
+ d3.select(this)
426
+ .transition().duration(200)
427
+ .attr("r", 7);
428
+ d3.select("#tooltip")
429
+ .style("opacity", 1)
430
+ .html(`Similarity: ${d.toFixed(2)}`)
431
+ .style("left", (event.pageX + 10) + "px")
432
+ .style("top", (event.pageY - 20) + "px");
433
+ })
434
+ .on("mouseout", function() {
435
+ d3.select(this)
436
+ .transition().duration(200)
437
+ .attr("r", 4);
438
+ d3.select("#tooltip").style("opacity", 0);
439
+ });
440
+
441
+ // Add x-axis for line chart
442
+ const xAxisLine = d3.axisBottom(xLine);
443
+ svgLine.append("g")
444
+ .attr("transform", `translate(0, ${lineChartHeight - margin.bottom})`)
445
+ .call(xAxisLine);
446
+ // x-axis label for line chart
447
+ svgLine.append("text")
448
+ .attr("class", "x label")
449
+ .attr("text-anchor", "middle")
450
+ .attr("x", lineChartWidth / 2)
451
+ .attr("y", lineChartHeight - 10)
452
+ .text("Index");
453
+
454
+ // Add y-axis for line chart
455
+ const yAxisLine = d3.axisLeft(yLine);
456
+ svgLine.append("g")
457
+ .attr("transform", `translate(${margin.left},0)`)
458
+ .call(yAxisLine);
459
+ // y-axis label for line chart
460
+ svgLine.append("text")
461
+ .attr("class", "y label")
462
+ .attr("text-anchor", "middle")
463
+ .attr("transform", "rotate(-90)")
464
+ .attr("x", -lineChartHeight / 2)
465
+ .attr("y", 15)
466
+ .text("Similarity Score");
467
+
468
+ // ---- Circular Cards for Similarity Statistics (Rounded to 2 Decimals) ----
469
+ const circularData = [
470
+ { label: "Avg Similarity", value: data.average_similarity },
471
+ { label: "Min Similarity", value: data.min_similarity },
472
+ { label: "Max Similarity", value: data.max_similarity }
473
+ ];
474
+ d3.select("#circularCards")
475
+ .selectAll(".circular-card")
476
+ .data(circularData)
477
+ .enter()
478
+ .append("div")
479
+ .attr("class", "circular-card")
480
+ .html(d => `<div><div>${d.label}</div><div>${(+d.value).toFixed(2)}</div></div>`);
481
+ }
482
+ </script>
483
+ </body>
484
  </html>