Playwright-manipulator / frontend.py
shethjenil's picture
Upload 2 files
04f1ca5 verified
import json
import gradio as gr
from backend import (
task_queue,
result_queue,
BROWSER_STATE,
BROWSER_LOCK,
start_worker_thread,
stop_worker_thread,
StorageState
)
# ─────────────────────────────
# Frontend callbacks (Gradio)
# ─────────────────────────────
def start_browser(storage_state_file:bytes):
with BROWSER_LOCK:
running = BROWSER_STATE.running
if running:
with BROWSER_LOCK:
tabs = list(BROWSER_STATE.pages.keys())
active = BROWSER_STATE.active_page
return "Browser is already running.", None, gr.update(choices=tabs, value=active)
start_worker_thread(StorageState(json.loads(storage_state_file)) if storage_state_file else None)
return "Browser Started!", None, gr.update(choices=["Tab-1"], value="Tab-1")
def stop_browser():
with BROWSER_LOCK:
running = BROWSER_STATE.running
if not running:
return "Browser is not running.", None, gr.update(choices=[], value=None)
stop_worker_thread()
with BROWSER_LOCK:
BROWSER_STATE.pages.clear()
BROWSER_STATE.active_page = None
return "Browser Closed!", None, gr.update(choices=[], value=None)
def execute_code(code):
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "eval", "code": code})
return result_queue.get()
def navigate(url):
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "goto", "url": url})
return result_queue.get()
def click(selector):
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "click", "selector": selector})
return result_queue.get()
def type_text(selector, text):
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "type", "selector": selector, "text": text})
return result_queue.get()
def new_tab():
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "new_tab"})
r, screenshot = result_queue.get()
with BROWSER_LOCK:
tabs = list(BROWSER_STATE.pages.keys())
active = BROWSER_STATE.active_page
return r, screenshot, gr.update(choices=tabs, value=active)
def close_tab(tab):
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "close_tab", "tab": tab})
r, screenshot = result_queue.get()
with BROWSER_LOCK:
tabs = list(BROWSER_STATE.pages.keys())
active = BROWSER_STATE.active_page
return r, screenshot, gr.update(choices=tabs, value=active)
def switch_tab(tab):
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "switch_tab", "tab": tab})
r, screenshot = result_queue.get()
with BROWSER_LOCK:
tabs = list(BROWSER_STATE.pages.keys())
active = BROWSER_STATE.active_page
return r, screenshot, gr.update(choices=tabs, value=active)
def inspect_element(selector):
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "inspect", "selector": selector})
return result_queue.get()
def show_network_logs():
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "get_network_logs"})
return result_queue.get()
def show_console_logs():
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "get_console_logs"})
return result_queue.get()
def clear_logs():
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "clear_logs"})
return result_queue.get()
def start_recording():
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "start_record"})
return result_queue.get()
def stop_recording():
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "stop_record"})
return result_queue.get()
def play_macro():
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "play_macro"})
return result_queue.get()
def capture_screenshot():
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "take_screenshot"})
return result_queue.get()
def find_template(template_img):
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({"cmd": "find_template", "template": template_img})
return result_queue.get()
def handle_click(event: gr.SelectData, click_type, last_image):
x, y = event.index
if last_image is None:
return "No screenshot available. Take screenshot first.", None
img_w, img_h = last_image.size
with BROWSER_LOCK:
if not BROWSER_STATE.running:
return "Start browser first.", None
task_queue.put({
"cmd": "click_xy",
"x": x,
"y": y,
"img_w": img_w,
"img_h": img_h,
"click_type": click_type
})
return result_queue.get()
# ─────────────────────────────
# Gradio UI
# ─────────────────────────────
with gr.Blocks() as app:
gr.Markdown("## πŸ”₯ Advanced Playwright Control Panel (DOM + Logs + Macro + Vision RPA)")
state_file = gr.File(label="PlayWright State File",file_types=['.json'],type="binary")
with gr.Row():
start_btn = gr.Button("Open Browser")
stop_btn = gr.Button("Close Browser")
tabs_dropdown = gr.Dropdown(label="Tabs", choices=[], value=None)
with gr.Tab("Browse"):
with gr.Row():
url_box = gr.Textbox(label="URL", scale=4)
nav_btn = gr.Button("Go", scale=1)
with gr.Row():
sel_box = gr.Textbox(label="Selector (CSS)", scale=3)
click_btn = gr.Button("Click", scale=1)
type_box = gr.Textbox(label="Type Text", scale=3)
type_btn = gr.Button("Type", scale=1)
with gr.Tab("Inspect / Code"):
with gr.Row():
inspect_sel = gr.Textbox(label="Inspect Selector (CSS)")
inspect_btn = gr.Button("Inspect + Generate XPath")
code_input = gr.TextArea(label="Python Code (eval in Playwright worker - restricted)")
run_btn = gr.Button("Run Code")
with gr.Tab("Logs"):
with gr.Row():
net_btn = gr.Button("Show Network Logs")
cons_btn = gr.Button("Show Console Logs")
clear_logs_btn = gr.Button("Clear Logs")
with gr.Tab("Tabs & Macros"):
with gr.Row():
new_tab_btn = gr.Button("New Tab")
close_tab_btn = gr.Button("Close Selected Tab")
switch_tab_btn = gr.Button("Switch Tab")
with gr.Row():
start_rec_btn = gr.Button("Start Macro Recording")
stop_rec_btn = gr.Button("Stop Recording")
play_macro_btn = gr.Button("Play Recorded Macro")
with gr.Tab("Vision Tools"):
capture_btn = gr.Button("πŸ“Έ Capture Screenshot")
click_type = gr.Radio(
["left", "double", "right", "hover"],
value="left",
label="Click Type"
)
template_img = gr.Image(
label="Template Image (for OpenCV match)",
type="pil"
)
find_template_btn = gr.Button("πŸ” Find Template on Page")
output_text = gr.TextArea(label="Output")
output_image = gr.Image(label="Screenshot", type="pil")
# screenshot click handler
output_image.select(
handle_click,
inputs=[click_type, output_image],
outputs=[output_text, output_image]
)
# Bindings
start_btn.click(start_browser, inputs=[state_file], outputs=[output_text, output_image, tabs_dropdown])
stop_btn.click(stop_browser, outputs=[output_text, output_image, tabs_dropdown])
new_tab_btn.click(new_tab, outputs=[output_text, output_image, tabs_dropdown])
close_tab_btn.click(close_tab, inputs=tabs_dropdown, outputs=[output_text, output_image, tabs_dropdown])
switch_tab_btn.click(switch_tab, inputs=tabs_dropdown, outputs=[output_text, output_image, tabs_dropdown])
nav_btn.click(navigate, inputs=url_box, outputs=[output_text, output_image])
click_btn.click(click, inputs=sel_box, outputs=[output_text, output_image])
type_btn.click(type_text, inputs=[sel_box, type_box], outputs=[output_text, output_image])
run_btn.click(execute_code, inputs=code_input, outputs=[output_text, output_image])
inspect_btn.click(inspect_element, inputs=inspect_sel, outputs=[output_text, output_image])
net_btn.click(show_network_logs, outputs=[output_text, output_image])
cons_btn.click(show_console_logs, outputs=[output_text, output_image])
clear_logs_btn.click(clear_logs, outputs=[output_text, output_image])
start_rec_btn.click(start_recording, outputs=[output_text, output_image])
stop_rec_btn.click(stop_recording, outputs=[output_text, output_image])
play_macro_btn.click(play_macro, outputs=[output_text, output_image])
capture_btn.click(capture_screenshot, outputs=[output_text, output_image])
find_template_btn.click(find_template, inputs=[template_img], outputs=[output_text, output_image])
if __name__ == "__main__":
app.launch()