simoncck commited on
Commit
ffa3383
ยท
verified ยท
1 Parent(s): e908443

Update browser_automation_ui.html

Browse files
Files changed (1) hide show
  1. browser_automation_ui.html +39 -68
browser_automation_ui.html CHANGED
@@ -1,5 +1,7 @@
1
  <!-- ========================= Browser Automation UI =========================
2
- Refactor: fullโ€‘screen screenshot, overlay logs, collapsible side panel
 
 
3
  ============================================================================ -->
4
  <!DOCTYPE html>
5
  <html lang="en">
@@ -16,13 +18,14 @@
16
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Side panel */
17
  .side-panel{position:fixed;left:0;top:0;width:var(--panel-w);height:100%;background:var(--bg);box-shadow:2px 0 6px rgba(0,0,0,.12);transition:transform .3s ease;z-index:900;overflow-y:auto}
18
  .side-panel.closed{transform:translateX(-100%)}
19
- .panel-toggle{position:absolute;right:-24px;top:12px;width:24px;height:24px;border:none;border-radius:4px;background:var(--accent);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:16px;}
20
  .panel-content{padding:14px 16px 40px 16px}
21
  h3{font-size:16px;margin-bottom:6px;color:var(--dark)}
22
  .btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:none;border-radius:6px;font-size:13px;cursor:pointer}
