forked from thinhhoangpham/tcp_timearcs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathattack_timearcs.html
More file actions
146 lines (146 loc) · 7.15 KB
/
attack_timearcs.html
File metadata and controls
146 lines (146 loc) · 7.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Network TimeArcs</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
color: #212529;
background: #f8f9fa;
}
header {
padding: 12px 16px;
background: #ffffff;
border-bottom: 1px solid #e9ecef;
position: sticky;
top: 0;
z-index: 100;
}
.header-controls {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.secondary-controls {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
padding: 12px 16px 8px 16px;
background: #ffffff;
border-bottom: 1px solid #e9ecef;
position: sticky;
top: 48px;
z-index: 99;
}
main { padding: 8px 16px 12px 16px; }
.top-bar {
position: sticky;
top: 110px;
z-index: 98;
background: #ffffff;
border-bottom: 1px solid #e9ecef;
padding: 8px 0;
}
#axis-top { display: block; height: 36px; }
#chart-container {
background: #fff;
border: 1px solid #e9ecef;
border-radius: 6px;
padding: 8px;
overflow: auto;
min-height: 400px;
margin-top: 8px;
position: relative;
}
.row-line { stroke: #e9ecef; stroke-width: 1; }
.ip-label { font-size: 8px; fill: #343a40; }
.time-axis text { font-size: 10px; fill: #000; }
.time-axis path, .time-axis line { stroke: #000; }
.arc { fill: none; stroke-opacity: 0.8; pointer-events: stroke; }
.arc:hover { stroke-opacity: 1; }
.legend { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin: 0; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.swatch { width: 12px; height: 12px; border-radius: 2px; border: 1px solid #dee2e6; }
.controls { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.hint { color: #6c757d; font-size: 12px; }
#status { color: #6c757d; font-size: 12px; margin-left: auto; white-space: nowrap; }
.tooltip { position: fixed; background: rgba(0,0,0,0.85); color: #fff; padding: 8px 10px; border-radius: 4px; font-size: 12px; pointer-events: none; display: none; z-index: 99999; }
</style>
<link rel="preconnect" href="https://d3js.org" />
<link rel="dns-prefetch" href="https://d3js.org" />
</head>
<body>
<header>
<div class="header-controls">
<label for="fileInput" style="font-weight:600;">Upload CSV(s)</label>
<input id="fileInput" type="file" accept=".csv" multiple />
<label for="ipMapInput" style="font-weight:600;">IP Map JSON</label>
<input id="ipMapInput" type="file" accept=".json" />
<label for="eventMapInput" style="font-weight:600;">Event Type Map JSON</label>
<input id="eventMapInput" type="file" accept=".json" />
<div id="status">Waiting for data…</div>
</div>
</header>
<div class="secondary-controls">
<fieldset style="border:1px solid #dee2e6; padding:4px 8px; border-radius:4px; display:flex; gap:8px; align-items:center;">
<legend style="font-size:12px; padding:0 4px; font-weight:600;">Label Mode</legend>
<label style="display:flex; align-items:center; gap:4px; font-size:12px; cursor:pointer;">
<input type="radio" name="labelMode" value="attack" id="labelModeAttack" checked>
<span>Attack</span>
</label>
<label style="display:flex; align-items:center; gap:4px; font-size:12px; cursor:pointer;">
<input type="radio" name="labelMode" value="attack_group" id="labelModeAttackGroup">
<span>Attack Group</span>
</label>
</fieldset>
<button id="lensingToggle" style="padding:6px 12px; border:1px solid #dee2e6; border-radius:4px; background:#fff; cursor:pointer; font-size:12px; font-weight:600; transition: all 0.2s;" title="Toggle lensing mode (Shift + L)">
<span>🔍 Lensing</span>
<span style="font-size:10px; opacity:0.7; margin-left:4px;">(⇧L)</span>
</button>
<button id="resetFisheyeBtn" style="padding:6px 12px; border:1px solid #dee2e6; border-radius:4px; background:#fff; cursor:pointer; font-size:12px; font-weight:600; transition: all 0.2s;" title="Reset fisheye effect to original positions">
<span>↺ Reset</span>
</button>
<div style="display:flex; align-items:center; gap:8px; padding:4px 8px; border:1px solid #dee2e6; border-radius:4px;">
<label for="lensingMulSlider" style="font-size:12px; font-weight:600; white-space:nowrap;">Zoom:</label>
<input type="range" id="lensingMulSlider" min="2" max="100" step="1" value="5" style="width:100px; cursor:pointer;" />
<span id="lensingMulValue" style="font-size:12px; min-width:24px; text-align:right;">5x</span>
</div>
<div id="fisheyeModeIndicator" style="display:none; font-size:11px; padding:4px 8px; background:#f8f9fa; border:1px solid #dee2e6; border-radius:4px; font-weight:600; color:#495057;">
<span id="fisheyeModeText">Both Axes</span>
</div>
<div style="border-left: 2px solid #dee2e6; height: 30px; margin: 0 4px;"></div>
<button id="brushToggle" style="padding:6px 12px; border:1px solid #dee2e6; border-radius:4px; background:#fff; cursor:pointer; font-size:12px; font-weight:600; transition: all 0.2s;" title="Enable brush selection to export data (Shift + B)">
<span>📐 Enable Brush</span>
<span style="font-size:10px; opacity:0.7; margin-left:4px;">(⇧B)</span>
</button>
<button id="clearBrush" style="padding:6px 12px; border:1px solid #dee2e6; border-radius:4px; background:#fff; cursor:pointer; font-size:12px; font-weight:600; transition: all 0.2s;" title="Clear brush selection">
<span>✕ Clear</span>
</button>
<button id="exportSelection" style="padding:6px 12px; border:1px solid #dee2e6; border-radius:4px; background:#fff; cursor:pointer; font-size:12px; font-weight:600; transition: all 0.2s; background:#007bff; color:#fff; border-color:#007bff;" title="Export selected arcs for processing">
<span>⬇ Export Selection</span>
</button>
<div class="hint" style="margin-left: auto;">
💡 Press <kbd style="padding:2px 6px; background:#f8f9fa; border:1px solid #dee2e6; border-radius:3px; font-size:11px; font-family:monospace;">Shift + L</kbd> to toggle lensing | <kbd style="padding:2px 6px; background:#f8f9fa; border:1px solid #dee2e6; border-radius:3px; font-size:11px; font-family:monospace;">Shift + B</kbd> for brush | 🔍 Top edge: horizontal zoom, Left edge: vertical zoom
</div>
</div>
<main>
<div class="top-bar">
<div class="legend" id="legend" style="margin-bottom:6px;"></div>
</div>
<div id="chart-container">
<div style="position: sticky; top: 0; z-index: 10; background: #fff; border-bottom: 1px solid #eee;">
<svg id="axis-top"></svg>
</div>
<svg id="chart" width="1200" height="600" aria-label="TimeArcs chart"></svg>
</div>
</main>
<div id="tooltip" class="tooltip"></div>
<script type="module" src="./attack_timearcs2.js"></script>
</body>
</html>