From ba53228f77e7b571962f5911bc6b2b2050e10a28 Mon Sep 17 00:00:00 2001 From: Jayden Pyles Date: Thu, 25 Jul 2024 13:56:59 -0500 Subject: [PATCH] wip: use ssr for more components --- api/backend/app.py | 19 +-- src/pages/logs.tsx | 9 +- src/pages/statistics.tsx | 348 +++++++++++++++++++++++---------------- 3 files changed, 223 insertions(+), 153 deletions(-) diff --git a/api/backend/app.py b/api/backend/app.py index 98da506..834e4cf 100644 --- a/api/backend/app.py +++ b/api/backend/app.py @@ -30,7 +30,6 @@ from api.backend.models import ( GetStatistics, SubmitScrapeJob, DeleteScrapeJobs, - RetrieveScrapeJobs, UpdateJobs, ) from api.backend.auth.auth_router import auth_router @@ -173,8 +172,6 @@ async def delete(delete_scrape_jobs: DeleteScrapeJobs): ) - - @app.get("/api/initial_logs") async def get_initial_logs(): container_id = "scraperr_api" @@ -182,11 +179,11 @@ async def get_initial_logs(): try: container = client.containers.get(container_id) log_stream = container.logs(stream=False).decode("utf-8") - logs = log_stream.split('\n') - return JSONResponse(content={"logs": logs}) + return JSONResponse(content={"logs": log_stream}) except Exception as e: raise HTTPException(status_code=500, detail=f"Unexpected error: {e}") + @app.get("/api/logs") async def get_own_logs(): container_id = "scraperr_api" @@ -207,12 +204,12 @@ async def get_own_logs(): raise HTTPException(status_code=500, detail=str(e)) -@app.post("/api/statistics/get-average-element-per-link") -async def get_average_element_per_link(get_statistics: GetStatistics): - return await average_elements_per_link(get_statistics.user) +@app.get("/api/statistics/get-average-element-per-link") +async def get_average_element_per_link(user: User = Depends(get_current_user)): + return await average_elements_per_link(user.email) -@app.post("/api/statistics/get-average-jobs-per-day") -async def average_jobs_per_day(get_statistics: GetStatistics): - data = await get_jobs_per_day(get_statistics.user) +@app.get("/api/statistics/get-average-jobs-per-day") +async def average_jobs_per_day(user: User = Depends(get_current_user)): + data = await get_jobs_per_day(user.email) return data diff --git a/src/pages/logs.tsx b/src/pages/logs.tsx index abdfaa4..22adbe5 100644 --- a/src/pages/logs.tsx +++ b/src/pages/logs.tsx @@ -3,10 +3,15 @@ import { ArrowUpward, ArrowDownward } from "@mui/icons-material"; import { useEffect, useRef, useState } from "react"; import { Constants } from "../lib"; +interface logs { + logs: string; +} + export async function getStaticProps() { try { const response = await fetch(`http://scraperr_api:8000/api/initial_logs`); - const initialLogs = await response.json(); + const logJson: logs = await response.json(); + const initialLogs = logJson.logs; return { props: { @@ -34,6 +39,8 @@ const Logs = ({ initialLogs }: LogProps) => { useEffect(() => { const eventSource = new EventSource(`${Constants.DOMAIN}/api/logs`); + setLogs(""); + eventSource.onmessage = (event) => { setLogs((prevLogs) => prevLogs + event.data + "\n"); if (logsContainerRef.current) { diff --git a/src/pages/statistics.tsx b/src/pages/statistics.tsx index 1b83b8f..ba4ab92 100644 --- a/src/pages/statistics.tsx +++ b/src/pages/statistics.tsx @@ -3,164 +3,230 @@ import { Chart, registerables } from "chart.js"; import { Box, Typography, useTheme } from "@mui/material"; import { useAuth } from "../contexts/AuthContext"; import { Constants } from "../lib"; +import { parseCookies } from "nookies"; +import { GetServerSideProps } from "next/types"; +import Cookies from "js-cookie"; Chart.register(...registerables); -const Statistics: React.FC = () => { +type averageElement = { + date: string; + average_elements: number; + count: number; +}; + +type averageJob = { + date: string; + job_count: number; +}; + +export const getServerSideProps: GetServerSideProps = async (context) => { + const { req } = context; + const cookies = parseCookies({ req }); + const token = cookies.token; + let averageElement: averageElement[] = []; + let averageJob: averageJob[] = []; + + if (token) { + try { + const averageElementResponse = await fetch( + `http://scraperr_api:8000/api/statistics/get-average-element-per-link`, + { + headers: { Authorization: `Bearer ${token}` }, + } + ); + + averageElement = await averageElementResponse.json(); + + const averageJobResponse = await fetch( + `http://scraperr_api:8000/api/statistics/get-average-jobs-per-day`, + { + headers: { Authorization: `Bearer ${token}` }, + } + ); + + averageJob = await averageJobResponse.json(); + } catch (error) { + console.error("Error fetching statistics:", error); + } + } + + return { + props: { averageElement, averageJob }, + }; +}; + +interface StatProps { + averageElement: averageElement[]; + averageJob: averageJob[]; +} + +const Statistics: React.FC = ({ averageElement, averageJob }) => { const theme = useTheme(); const elementsChartRef = useRef(null); const jobsChartRef = useRef(null); const [elementsChart, setElementsChart] = useState(null); const [jobsChart, setJobsChart] = useState(null); + const [elementsData, setElementsData] = + useState(averageElement); + const [jobsData, setJobsData] = useState(averageJob); const { user } = useAuth(); + const token = Cookies.get("token"); + + const fetchElementsData = async () => { + try { + const response = await fetch( + `${Constants.DOMAIN}/api/statistics/get-average-element-per-link`, + { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + } + ); + const data = await response.json(); + setElementsData(data); + } catch (error) { + console.error("Error fetching elements data:", error); + } + }; + + const fetchJobsData = async () => { + try { + const response = await fetch( + `${Constants.DOMAIN}/api/statistics/get-average-jobs-per-day`, + { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + } + ); + const data = await response.json(); + setJobsData(data); + } catch (error) { + console.error("Error fetching jobs data:", error); + } + }; useEffect(() => { - const fetchElementsData = async () => { - try { - const response = await fetch( - `${Constants.DOMAIN}/api/statistics/get-average-element-per-link`, - { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ user: user.email }), - } - ); - const data = await response.json(); - - const dates = data.map((item: any) => item.date); - const averages = data.map((item: any) => item.average_elements); - - if (elementsChartRef.current) { - const ctx = elementsChartRef.current.getContext("2d"); - - if (ctx) { - if (elementsChart) { - elementsChart.destroy(); - } - - const newChart = new Chart(ctx, { - type: "line", - data: { - labels: dates, - datasets: [ - { - label: "Average Elements per Link", - data: averages, - backgroundColor: - theme.palette.mode === "light" - ? "rgba(75, 192, 192, 0.2)" - : "rgba(255, 99, 132, 0.2)", - borderColor: - theme.palette.mode === "light" - ? "rgba(75, 192, 192, 1)" - : "rgba(255, 99, 132, 1)", - borderWidth: 1, - }, - ], - }, - options: { - scales: { - y: { - beginAtZero: true, - ticks: { - color: theme.palette.text.primary, - }, - }, - x: { - ticks: { - color: theme.palette.text.primary, - }, - }, - }, - responsive: true, - maintainAspectRatio: false, - }, - }); - - setElementsChart(newChart); - } - } - } catch (error) { - console.error("Error fetching elements data:", error); - } - }; - - fetchElementsData(); - }, [elementsChartRef, theme.palette.mode]); + if (user) { + fetchElementsData(); + fetchJobsData(); + } + }, [theme.palette.mode, user]); useEffect(() => { - const fetchJobsData = async () => { - try { - const response = await fetch( - `${Constants.DOMAIN}/api/statistics/get-average-jobs-per-day`, - { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ user: user.email }), - } - ); - const data = await response.json(); + const dates = elementsData.map((item) => item.date); + const averages = elementsData.map((item) => item.average_elements); - const dates = data.map((item: any) => item.date); - const jobCounts = data.map((item: any) => item.job_count); + if (elementsChartRef.current) { + const ctx = elementsChartRef.current.getContext("2d"); - if (jobsChartRef.current) { - const ctx = jobsChartRef.current.getContext("2d"); - - if (ctx) { - if (jobsChart) { - jobsChart.destroy(); - } - - const newChart = new Chart(ctx, { - type: "line", - data: { - labels: dates, - datasets: [ - { - label: "Average Jobs per Day", - data: jobCounts, - backgroundColor: - theme.palette.mode === "light" - ? "rgba(153, 102, 255, 0.2)" - : "rgba(54, 162, 235, 0.2)", - borderColor: - theme.palette.mode === "light" - ? "rgba(153, 102, 255, 1)" - : "rgba(54, 162, 235, 1)", - borderWidth: 1, - }, - ], - }, - options: { - scales: { - y: { - beginAtZero: true, - ticks: { - color: theme.palette.text.primary, - }, - }, - x: { - ticks: { - color: theme.palette.text.primary, - }, - }, - }, - responsive: true, - maintainAspectRatio: false, - }, - }); - - setJobsChart(newChart); - } + if (ctx) { + if (elementsChart) { + elementsChart.destroy(); } - } catch (error) { - console.error("Error fetching jobs data:", error); - } - }; - fetchJobsData(); - }, [jobsChartRef, theme.palette.mode]); + const newChart = new Chart(ctx, { + type: "line", + data: { + labels: dates, + datasets: [ + { + label: "Average Elements per Link", + data: averages, + backgroundColor: + theme.palette.mode === "light" + ? "rgba(75, 192, 192, 0.2)" + : "rgba(255, 99, 132, 0.2)", + borderColor: + theme.palette.mode === "light" + ? "rgba(75, 192, 192, 1)" + : "rgba(255, 99, 132, 1)", + borderWidth: 1, + }, + ], + }, + options: { + scales: { + y: { + beginAtZero: true, + ticks: { + color: theme.palette.text.primary, + }, + }, + x: { + ticks: { + color: theme.palette.text.primary, + }, + }, + }, + responsive: true, + maintainAspectRatio: false, + }, + }); + + setElementsChart(newChart); + } + } + }, [elementsData, theme.palette.mode]); + + useEffect(() => { + const dates = jobsData.map((item) => item.date); + const jobCounts = jobsData.map((item) => item.job_count); + + if (jobsChartRef.current) { + const ctx = jobsChartRef.current.getContext("2d"); + + if (ctx) { + if (jobsChart) { + jobsChart.destroy(); + } + + const newChart = new Chart(ctx, { + type: "line", + data: { + labels: dates, + datasets: [ + { + label: "Average Jobs per Day", + data: jobCounts, + backgroundColor: + theme.palette.mode === "light" + ? "rgba(153, 102, 255, 0.2)" + : "rgba(54, 162, 235, 0.2)", + borderColor: + theme.palette.mode === "light" + ? "rgba(153, 102, 255, 1)" + : "rgba(54, 162, 235, 1)", + borderWidth: 1, + }, + ], + }, + options: { + scales: { + y: { + beginAtZero: true, + ticks: { + color: theme.palette.text.primary, + }, + }, + x: { + ticks: { + color: theme.palette.text.primary, + }, + }, + }, + responsive: true, + maintainAspectRatio: false, + }, + }); + + setJobsChart(newChart); + } + } + }, [jobsData, theme.palette.mode]); return ( <>