23
  .btn-primary{background:var(--accent);color:#fff}
24
  .btn-secondary{background:#e2e8f0;color:#334155}
25
  .btn-danger{background:#ef4444;color:#fff}
 
26
  .form-group{display:flex;flex-direction:column;margin-bottom:8px}
27
  .form-group input,.form-group select{padding:6px 8px;border:1px solid #cbd5e1;border-radius:4px;font-size:13px}
28
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Main screenshot area */
@@ -32,6 +35,17 @@
32
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Log overlay */
33
  #logOverlay{position:fixed;left:0;bottom:0;width:100%;height:20vh;background:rgba(30,41,59,0.7);color:#f1f5f9;font-size:12px;overflow-y:auto;padding:6px 10px;z-index:950;backdrop-filter:blur(3px)}
34
  #logOverlay pre{margin:0;white-space:pre-wrap;word-break:break-word}
 
 
 
 
 
 
 
 
 
 
 
35
  </style>
36
  </head>
37
  <body>
@@ -45,7 +59,10 @@
45
  <div class="form-group"><button class="btn btn-primary" onclick="launchBrowser()"><i class="lucide lucide-rocket"></i>Launch</button></div>
46
  <div class="form-group"><input id="navUrl" placeholder="https://example.com"/></div>
47
  <div class="form-group"><button class="btn btn-secondary" onclick="navigate()"><i class="lucide lucide-globe"></i>Navigate</button></div>
48
- <div class="form-group"><button class="btn btn-secondary" onclick="captureScreenshot()"><i class="lucide lucide-camera"></i>Screenshot</button></div>
 
 
 
49
  <div class="form-group"><button class="btn btn-danger" onclick="closeAllSessions()"><i class="lucide lucide-trash-2"></i>Closeย All</button></div>
50
  </section>
51
  <hr style="margin:12px 0;border:none;border-top:1px solid #e2e8f0"/>
@@ -60,13 +77,14 @@
60
  </select></div>
61
  <div class="form-group" id="typeTextGroup" style="display:none"><input id="typeText" placeholder="text to type"/></div>
62
  <button class="btn btn-primary" onclick="elementAction()"><i class="lucide lucide-mouse-pointer-click"></i>Run</button>
 
63
  </section>
64
  <hr style="margin:12px 0;border:none;border-top:1px solid #e2e8f0"/>
65
  <!-- Session Manager -->
66
  <section>
67
  <h3>Sessions</h3>
68
  <button class="btn btn-secondary btn-sm" style="margin-bottom:6px" onclick="refreshSessions()"><i class="lucide lucide-refresh-ccw"></i>Refresh</button>
69
- <ul id="sessionList" class="session-list"></ul>
70
  </section>
71
  </div>
72
  </aside>
@@ -79,6 +97,13 @@
79
  <!-- โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Log Overlay โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ -->
80
  <div id="logOverlay"><pre id="logText"></pre></div>
81
 
 
 
 
 
 
 
 
82
  <!-- โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Scripts โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ -->
83
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lucide/0.263.1/lucide.min.js"></script>
84
  <script>
@@ -88,76 +113,22 @@
88
  function log(msg){const pre=document.getElementById('logText');pre.textContent+=`\n${new Date().toLocaleTimeString()} ${msg}`;pre.parentElement.scrollTop=pre.parentElement.scrollHeight}
89
 
90
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Global state โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
91
- let currentSessionId=null;
92
 
93
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Side panel toggle โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
94
  const panel=document.getElementById('sidePanel');
95
  const mainArea=document.getElementById('mainArea');
96
  document.getElementById('togglePanel').onclick=()=>{
97
- panel.classList.toggle('closed');
98
- mainArea.classList.toggle('with-panel');
99
- document.getElementById('togglePanel').textContent=panel.classList.contains('closed')?'โฏ':'โฎ';
100
- };
101
 
102
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Browser controls โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
103
- async function launchBrowser(){
104
- const res=await api('/api/browser/launch',{});
105
- if(res.session_id){currentSessionId=res.session_id;log(`Launched session ${res.session_id}`);refreshSessions();captureScreenshot();}
106
- }
107
- async function navigate(){
108
- if(!currentSessionId)return alert('No session');
109
- const url=document.getElementById('navUrl').value.trim();
110
- if(!url)return;
111
- await api('/api/browser/navigate',{session_id:currentSessionId,url});
112
- log(`Navigated to ${url}`);
113
- captureScreenshot();
114
- }
115
- async function captureScreenshot(){
116
- if(!currentSessionId)return;
117
- const res=await api('/api/browser/screenshot',{session_id:currentSessionId,full_page:false});
118
- if(res.screenshot){document.getElementById('screenshot').src=`data:image/png;base64,${res.screenshot}`;log('Screenshot updated');}
119
- }
120
- async function closeAllSessions(){
121
- const items=[...document.querySelectorAll('.session-item')];
122
- if (items.length === 0) return;
123
- if (!confirm(`Close ALL ${items.length} sessions?`)) return;
124
- for(const li of items){await api(`/api/browser/close/${li.dataset.id}`,{});}
125
- currentSessionId=null;refreshSessions();log('Closed all sessions');document.getElementById('screenshot').src='';
126
- }
127
 
128
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Element interaction โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
129
- document.getElementById('action').addEventListener('change',e=>{
130
- document.getElementById('typeTextGroup').style.display=e.target.value==='type'?'block':'none';
131
- });
132
- async function elementAction(){
133
- if(!currentSessionId)return;
134
- const selector=document.getElementById('selector').value.trim();
135
- if(!selector)return;
136
- const action=document.getElementById('action').value;
137
- const value=action==='type'?document.getElementById('typeText').value:'';
138
- const res=await api('/api/elements/action',{session_id:currentSessionId,selector,action,value});
139
- log(`Action ${action} on ${selector} โ†’ ${JSON.stringify(res)}`);
140
- if(action==='textContent'&&res.text)alert(`Text: ${res.text}`);
141
- captureScreenshot();
142
- }
143
-
144
- /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Session manager โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
145
- async function refreshSessions(){
146
- const listEl=document.getElementById('sessionList');
147
- listEl.innerHTML='';
148
- const {sessions=[]}=await apiGet('/api/sessions');
149
- sessions.forEach(s=>{
150
- const li=document.createElement('li');li.className='session-item';li.textContent=s.session_id;li.dataset.id=s.session_id;
151
- li.style.cursor='pointer';li.style.padding='4px 6px';li.style.borderBottom='1px solid #e2e8f0';
152
- if(s.session_id===currentSessionId){li.style.background='#dbeafe';}
153
- li.onclick=()=>{currentSessionId=s.session_id;refreshSessions();captureScreenshot();log(`Switched to session ${s.session_id}`);} ;
154
- listEl.appendChild(li);
155
- });
156
- }
157
-
158
- // initial icon replacement
159
- lucide.createIcons();
160
- refreshSessions();
161
- </script>
162
- </body>
163
- </html>
 
1
  <!-- ========================= Browser Automation UI =========================
2
+ Fullโ€‘screen screenshot | overlay logs | collapsible side panel
3
+ Added: download screenshot, perโ€‘session close, confirm on mass close,
4
+ Inspect overlay listing selectors with hover details
5
  ============================================================================ -->
6
  <!DOCTYPE html>
7
  <html lang="en">
 
18
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Side panel */
19
  .side-panel{position:fixed;left:0;top:0;width:var(--panel-w);height:100%;background:var(--bg);box-shadow:2px 0 6px rgba(0,0,0,.12);transition:transform .3s ease;z-index:900;overflow-y:auto}
20
  .side-panel.closed{transform:translateX(-100%)}
21
+ .panel-toggle{position:absolute;right:-24px;top:12px;width:24px;height:24px;border:none;border-radius:4px;background:var(--accent);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:16px}
22
  .panel-content{padding:14px 16px 40px 16px}
23
  h3{font-size:16px;margin-bottom:6px;color:var(--dark)}
24
  .btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:none;border-radius:6px;font-size:13px;cursor:pointer}
25
  .btn-primary{background:var(--accent);color:#fff}
26
  .btn-secondary{background:#e2e8f0;color:#334155}
27
  .btn-danger{background:#ef4444;color:#fff}
28
+ .btn-sm{padding:4px 8px;font-size:11px}
29
  .form-group{display:flex;flex-direction:column;margin-bottom:8px}
30
  .form-group input,.form-group select{padding:6px 8px;border:1px solid #cbd5e1;border-radius:4px;font-size:13px}
31
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Main screenshot area */
 
35
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Log overlay */
36
  #logOverlay{position:fixed;left:0;bottom:0;width:100%;height:20vh;background:rgba(30,41,59,0.7);color:#f1f5f9;font-size:12px;overflow-y:auto;padding:6px 10px;z-index:950;backdrop-filter:blur(3px)}
37
  #logOverlay pre{margin:0;white-space:pre-wrap;word-break:break-word}
38
+ /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Session list */
39
+ .session-item{display:flex;align-items:center;justify-content:space-between;padding:4px 6px;border-bottom:1px solid #e2e8f0;font-family:"Source Code Pro",monospace;font-size:12px}
40
+ .session-id{cursor:pointer;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
41
+ .session-item.active{background:#dbeafe}
42
+ .session-close{background:none;border:none;color:#ef4444;cursor:pointer;font-size:14px;width:18px;height:18px;display:flex;align-items:center;justify-content:center}
43
+ /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Inspect overlay */
44
+ #inspectOverlay{position:fixed;right:0;top:0;width:300px;height:100%;background:rgba(15,23,42,0.9);color:#f8fafc;z-index:940;transform:translateX(100%);transition:transform .3s ease;overflow-y:auto;padding:10px;font-size:12px}
45
+ #inspectOverlay.open{transform:translateX(0)}
46
+ #inspectList li{padding:4px 6px;border-bottom:1px solid rgba(255,255,255,.08);cursor:pointer}
47
+ #inspectList li:hover{background:rgba(255,255,255,.08)}
48
+ #inspectDetail{margin-top:6px;font-size:11px;color:#cbd5e1;white-space:pre-wrap}
49
  </style>
50
  </head>
51
  <body>
 
59
  <div class="form-group"><button class="btn btn-primary" onclick="launchBrowser()"><i class="lucide lucide-rocket"></i>Launch</button></div>
60
  <div class="form-group"><input id="navUrl" placeholder="https://example.com"/></div>
61
  <div class="form-group"><button class="btn btn-secondary" onclick="navigate()"><i class="lucide lucide-globe"></i>Navigate</button></div>
62
+ <div class="form-group" style="display:flex;gap:6px">
63
+ <button class="btn btn-secondary" onclick="captureScreenshot()"><i class="lucide lucide-camera"></i>Capture</button>
64
+ <button class="btn btn-secondary" onclick="downloadCurrentScreenshot()"><i class="lucide lucide-download"></i>Download</button>
65
+ </div>
66
  <div class="form-group"><button class="btn btn-danger" onclick="closeAllSessions()"><i class="lucide lucide-trash-2"></i>Closeย All</button></div>
67
  </section>
68
  <hr style="margin:12px 0;border:none;border-top:1px solid #e2e8f0"/>
 
77
  </select></div>
78
  <div class="form-group" id="typeTextGroup" style="display:none"><input id="typeText" placeholder="text to type"/></div>
79
  <button class="btn btn-primary" onclick="elementAction()"><i class="lucide lucide-mouse-pointer-click"></i>Run</button>
80
+ <button class="btn btn-secondary btn-sm" style="margin-left:6px" onclick="inspectPage()"><i class="lucide lucide-list"></i>Inspect</button>
81
  </section>
82
  <hr style="margin:12px 0;border:none;border-top:1px solid #e2e8f0"/>
83
  <!-- Session Manager -->
84
  <section>
85
  <h3>Sessions</h3>
86
  <button class="btn btn-secondary btn-sm" style="margin-bottom:6px" onclick="refreshSessions()"><i class="lucide lucide-refresh-ccw"></i>Refresh</button>
87
+ <ul id="sessionList"></ul>
88
  </section>
89
  </div>
90
  </aside>
 
97
  <!-- โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Log Overlay โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ -->
98
  <div id="logOverlay"><pre id="logText"></pre></div>
99
 
100
+ <!-- โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Inspect Overlay โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ -->
101
+ <aside id="inspectOverlay">
102
+ <h3 style="color:#38bdf8;margin-bottom:8px">Selectors</h3>
103
+ <ul id="inspectList"></ul>
104
+ <div id="inspectDetail"></div>
105
+ </aside>
106
+
107
  <!-- โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Scripts โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ -->
108
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lucide/0.263.1/lucide.min.js"></script>
109
  <script>
 
113
  function log(msg){const pre=document.getElementById('logText');pre.textContent+=`\n${new Date().toLocaleTimeString()} ${msg}`;pre.parentElement.scrollTop=pre.parentElement.scrollHeight}
114
 
115
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Global state โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
116
+ let currentSessionId=null;let lastScreenshotData=null;
117
 
118
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Side panel toggle โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
119
  const panel=document.getElementById('sidePanel');
120
  const mainArea=document.getElementById('mainArea');
121
  document.getElementById('togglePanel').onclick=()=>{
122
+ panel.classList.toggle('closed');mainArea.classList.toggle('with-panel');
123
+ document.getElementById('togglePanel').textContent=panel.classList.contains('closed')?'โฏ':'โฎ';};
 
 
124
 
125
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Browser controls โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
126
+ async function launchBrowser(){const res=await api('/api/browser/launch',{});if(res.session_id){currentSessionId=res.session_id;log(`Launched session ${res.session_id}`);refreshSessions();captureScreenshot();}}
127
+ async function navigate(){if(!currentSessionId)return alert('No session');const url=document.getElementById('navUrl').value.trim();if(!url)return;await api('/api/browser/navigate',{session_id:currentSessionId,url});log(`Navigated to ${url}`);captureScreenshot();}
128
+ async function captureScreenshot(){if(!currentSessionId)return;const res=await api('/api/browser/screenshot',{session_id:currentSessionId,full_page:false});if(res.screenshot){lastScreenshotData=res.screenshot;document.getElementById('screenshot').src=`data:image/png;base64,${res.screenshot}`;log('Screenshot updated');}}
129
+ function downloadCurrentScreenshot(){if(!lastScreenshotData)return alert('No screenshot');const a=document.createElement('a');a.href=`data:image/png;base64,${lastScreenshotData}`;a.download=`screenshot_${Date.now()}.png`;a.click();}
130
+ async function closeAllSessions(){const items=[...document.querySelectorAll('.session-item')];if(items.length===0)return alert('No sessions');if(!confirm(`Close ALL ${items.length} sessions?`))return;for(const li of items){await api(`/api/browser/close/${li.dataset.id}`,{});}currentSessionId=null;refreshSessions();log('Closed all sessions');document.getElementById('screenshot').src='';lastScreenshotData=null;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
  /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Element interaction โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
133
+ document.getElementById('action').addEventListener('change',e=>{document.getElementById('typeTextGroup').style.display=e.target.value==='type'?'block':'none';});
134
+ async function elementAction(){if(!currentSessionId)return;const selector=document.getElementById('selector').