Update playwright_model.py
Browse files- playwright_model.py +62 -69
playwright_model.py
CHANGED
|
@@ -45,97 +45,87 @@ def capture_workflows(public_url: str, pdf_filename: str = "workflow_screens.pdf
|
|
| 45 |
console.log('π§ Fixing layout...');
|
| 46 |
|
| 47 |
// Reset all layout elements
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
'main, .main-content, .app-body, .content, .page-content'
|
| 52 |
-
];
|
| 53 |
-
|
| 54 |
-
resetSelectors.forEach(selector => {
|
| 55 |
document.querySelectorAll(selector).forEach(el => {
|
| 56 |
if (el) {
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
el.style.height = '';
|
| 62 |
-
el.style.zIndex = '';
|
| 63 |
-
el.style.overflow = '';
|
| 64 |
-
el.style.transition = '';
|
| 65 |
-
el.style.marginLeft = '';
|
| 66 |
-
el.style.marginTop = '';
|
| 67 |
-
el.style.paddingTop = '';
|
| 68 |
}
|
| 69 |
});
|
| 70 |
});
|
| 71 |
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
const marginBottom = parseInt(style.marginBottom) || 0;
|
| 82 |
-
return Math.max(rect.height, element.offsetHeight) + marginTop + marginBottom;
|
| 83 |
};
|
| 84 |
|
| 85 |
-
// Fix topbar
|
| 86 |
-
const
|
| 87 |
-
const topbar = document.querySelector(topbarSelectors);
|
| 88 |
let topOffset = 60;
|
| 89 |
|
| 90 |
if (topbar) {
|
| 91 |
-
|
|
|
|
| 92 |
|
| 93 |
-
topbar.style
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
|
|
|
|
|
|
| 100 |
|
| 101 |
-
// Push page down to reveal content
|
| 102 |
document.body.style.marginTop = topOffset + 'px';
|
| 103 |
console.log('β
Topbar height:', topOffset, 'px');
|
| 104 |
}
|
| 105 |
|
| 106 |
-
// Fix sidebar
|
| 107 |
-
const
|
| 108 |
-
|
| 109 |
|
| 110 |
if (sidebar) {
|
| 111 |
-
const
|
|
|
|
| 112 |
|
| 113 |
-
sidebar.style
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
console.log('β
Sidebar top:', topOffset, 'px');
|
| 124 |
-
|
| 125 |
-
// Fix content spacing
|
| 126 |
-
const contentSelectors = 'main, .main-content, .app-body, .content, .page-content';
|
| 127 |
-
document.querySelectorAll(contentSelectors).forEach(el => {
|
| 128 |
-
if (el) {
|
| 129 |
-
el.style.marginLeft = sidebarWidth + 'px';
|
| 130 |
-
el.style.position = 'relative';
|
| 131 |
-
el.style.paddingTop = '20px'; // Add breathing room for titles
|
| 132 |
-
}
|
| 133 |
});
|
|
|
|
|
|
|
| 134 |
}
|
| 135 |
|
| 136 |
-
//
|
| 137 |
-
document.
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
el.style.display = 'none';
|
| 140 |
}
|
| 141 |
});
|
|
@@ -151,7 +141,10 @@ def capture_workflows(public_url: str, pdf_filename: str = "workflow_screens.pdf
|
|
| 151 |
page.wait_for_selector("aside, .sidebar, nav", timeout=5000)
|
| 152 |
wait_for_layout_stable()
|
| 153 |
fix_layout_dynamically()
|
| 154 |
-
page.wait_for_timeout(2000) #
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
# JS logic for capturing workflows
|
| 157 |
js_logic = """
|
|
|
|
| 45 |
console.log('π§ Fixing layout...');
|
| 46 |
|
| 47 |
// Reset all layout elements
|
| 48 |
+
['.top-bar, header, .app-header',
|
| 49 |
+
'aside, .sidebar, nav',
|
| 50 |
+
'main, .main-content, .content, .page-content'].forEach(selector => {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
document.querySelectorAll(selector).forEach(el => {
|
| 52 |
if (el) {
|
| 53 |
+
['position','top','left','width','height','zIndex','overflow',
|
| 54 |
+
'transition','margin','padding','boxSizing'].forEach(prop => {
|
| 55 |
+
el.style[prop] = '';
|
| 56 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
}
|
| 58 |
});
|
| 59 |
});
|
| 60 |
|
| 61 |
+
// Get accurate element dimensions
|
| 62 |
+
const getDims = (el) => {
|
| 63 |
+
if (!el || !el.isConnected) return {width: 240, height: 60};
|
| 64 |
+
const rect = el.getBoundingClientRect();
|
| 65 |
+
const style = window.getComputedStyle(el);
|
| 66 |
+
return {
|
| 67 |
+
width: rect.width + (parseFloat(style.marginLeft) || 0) + (parseFloat(style.marginRight) || 0),
|
| 68 |
+
height: rect.height + (parseFloat(style.marginTop) || 0) + (parseFloat(style.marginBottom) || 0)
|
| 69 |
+
};
|
|
|
|
|
|
|
| 70 |
};
|
| 71 |
|
| 72 |
+
// Fix topbar
|
| 73 |
+
const topbar = document.querySelector('.top-bar, header, .app-header, .navbar');
|
|
|
|
| 74 |
let topOffset = 60;
|
| 75 |
|
| 76 |
if (topbar) {
|
| 77 |
+
const dims = getDims(topbar);
|
| 78 |
+
topOffset = Math.round(dims.height);
|
| 79 |
|
| 80 |
+
Object.assign(topbar.style, {
|
| 81 |
+
position: 'fixed',
|
| 82 |
+
top: '0',
|
| 83 |
+
left: '0',
|
| 84 |
+
width: '100vw',
|
| 85 |
+
zIndex: '10000',
|
| 86 |
+
transition: 'none',
|
| 87 |
+
boxSizing: 'border-box'
|
| 88 |
+
});
|
| 89 |
|
|
|
|
| 90 |
document.body.style.marginTop = topOffset + 'px';
|
| 91 |
console.log('β
Topbar height:', topOffset, 'px');
|
| 92 |
}
|
| 93 |
|
| 94 |
+
// Fix sidebar
|
| 95 |
+
const sidebar = document.querySelector('aside, .sidebar, nav');
|
| 96 |
+
let sidebarWidth = 240;
|
| 97 |
|
| 98 |
if (sidebar) {
|
| 99 |
+
const dims = getDims(sidebar);
|
| 100 |
+
sidebarWidth = Math.round(dims.width);
|
| 101 |
|
| 102 |
+
Object.assign(sidebar.style, {
|
| 103 |
+
position: 'fixed',
|
| 104 |
+
top: topOffset + 'px',
|
| 105 |
+
left: '0',
|
| 106 |
+
height: `calc(100vh - ${topOffset}px)`,
|
| 107 |
+
width: sidebarWidth + 'px',
|
| 108 |
+
zIndex: '9999',
|
| 109 |
+
overflow: 'auto',
|
| 110 |
+
transition: 'none',
|
| 111 |
+
boxSizing: 'border-box'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
});
|
| 113 |
+
|
| 114 |
+
console.log('β
Sidebar width:', sidebarWidth, 'px');
|
| 115 |
}
|
| 116 |
|
| 117 |
+
// Fix main content using padding (more reliable than margin)
|
| 118 |
+
const content = document.querySelector('main, .main-content, .content, .page-content');
|
| 119 |
+
if (content) {
|
| 120 |
+
content.style.paddingLeft = (sidebarWidth + 20) + 'px'; // +20px for breathing room
|
| 121 |
+
content.style.position = 'relative';
|
| 122 |
+
content.style.boxSizing = 'border-box';
|
| 123 |
+
console.log('β
Content padding-left:', (sidebarWidth + 20), 'px');
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
// Hide any duplicate fixed elements that might overlap
|
| 127 |
+
document.querySelectorAll('.title-bar, .page-title, [class*="header"]').forEach(el => {
|
| 128 |
+
if (el && el !== topbar && window.getComputedStyle(el).position === 'fixed') {
|
| 129 |
el.style.display = 'none';
|
| 130 |
}
|
| 131 |
});
|
|
|
|
| 141 |
page.wait_for_selector("aside, .sidebar, nav", timeout=5000)
|
| 142 |
wait_for_layout_stable()
|
| 143 |
fix_layout_dynamically()
|
| 144 |
+
page.wait_for_timeout(2000) # Extra time for CSS transitions to complete
|
| 145 |
+
|
| 146 |
+
# [Rest of the code remains the same as previous version]
|
| 147 |
+
# ... (JS logic for capturing workflows, screenshot loop, PDF generation)
|
| 148 |
|
| 149 |
# JS logic for capturing workflows
|
| 150 |
js_logic = """
|