Spaces:
Running
Running
""" | |
Screenshot capture tool for ChatUI Helper documentation | |
Uses Playwright to automate browser interactions and capture screenshots | |
""" | |
import asyncio | |
import os | |
from pathlib import Path | |
from playwright.async_api import async_playwright | |
import logging | |
from datetime import datetime | |
# Configure logging | |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') | |
logger = logging.getLogger(__name__) | |
# Screenshot configurations for each documentation step | |
SCREENSHOT_CONFIGS = [ | |
{ | |
"name": "main_interface", | |
"url": "http://localhost:7860", | |
"description": "Main interface with all tabs", | |
"actions": [], | |
"wait_time": 2000, | |
"selector": None, # Full page | |
"output": "img/main_interface.png" | |
}, | |
{ | |
"name": "config_tab", | |
"url": "http://localhost:7860", | |
"description": "Configuration tab", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Configure Space')"} | |
], | |
"wait_time": 1000, | |
"selector": None, | |
"output": "img/config_tab.png" | |
}, | |
{ | |
"name": "template_dropdown", | |
"url": "http://localhost:7860", | |
"description": "Template selection dropdown", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Configure Space')"}, | |
{"type": "click", "selector": "div[data-testid='dropdown']", "nth": 0} | |
], | |
"wait_time": 1000, | |
"selector": "div.dropdown-menu", | |
"output": "img/template_dropdown.png" | |
}, | |
{ | |
"name": "preview_tab", | |
"url": "http://localhost:7860", | |
"description": "Preview tab with chat interface", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Preview')"} | |
], | |
"wait_time": 2000, | |
"selector": None, | |
"output": "img/preview_tab.png" | |
}, | |
{ | |
"name": "preview_chat_example", | |
"url": "http://localhost:7860", | |
"description": "Preview tab with example conversation", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Preview')"}, | |
{"type": "wait", "time": 2000}, | |
{"type": "type", "selector": "textarea[placeholder*='Type a message']", "text": "Hello! Can you help me understand quantum mechanics?"}, | |
{"type": "click", "selector": "button:has-text('Send')"}, | |
{"type": "wait", "time": 3000} | |
], | |
"wait_time": 1000, | |
"selector": None, | |
"output": "img/preview_chat_example.png" | |
}, | |
{ | |
"name": "docs_tab", | |
"url": "http://localhost:7860", | |
"description": "Documentation tab", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Docs')"} | |
], | |
"wait_time": 1000, | |
"selector": None, | |
"output": "img/docs_tab.png" | |
}, | |
{ | |
"name": "docs_quickstart", | |
"url": "http://localhost:7860", | |
"description": "Documentation quick start guide", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Docs')"}, | |
{"type": "wait", "time": 1000}, | |
{"type": "click", "selector": "button:has-text('📖 Quick Start Guide')"} | |
], | |
"wait_time": 1000, | |
"selector": None, | |
"output": "img/docs_quickstart.png" | |
}, | |
{ | |
"name": "config_system_prompt", | |
"url": "http://localhost:7860", | |
"description": "System configuration section", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Configure Space')"}, | |
{"type": "wait", "time": 1000}, | |
{"type": "scroll", "y": 500} | |
], | |
"wait_time": 1000, | |
"selector": None, | |
"output": "img/config_system_prompt.png" | |
}, | |
{ | |
"name": "config_api_section", | |
"url": "http://localhost:7860", | |
"description": "API configuration section", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Configure Space')"}, | |
{"type": "wait", "time": 1000}, | |
{"type": "scroll", "y": 1200} | |
], | |
"wait_time": 1000, | |
"selector": None, | |
"output": "img/config_api_section.png" | |
}, | |
{ | |
"name": "generate_button", | |
"url": "http://localhost:7860", | |
"description": "Generate deployment package button", | |
"actions": [ | |
{"type": "click", "selector": "button:has-text('Configure Space')"}, | |
{"type": "wait", "time": 1000}, | |
{"type": "scroll", "y": 2000} | |
], | |
"wait_time": 1000, | |
"selector": "button:has-text('🗳️ Generate Deployment Package')", | |
"output": "img/generate_button.png" | |
} | |
] | |
async def capture_screenshot(page, config): | |
"""Capture a single screenshot based on configuration""" | |
logger.info(f"Capturing screenshot: {config['name']} - {config['description']}") | |
try: | |
# Navigate to URL | |
await page.goto(config['url']) | |
# Execute actions | |
for action in config.get('actions', []): | |
if action['type'] == 'click': | |
selector = action['selector'] | |
nth = action.get('nth', 0) | |
if nth > 0: | |
await page.locator(selector).nth(nth).click() | |
else: | |
await page.click(selector) | |
await page.wait_for_timeout(500) | |
elif action['type'] == 'type': | |
await page.fill(action['selector'], action['text']) | |
elif action['type'] == 'wait': | |
await page.wait_for_timeout(action['time']) | |
elif action['type'] == 'scroll': | |
await page.evaluate(f"window.scrollBy(0, {action['y']})") | |
await page.wait_for_timeout(500) | |
# Wait for any animations to complete | |
await page.wait_for_timeout(config.get('wait_time', 1000)) | |
# Take screenshot | |
output_path = Path(config['output']) | |
output_path.parent.mkdir(parents=True, exist_ok=True) | |
if config.get('selector'): | |
# Screenshot of specific element | |
element = page.locator(config['selector']) | |
await element.screenshot(path=str(output_path)) | |
else: | |
# Full page screenshot | |
await page.screenshot(path=str(output_path), full_page=False) | |
logger.info(f"✅ Saved screenshot to {output_path}") | |
return True | |
except Exception as e: | |
logger.error(f"❌ Failed to capture {config['name']}: {str(e)}") | |
return False | |
async def capture_all_screenshots(): | |
"""Capture all configured screenshots""" | |
logger.info("Starting screenshot capture process...") | |
# Ensure the app is running | |
logger.info("Make sure the Gradio app is running on http://localhost:7860") | |
async with async_playwright() as p: | |
# Launch browser | |
browser = await p.chromium.launch(headless=False) # Set to True for headless mode | |
context = await browser.new_context( | |
viewport={'width': 1280, 'height': 800}, | |
device_scale_factor=2 # Higher quality screenshots | |
) | |
page = await context.new_page() | |
# Capture each screenshot | |
success_count = 0 | |
for config in SCREENSHOT_CONFIGS: | |
if await capture_screenshot(page, config): | |
success_count += 1 | |
await page.wait_for_timeout(1000) # Brief pause between screenshots | |
# Clean up | |
await browser.close() | |
logger.info(f"\nCapture complete! {success_count}/{len(SCREENSHOT_CONFIGS)} screenshots captured successfully.") | |
# Create a summary report | |
report_path = Path("img/screenshot_report.txt") | |
with open(report_path, 'w') as f: | |
f.write(f"Screenshot Capture Report\n") | |
f.write(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") | |
f.write(f"Total Screenshots: {len(SCREENSHOT_CONFIGS)}\n") | |
f.write(f"Successful: {success_count}\n\n") | |
f.write("Screenshots Generated:\n") | |
for config in SCREENSHOT_CONFIGS: | |
f.write(f"- {config['output']}: {config['description']}\n") | |
logger.info(f"Report saved to {report_path}") | |
async def capture_single_screenshot(name): | |
"""Capture a single screenshot by name""" | |
config = next((c for c in SCREENSHOT_CONFIGS if c['name'] == name), None) | |
if not config: | |
logger.error(f"No configuration found for screenshot: {name}") | |
return | |
async with async_playwright() as p: | |
browser = await p.chromium.launch(headless=False) | |
context = await browser.new_context( | |
viewport={'width': 1280, 'height': 800}, | |
device_scale_factor=2 | |
) | |
page = await context.new_page() | |
await capture_screenshot(page, config) | |
await browser.close() | |
def main(): | |
"""Main entry point""" | |
import sys | |
if len(sys.argv) > 1: | |
# Capture specific screenshot | |
asyncio.run(capture_single_screenshot(sys.argv[1])) | |
else: | |
# Capture all screenshots | |
asyncio.run(capture_all_screenshots()) | |
if __name__ == "__main__": | |
main() |