From fc9d6c2f00817731e625bed4cd489899d0448114 Mon Sep 17 00:00:00 2001 From: Tyler <26290074+tylersayshi@users.noreply.github.com> Date: Tue, 6 May 2025 22:45:34 -0700 Subject: [PATCH 1/7] fix(frontend): unstack download charts --- frontend/routes/package/(_islands)/DownloadChart.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/routes/package/(_islands)/DownloadChart.tsx b/frontend/routes/package/(_islands)/DownloadChart.tsx index 1881d3f3..76cbb2f1 100644 --- a/frontend/routes/package/(_islands)/DownloadChart.tsx +++ b/frontend/routes/package/(_islands)/DownloadChart.tsx @@ -24,7 +24,6 @@ export function DownloadChart(props: Props) { ) => ({ chart: { type: "area", - stacked: true, animations: { enabled: false, }, From 226e7ce358639898b4472acc848a79a9c1ae2fd7 Mon Sep 17 00:00:00 2001 From: Tyler <26290074+tylersayshi@users.noreply.github.com> Date: Thu, 8 May 2025 22:55:59 -0700 Subject: [PATCH 2/7] feat(frontend): add option to unstack downloads per version --- .../package/(_islands)/DownloadChart.tsx | 112 ++++++++++-------- 1 file changed, 63 insertions(+), 49 deletions(-) diff --git a/frontend/routes/package/(_islands)/DownloadChart.tsx b/frontend/routes/package/(_islands)/DownloadChart.tsx index 76cbb2f1..acce013f 100644 --- a/frontend/routes/package/(_islands)/DownloadChart.tsx +++ b/frontend/routes/package/(_islands)/DownloadChart.tsx @@ -20,10 +20,10 @@ export function DownloadChart(props: Props) { const getChartOptions = ( isDarkMode: boolean, - aggregationPeriod: AggregationPeriod = "weekly", ) => ({ chart: { type: "area", + stacked: true, animations: { enabled: false, }, @@ -56,7 +56,7 @@ export function DownloadChart(props: Props) { curve: "straight", width: 1.7, }, - series: getSeries(props.downloads, aggregationPeriod), + series: getSeries(props.downloads, "weekly"), xaxis: { type: "datetime", tooltip: { @@ -136,37 +136,52 @@ export function DownloadChart(props: Props) { return (
{graphRendered && ( -
- - { + chartRef.current?.updateSeries( + getSeries( + props.downloads, + e.currentTarget.value as AggregationPeriod, + ), + ); + }} + className="input-container input select w-20" + > + + + + +
+
+ + + // Update chart with new options including the new stacked display + chartRef.current?.updateOptions( + { chart: { stacked: newDisplay } }, + ); + }} + className="input-container input select w-24" + > + + + +
)}
@@ -196,19 +211,17 @@ function adjustTimePeriod( switch (aggregation) { case "weekly": // start of week (Sunday) in UTC - out = new Date(Date.UTC( - date.getUTCFullYear(), - date.getUTCMonth(), - date.getUTCDate() - date.getUTCDay(), - )); + out = new Date( + Date.UTC( + date.getUTCFullYear(), + date.getUTCMonth(), + date.getUTCDate() - date.getUTCDay(), + ), + ); break; case "monthly": // first day of month in UTC - out = new Date(Date.UTC( - date.getUTCFullYear(), - date.getUTCMonth(), - 1, - )); + out = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1)); break; default: // daily out = date; @@ -226,8 +239,8 @@ export function collectX( xValues.add(adjustTimePeriod(point.timeBucket, aggregationPeriod)); }); - return Array.from(xValues).sort((a, b) => - new Date(a).getTime() - new Date(b).getTime() + return Array.from(xValues).sort( + (a, b) => new Date(a).getTime() - new Date(b).getTime(), ); } @@ -251,17 +264,18 @@ export function normalize( } }); - return Object.entries(normalized).map(( - [key, value], - ) => [new Date(key).getTime(), value]); + return Object.entries(normalized).map(([key, value]) => [ + new Date(key).getTime(), + value, + ]); } function getSeries( recentVersions: PackageDownloadsRecentVersion[], aggregationPeriod: AggregationPeriod, ) { - const dataPointsWithDownloads = recentVersions.filter((dataPoints) => - dataPoints.downloads.length > 0 + const dataPointsWithDownloads = recentVersions.filter( + (dataPoints) => dataPoints.downloads.length > 0, ); const dataPointsToDisplay = dataPointsWithDownloads.slice(0, 5); From 246ae13bbdcbcf38e4eec8e4aa0af2928e46ad9d Mon Sep 17 00:00:00 2001 From: Tyler <26290074+tylersayshi@users.noreply.github.com> Date: Tue, 20 May 2025 22:41:49 -0700 Subject: [PATCH 3/7] fix change theme with series --- .../package/(_islands)/DownloadChart.tsx | 142 +++++++++--------- 1 file changed, 70 insertions(+), 72 deletions(-) diff --git a/frontend/routes/package/(_islands)/DownloadChart.tsx b/frontend/routes/package/(_islands)/DownloadChart.tsx index acce013f..a723dd27 100644 --- a/frontend/routes/package/(_islands)/DownloadChart.tsx +++ b/frontend/routes/package/(_islands)/DownloadChart.tsx @@ -13,98 +13,96 @@ interface Props { export type AggregationPeriod = "daily" | "weekly" | "monthly"; -export function DownloadChart(props: Props) { - const chartDivRef = useRef(null); - const chartRef = useRef(null); - const [graphRendered, setGraphRendered] = useState(false); - - const getChartOptions = ( - isDarkMode: boolean, - ) => ({ - chart: { - type: "area", - stacked: true, - animations: { - enabled: false, - }, - height: "100%", - width: "100%", - zoom: { - allowMouseWheelZoom: false, - }, - background: "transparent", - foreColor: isDarkMode ? "#a8b2bd" : "#515d6c", // jsr-gray-300 for dark mode, jsr-gray-600 for light +const getChartOptions = ( + isDarkMode: boolean, +): ApexCharts.ApexOptions => ({ + chart: { + type: "area", + stacked: true, + animations: { + enabled: false, }, - legend: { - horizontalAlign: "center", - position: "top", - showForSingleSeries: true, - labels: { - colors: isDarkMode ? "#a8b2bd" : "#515d6c", // jsr-gray-300 for dark mode, jsr-gray-600 for light - }, + height: "100%", + width: "100%", + zoom: { + allowMouseWheelZoom: false, + }, + background: "transparent", + foreColor: isDarkMode ? "#a8b2bd" : "#515d6c", // jsr-gray-300 for dark mode, jsr-gray-600 for light + }, + legend: { + horizontalAlign: "center", + position: "top", + showForSingleSeries: true, + labels: { + colors: isDarkMode ? "#a8b2bd" : "#515d6c", // jsr-gray-300 for dark mode, jsr-gray-600 for light }, + }, + tooltip: { + theme: isDarkMode ? "dark" : "light", + }, + dataLabels: { + enabled: false, + }, + stroke: { + curve: "straight", + width: 1.7, + }, + xaxis: { + type: "datetime", tooltip: { - items: { - padding: 0, + enabled: false, + }, + labels: { + style: { + colors: isDarkMode ? "#ced3da" : "#515d6c", // jsr-gray-200 for dark mode, jsr-gray-600 for light }, - theme: isDarkMode ? "dark" : "light", }, - dataLabels: { - enabled: false, + axisBorder: { + color: isDarkMode ? "#47515c" : "#ced3da", // jsr-gray-700 for dark mode, jsr-gray-200 for light }, - stroke: { - curve: "straight", - width: 1.7, + axisTicks: { + color: isDarkMode ? "#47515c" : "#ced3da", // jsr-gray-700 for dark mode, jsr-gray-200 for light }, - series: getSeries(props.downloads, "weekly"), - xaxis: { - type: "datetime", - tooltip: { - enabled: false, - }, - labels: { - style: { - colors: isDarkMode ? "#ced3da" : "#515d6c", // jsr-gray-200 for dark mode, jsr-gray-600 for light - }, - }, - axisBorder: { - color: isDarkMode ? "#47515c" : "#ced3da", // jsr-gray-700 for dark mode, jsr-gray-200 for light - }, - axisTicks: { - color: isDarkMode ? "#47515c" : "#ced3da", // jsr-gray-700 for dark mode, jsr-gray-200 for light + }, + yaxis: { + labels: { + style: { + colors: isDarkMode ? "#a8b2bd" : "#515d6c", // jsr-gray-300 for dark mode, jsr-gray-600 for light }, }, - yaxis: { - labels: { - style: { - colors: isDarkMode ? "#a8b2bd" : "#515d6c", // jsr-gray-300 for dark mode, jsr-gray-600 for light + }, + grid: { + borderColor: isDarkMode ? "#47515c" : "#e5e8eb", // jsr-gray-700 for dark mode, jsr-gray-100 for light + strokeDashArray: 3, + }, + responsive: [ + { + breakpoint: 768, + options: { + legend: { + horizontalAlign: "left", }, }, }, - grid: { - borderColor: isDarkMode ? "#47515c" : "#e5e8eb", // jsr-gray-700 for dark mode, jsr-gray-100 for light - strokeDashArray: 3, - }, - responsive: [ - { - breakpoint: 768, - options: { - legend: { - horizontalAlign: "left", - }, - }, - }, - ], - }); + ], +}); + +export function DownloadChart(props: Props) { + const chartDivRef = useRef(null); + const chartRef = useRef(null); + const [graphRendered, setGraphRendered] = useState(false); useEffect(() => { (async () => { const { default: ApexCharts } = await import("apexcharts"); const isDarkMode = document.documentElement.classList.contains("dark"); + const initialOptions = getChartOptions(isDarkMode); + initialOptions.series = getSeries(props.downloads, "weekly"); chartRef.current = new ApexCharts( chartDivRef.current!, - getChartOptions(isDarkMode), + initialOptions, ); chartRef.current.render(); From 9a60e213de64c274701c02d9666489c4f27bfa14 Mon Sep 17 00:00:00 2001 From: Tyler <26290074+tylersayshi@users.noreply.github.com> Date: Tue, 20 May 2025 23:18:41 -0700 Subject: [PATCH 4/7] fix styles for legend --- .../package/(_islands)/DownloadChart.tsx | 19 +++++++++++++++---- frontend/routes/package/versions.tsx | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/frontend/routes/package/(_islands)/DownloadChart.tsx b/frontend/routes/package/(_islands)/DownloadChart.tsx index a723dd27..2a59dd9f 100644 --- a/frontend/routes/package/(_islands)/DownloadChart.tsx +++ b/frontend/routes/package/(_islands)/DownloadChart.tsx @@ -6,6 +6,7 @@ import type { PackageDownloadsRecentVersion, } from "../../../utils/api_types.ts"; import type ApexCharts from "apexcharts"; +import { off } from "node:process"; interface Props { downloads: PackageDownloadsRecentVersion[]; @@ -31,7 +32,8 @@ const getChartOptions = ( foreColor: isDarkMode ? "#a8b2bd" : "#515d6c", // jsr-gray-300 for dark mode, jsr-gray-600 for light }, legend: { - horizontalAlign: "center", + horizontalAlign: "right", + offsetY: -1, position: "top", showForSingleSeries: true, labels: { @@ -81,7 +83,7 @@ const getChartOptions = ( breakpoint: 768, options: { legend: { - horizontalAlign: "left", + offsetY: -30, }, }, }, @@ -134,7 +136,7 @@ export function DownloadChart(props: Props) { return (
{graphRendered && ( -
+
)} -
+ +
diff --git a/frontend/routes/package/versions.tsx b/frontend/routes/package/versions.tsx index 6dc28743..578b2921 100644 --- a/frontend/routes/package/versions.tsx +++ b/frontend/routes/package/versions.tsx @@ -101,7 +101,7 @@ export default define.page(function Versions({ latestVersion={data.package.latestVersion} /> -
+
From dd8983c80ae626b25f0167301feaa06675deb971 Mon Sep 17 00:00:00 2001 From: Tyler <26290074+tylersayshi@users.noreply.github.com> Date: Tue, 20 May 2025 23:30:53 -0700 Subject: [PATCH 5/7] change to what's on main --- frontend/routes/package/(_islands)/DownloadChart.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/routes/package/(_islands)/DownloadChart.tsx b/frontend/routes/package/(_islands)/DownloadChart.tsx index 2a59dd9f..4d72de97 100644 --- a/frontend/routes/package/(_islands)/DownloadChart.tsx +++ b/frontend/routes/package/(_islands)/DownloadChart.tsx @@ -1,12 +1,12 @@ // Copyright 2024 the JSR authors. All rights reserved. MIT license. -import { useEffect, useRef, useState } from "preact/hooks"; +import { useEffect, useRef } from "preact/hooks"; import type { DownloadDataPoint, PackageDownloadsRecentVersion, } from "../../../utils/api_types.ts"; import type ApexCharts from "apexcharts"; -import { off } from "node:process"; +import { useSignal } from "@preact/signals"; interface Props { downloads: PackageDownloadsRecentVersion[]; @@ -93,7 +93,7 @@ const getChartOptions = ( export function DownloadChart(props: Props) { const chartDivRef = useRef(null); const chartRef = useRef(null); - const [graphRendered, setGraphRendered] = useState(false); + const graphRendered = useSignal(false); useEffect(() => { (async () => { @@ -108,7 +108,7 @@ export function DownloadChart(props: Props) { ); chartRef.current.render(); - setGraphRendered(true); + graphRendered.value = true; // Listen for theme changes const observer = new MutationObserver(() => { @@ -135,7 +135,7 @@ export function DownloadChart(props: Props) { return (
- {graphRendered && ( + {graphRendered.value && (