From 784a07dd1b041f38c44990ba859a92e30271f5fc Mon Sep 17 00:00:00 2001 From: "stone-24tch3r (aider)" <100294019+stone-w4tch3r@users.noreply.github.com> Date: Fri, 27 Sep 2024 02:05:40 +0500 Subject: [PATCH] feat: Create FastAPI web service and bootstrap it with Jinja2 templates --- front/Dockerfile | 12 ++++++ front/main.py | 34 +++++++++++++++ front/requirements.txt | 3 ++ front/static/styles.css | 91 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 front/Dockerfile create mode 100644 front/main.py create mode 100644 front/requirements.txt create mode 100644 front/static/styles.css diff --git a/front/Dockerfile b/front/Dockerfile new file mode 100644 index 0000000..01ae668 --- /dev/null +++ b/front/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY main.py . +COPY templates templates/ +COPY static static/ + +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/front/main.py b/front/main.py new file mode 100644 index 0000000..a2a85ae --- /dev/null +++ b/front/main.py @@ -0,0 +1,34 @@ +from fastapi import FastAPI, Request +from fastapi.templating import Jinja2Templates +from fastapi.staticfiles import StaticFiles +from fastapi.responses import HTMLResponse + +app = FastAPI() + +# Mount static files +app.mount("/static", StaticFiles(directory="front/static"), name="static") + +# Set up Jinja2 templates +templates = Jinja2Templates(directory="front/templates") + +@app.get("/", response_class=HTMLResponse) +async def read_dashboard(request: Request): + # Dummy data for certificates + certificates = [ + {"id": "1", "name": "Cert 1", "status": "Active", "actions": ["Renew", "Revoke"]}, + {"id": "2", "name": "Cert 2", "status": "Expired", "actions": ["Renew"]}, + ] + return templates.TemplateResponse("dashboard.html.j2", {"request": request, "certificates": certificates}) + +@app.get("/logs", response_class=HTMLResponse) +async def read_logs(request: Request): + # Dummy data for logs + logs = [ + {"entry_id": "1", "timestamp": "2023-07-01 10:00:00", "severity": "INFO", "trace_id": "abc123", "message": "Certificate generated"}, + {"entry_id": "2", "timestamp": "2023-07-01 11:00:00", "severity": "WARN", "trace_id": "def456", "message": "Certificate expiring soon"}, + ] + return templates.TemplateResponse("logs.html.j2", {"request": request, "logs": logs}) + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/front/requirements.txt b/front/requirements.txt new file mode 100644 index 0000000..c6dcdc7 --- /dev/null +++ b/front/requirements.txt @@ -0,0 +1,3 @@ +fastapi==0.68.0 +uvicorn==0.15.0 +jinja2==3.0.1 diff --git a/front/static/styles.css b/front/static/styles.css new file mode 100644 index 0000000..d7974e3 --- /dev/null +++ b/front/static/styles.css @@ -0,0 +1,91 @@ +body { + font-family: Arial, sans-serif; + line-height: 1.6; + margin: 0; + padding: 0; +} + +header { + background-color: #333; + color: #fff; + text-align: center; + padding: 1rem; +} + +main { + padding: 2rem; +} + +table { + width: 100%; + border-collapse: collapse; + margin-bottom: 1rem; +} + +th, td { + border: 1px solid #ddd; + padding: 0.5rem; + text-align: left; +} + +th { + background-color: #f2f2f2; +} + +.certs-table { + margin-bottom: 2rem; +} + +.certs-table-header { + background-color: #f2f2f2; +} + +.certs-actions-td { + display: flex; + gap: 0.5rem; +} + +.small-button, .main-bottom-button { + padding: 0.5rem 1rem; + background-color: #007bff; + color: #fff; + border: none; + cursor: pointer; + transition: background-color 0.3s; +} + +.small-button:hover, .main-bottom-button:hover { + background-color: #0056b3; +} + +.main-bottom-button { + display: block; + margin: 2rem auto; + font-size: 1.1rem; +} + +.logs-filters-container { + display: flex; + flex-wrap: wrap; + gap: 1rem; + margin-bottom: 2rem; +} + +.logs-filters-item { + display: flex; + flex-direction: column; +} + +.logs-filters-datepicker { + display: flex; + gap: 0.5rem; +} + +.logs-filters-fieldset { + border: 1px solid #ddd; + padding: 1rem; +} + +.logs-filters-legend { + font-weight: bold; +}