ulduldp commited on
Commit
dbe47f5
·
verified ·
1 Parent(s): 7b2ef27

Update public/index.html

Browse files
Files changed (1) hide show
  1. public/index.html +166 -74
public/index.html CHANGED
@@ -5,71 +5,102 @@
5
  <title>Live Logs</title>
6
 
7
  <style>
8
- body {
9
- margin: 0;
10
- background: #0b1020;
11
- color: #e2e8f0;
12
- font-family: monospace;
13
- display: flex;
14
- flex-direction: column;
15
- height: 90vh;
16
- }
17
 
18
- header {
19
- padding: 10px;
20
- background: #111827;
21
- border-bottom: 1px solid #1f2937;
22
- }
23
 
24
- #logs {
25
- flex: 1;
26
- overflow-y: auto;
27
- padding: 10px;
28
- font-size: 13px;
29
- }
30
 
31
- .log {
32
- margin-bottom: 6px;
33
- word-break: break-word;
34
- }
35
 
36
- .time {
37
- color: #64748b;
38
- margin-right: 6px;
39
- }
40
 
41
- footer {
42
- display: flex;
43
- padding: 8px;
44
- background: #111827;
45
- }
 
 
46
 
47
- input {
48
- flex: 1;
49
- padding: 10px;
50
- background: #0b1020;
51
- border: none;
52
- color: white;
53
- }
 
 
54
 
