Skip to content

Commit

Permalink
pdf generation
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorwalton committed Mar 11, 2024
1 parent 0149da0 commit 5c1c8fd
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 2 deletions.
3 changes: 3 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ RUN /opt/venv/bin/pip install --no-cache-dir -r requirements.txt
# Install required browsers for playwright
RUN playwright install

# Install wkhtmltopdf
RUN apt-get install -y wkhtmltopdf

# Copy your application into the Docker image
WORKDIR /opt/copilot/backend
COPY . .
Expand Down
59 changes: 59 additions & 0 deletions backend/app/connectors/grafana/reporting/report-template-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Grafana Dashboard Report</title>
<style>
html, body {
padding: 0;
margin: 0;
}
* {
box-sizing: border-box;
}
:root {
--border-radius: 6px;
--bg-secondary-color: #f0f0f0;
--border-small-050: 1px solid #ccc;
}
.dashboard-container, .screenshots-container {
background-color: var(--bg-secondary-color);
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
padding: 10px;
margin-bottom: 20px;
}
.dashboard-panel, .screenshot {
background-color: white;
overflow: hidden;
flex-grow: 1;
min-width: 300px; /* Adjust based on your content */
box-sizing: border-box;
padding: 10px;
margin: 10px;
border: 1px solid #ddd;
border-radius: var(--border-radius);
}
.screenshot img {
border-radius: var(--border-radius);
}
.caption {
text-align: center;
font-size: 0.8em;
color: #666;
}
</style>
</head>
<body>
<div class="screenshots-container">
<h2>Screenshots</h2>
{% for panel in panels %}
<div class="screenshot">
<img src="data:image/png;base64,{{ panel.base64_image }}" alt="Screenshot" style="width: {{ panel.width }}px; height: {{ panel.height }}px;">
<div class="caption">Page {{ loop.index }}</div>
</div>
{% endfor %}
</div>
</body>
</html>
64 changes: 62 additions & 2 deletions backend/app/connectors/grafana/services/reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
from playwright.async_api import async_playwright
from loguru import logger
import base64
import os
import sys
import subprocess
import pdfkit
from jinja2 import Environment, FileSystemLoader
from sqlalchemy.ext.asyncio import AsyncSession
from app.connectors.grafana.schema.reporting import GenerateReportRequest, GenerateReportResponse, Base64Image
from app.utils import get_connector_attribute
Expand All @@ -13,6 +18,11 @@
from app.connectors.grafana.schema.reporting import GrafanaOrganizationDashboards
from app.connectors.grafana.schema.reporting import GrafanaOrganizations
from app.connectors.grafana.utils.universal import create_grafana_client
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.platypus import SimpleDocTemplate, Image
from reportlab.lib.units import inch
from pathlib import Path


async def get_orgs() -> List[GrafanaOrganizations]:
Expand Down Expand Up @@ -101,14 +111,62 @@ async def check_login_success(page):

async def capture_screenshots(page, urls):
base64_images = []
for url in urls:
for i, url in enumerate(urls):
await page.goto(url)
await page.wait_for_load_state(state='networkidle')
screenshot = await page.screenshot(type='png')
base64_image = base64.b64encode(screenshot).decode('utf-8')
base64_images.append({"url": url, "base64_image": base64_image})
width = await page.evaluate('window.innerWidth')
height = await page.evaluate('window.innerHeight')
base64_images.append({
'url': url,
'base64_image': base64_image,
'width': width,
'height': height,
'page_number': i + 1
})
return base64_images

def get_wkhtmltopdf_path():
if sys.platform == 'win32':
return 'C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe'
elif sys.platform == 'darwin':
return '/usr/local/bin/wkhtmltopdf'
else:
try:
# Try to find the path using 'which' command in Linux
path = subprocess.check_output(['which', 'wkhtmltopdf'])
return path.strip()
except Exception as e:
logger.error(f"Could not find wkhtmltopdf: {e}")
return None

def create_pdf(html_string):
logger.info(f"Creating PDF from HTML: {html_string}")
wkhtmltopdf_path = get_wkhtmltopdf_path()
if wkhtmltopdf_path is None:
logger.error("Cannot create PDF without wkhtmltopdf")
return
config = pdfkit.configuration(wkhtmltopdf=wkhtmltopdf_path)
pdfkit.from_string(html_string, 'report.pdf', configuration=config)


def generate_html(base64_images):
# Load the template
templates_dir = Path(__file__).parent / '../reporting'
env = Environment(loader=FileSystemLoader(templates_dir))
template = env.get_template('report-template-test.html')

# Define the context
context = {
'panels': base64_images, # Assuming this is adjusted to contain base64 encoded images
}

# Render the template with the context
html_string = template.render(context)

return html_string

async def generate_report(
request: GenerateReportRequest,
session: AsyncSession
Expand All @@ -124,6 +182,8 @@ async def generate_report(
return
base64_images = await capture_screenshots(page, request.urls)
await browser.close()
html_string = generate_html(base64_images)
create_pdf(html_string)
return GenerateReportResponse(
base64_images=[Base64Image(url=img['url'], base64_image=img['base64_image']) for img in base64_images],
message="Report generated successfully",
Expand Down
Binary file added backend/report.pdf
Binary file not shown.
2 changes: 2 additions & 0 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ pytest-playwright==0.4.4
python-dateutil==2.8.2
python-dotenv==1.0.0
python-jose==3.3.0
pdfkit==1.0.0
python-magic==0.4.27
python-multipart==0.0.6
pytz==2023.3.post1
Expand All @@ -128,6 +129,7 @@ regex==2023.10.3
reportlab==4.0.5
requests==2.31.0
requests-cache==1.1.0
Jinja2=3.1.2
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rich==13.6.0
Expand Down

0 comments on commit 5c1c8fd

Please sign in to comment.