55
- button {
56
- margin-left: 8px;
57
- padding: 10px;
58
- background: #2563eb;
59
- border: none;
60
- color: white;
61
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  </style>
63
  </head>
64
 
65
  <body>
66
 
67
  <header>📡 Live Logs Terminal</header>
 
68
  <div id="logs"></div>
69
 
70
  <footer>
71
- <input id="cmd" placeholder="Enter command..." />
72
  <button onclick="sendCmd()">Send</button>
 
 
73
  </footer>
74
 
75
  <script src="/socket.io/socket.io.js"></script>
@@ -77,6 +108,7 @@ button {
77
  const socket = io();
78
  const logsDiv = document.getElementById('logs');
79
  const input = document.getElementById('cmd');
 
80
 
81
  // ===== CONFIG =====
82
  const LIMIT = 50;
@@ -86,7 +118,7 @@ let offset = 0;
86
  let loading = false;
87
  let hasMore = true;
88
 
89
- // ===== HELPERS =====
90
  function formatTime(ts) {
91
  return new Date(ts).toLocaleString('en-IN', {
92
  timeZone: 'Asia/Kolkata',
@@ -94,9 +126,11 @@ function formatTime(ts) {
94
  });
95
  }
96
 
 
97
  function createLogElement(log) {
98
  const div = document.createElement('div');
99
  div.className = 'log';
 
100
  div.innerHTML = `
101
  <span class="time">[${formatTime(log.timestamp)}]</span>
102
  ${log.html}
@@ -104,7 +138,26 @@ function createLogElement(log) {
104
  return div;
105
  }
106
 
107
- // ===== LOAD OLD LOGS =====
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  async function loadLogs() {
109
  if (loading || !hasMore) return;
110
  loading = true;
@@ -122,61 +175,100 @@ async function loadLogs() {
122
 
123
  offset += data.logs.length;
124
 
 
125
  logsDiv.scrollTop = logsDiv.scrollHeight - prevHeight;
126
 
127
  loading = false;
128
  }
129
 
130
- // ===== LIVE LOGS =====
131
- function addLog(log) {
132
- const div = createLogElement(log);
 
133
 
134
- const isNearBottom =
135
- logsDiv.scrollHeight - logsDiv.scrollTop <= logsDiv.clientHeight + 50;
136
 
137
- logsDiv.appendChild(div);
 
138
 
139
- // cleanup old DOM
140
- if (logsDiv.children.length > MAX_DOM_LOGS) {
141
- logsDiv.removeChild(logsDiv.firstChild);
142
- }
143
 
144
- if (isNearBottom) {
145
- logsDiv.scrollTop = logsDiv.scrollHeight;
146
- }
147
  }
148
 
149
- socket.on('log', addLog);
 
 
150
 
151
- // ===== SCROLL LOAD =====
152
- logsDiv.addEventListener('scroll', () => {
153
- if (logsDiv.scrollTop < 50) {
154
- loadLogs();
 
 
 
155
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  });
157
 
158
- // ===== SEND CMD =====
 
 
 
 
159
  function sendCmd() {
160
  const val = input.value.trim();
161
  if (!val) return;
162
 
163
  socket.emit('command', { command: val });
 
 
 
 
164
 
165
  if (val === "clear") {
166
  logsDiv.innerHTML = "";
 
 
167
  return;
168
  }
169
-
170
- input.value = '';
171
  }
172
 
173
- // enter key
174
- input.addEventListener('keypress', e => {
175
- if (e.key === 'Enter') sendCmd();
 
 
176
  });
177
 
178
  // ===== INIT =====
179
  loadLogs();
 
 
 
 
180
  </script>
181
 
182
  </body>
 
5
  <title>Live Logs</title>
6
 
7
  <style>
8
+ body {
9
+ margin: 0;
10
+ background: #0b1020;
11
+ color: #e2e8f0;
12
+ font-family: monospace;
13
+ display: flex;
14
+ flex-direction: column;
15
+ height: 90vh;
16
+ }
17
 
18
+ header {
19
+ padding: 10px;
20
+ background: #111827;
21
+ border-bottom: 1px solid #1f2937;
22
+ }
23
 
24
+ #logs {
25
+ flex: 1;
26
+ overflow-y: auto;
27
+ padding: 10px;
28
+ font-size: 13px;
29
+ }
30
 
31
+ .log {
32
+ margin-bottom: 6px;
33
+ word-break: break-word;
34
+ }
35
 
36
+ .time {
37
+ color: #64748b;
38
+ margin-right: 6px;
39
+ }
40
 
41
+ footer {
42
+ position: relative;
43
+ display: flex;
44
+ padding: 8px;
45
+ background: #111827;
46
+ border-top: 1px solid #1f2937;
47
+ }
48
 
49
+ input {
50
+ flex: 1;
51
+ padding: 10px;
52
+ background: #0b1020;
53
+ border: none;
54
+ color: white;
55
+ border-radius: 6px;
56
+ outline: none;
57
+ }
58
 
59
+ button {
60
+ margin-left: 8px;
61
+ padding: 10px 14px;
62
+ background: #2563eb;
63
+ border: none;
64
+ color: white;
65
+ border-radius: 6px;
66
+ }
67
+
68
+ #suggestions {
69
+ position: absolute;
70
+ bottom: 60px;
71
+ left: 10px;
72
+ right: 10px;
73
+ background: #111827;
74
+ border: 1px solid #1f2937;
75
+ border-radius: 6px;
76
+ max-height: 150px;
77
+ overflow-y: auto;
78
+ display: none;
79
+ z-index: 10;
80
+ }
81
+
82
+ .suggestion-item {
83
+ padding: 8px;
84
+ cursor: pointer;
85
+ }
86
+
87
+ .suggestion-item:hover {
88
+ background: #1f2937;
89
+ }
90
  </style>
91
  </head>
92
 
93
  <body>
94
 
95
  <header>📡 Live Logs Terminal</header>
96
+
97
  <div id="logs"></div>
98
 
99
  <footer>
100
+ <input id="cmd" placeholder="Enter command..." autocomplete="off" />
101
  <button onclick="sendCmd()">Send</button>
102
+
103
+ <div id="suggestions"></div>
104
  </footer>
105
 
106
  <script src="/socket.io/socket.io.js"></script>
 
108
  const socket = io();
109
  const logsDiv = document.getElementById('logs');
110
  const input = document.getElementById('cmd');
111
+ const suggestionBox = document.getElementById('suggestions');
112
 
113
  // ===== CONFIG =====
114
  const LIMIT = 50;
 
118
  let loading = false;
119
  let hasMore = true;
120
 
121
+ // ===== TIME =====
122
  function formatTime(ts) {
123
  return new Date(ts).toLocaleString('en-IN', {
124
  timeZone: 'Asia/Kolkata',
 
126
  });
127
  }
128
 
129
+ // ===== CREATE LOG ELEMENT =====
130
  function createLogElement(log) {
131
  const div = document.createElement('div');
132
  div.className = 'log';
133
+
134
  div.innerHTML = `
135
  <span class="time">[${formatTime(log.timestamp)}]</span>
136
  ${log.html}
 
138
  return div;
139
  }
140
 
141
+ // ===== LIVE LOG ADD =====
142
+ function addLog(log) {
143
+ const div = createLogElement(log);
144
+
145
+ const isNearBottom =
146
+ logsDiv.scrollHeight - logsDiv.scrollTop <= logsDiv.clientHeight + 50;
147
+
148
+ logsDiv.appendChild(div);
149
+
150
+ // 🧹 DOM cleanup
151
+ if (logsDiv.children.length > MAX_DOM_LOGS) {
152
+ logsDiv.removeChild(logsDiv.firstChild);
153
+ }
154
+
155
+ if (isNearBottom) {
156
+ logsDiv.scrollTop = logsDiv.scrollHeight;
157
+ }
158
+ }
159
+
160
+ // ===== LOAD OLD LOGS (PAGINATION) =====
161
  async function loadLogs() {
162
  if (loading || !hasMore) return;
163
  loading = true;
 
175
 
176
  offset += data.logs.length;
177
 
178
+ // maintain scroll position
179
  logsDiv.scrollTop = logsDiv.scrollHeight - prevHeight;
180
 
181
  loading = false;
182
  }
183
 
184
+ // ===== HISTORY =====
185
+ function getHistory() {
186
+ return JSON.parse(localStorage.getItem('cmd_history') || '[]');
187
+ }
188
 
189
+ function saveToHistory(cmd) {
190
+ let history = getHistory();
191
 
192
+ history = history.filter(c => c !== cmd);
193
+ history.unshift(cmd);
194
 
195
+ if (history.length > 50) history.pop();
 
 
 
196
 
197
+ localStorage.setItem('cmd_history', JSON.stringify(history));
 
 
198
  }
199
 
200
+ // ===== SUGGESTIONS =====
201
+ function showSuggestions(value) {
202
+ const history = getHistory();
203
 
204
+ const filtered = history.filter(cmd =>
205
+ cmd.toLowerCase().includes(value.toLowerCase())
206
+ );
207
+
208
+ if (!value || filtered.length === 0) {
209
+ suggestionBox.style.display = 'none';
210
+ return;
211
  }
212
+
213
+ suggestionBox.innerHTML = '';
214
+
215
+ filtered.slice(0, 5).forEach(cmd => {
216
+ const div = document.createElement('div');
217
+ div.className = 'suggestion-item';
218
+ div.textContent = cmd;
219
+
220
+ div.onclick = () => {
221
+ input.value = cmd;
222
+ suggestionBox.style.display = 'none';
223
+ };
224
+
225
+ suggestionBox.appendChild(div);
226
+ });
227
+
228
+ suggestionBox.style.display = 'block';
229
+ }
230
+
231
+ // ===== EVENTS =====
232
+ input.addEventListener('input', () => {
233
+ showSuggestions(input.value);
234
  });
235
 
236
+ input.addEventListener('keypress', e => {
237
+ if (e.key === 'Enter') sendCmd();
238
+ });
239
+
240
+ // ===== SEND COMMAND =====
241
  function sendCmd() {
242
  const val = input.value.trim();
243
  if (!val) return;
244
 
245
  socket.emit('command', { command: val });
246
+ saveToHistory(val);
247
+
248
+ input.value = '';
249
+ suggestionBox.style.display = 'none';
250
 
251
  if (val === "clear") {
252
  logsDiv.innerHTML = "";
253
+ offset = 0;
254
+ hasMore = true;
255
  return;
256
  }
 
 
257
  }
258
 
259
+ // ===== SCROLL LOAD =====
260
+ logsDiv.addEventListener('scroll', () => {
261
+ if (logsDiv.scrollTop < 50) {
262
+ loadLogs();
263
+ }
264
  });
265
 
266
  // ===== INIT =====
267
  loadLogs();
268
+
269
+ // ===== LIVE SOCKET =====
270
+ socket.on('log', addLog);
271
+
272
  </script>
273
 
274
  </body>