From fe1bd94050a09963396bc217ba95cc0d5c917d3d Mon Sep 17 00:00:00 2001 From: Damian Maslanka Date: Wed, 26 Nov 2025 22:35:27 +0100 Subject: [PATCH] Add downloads by package manager over time to the main page --- src/app/page.js | 9 ++++++--- src/components/Charts/MultiLine.jsx | 9 +++++++-- src/components/Summary.jsx | 19 ++++++++++++++++++- src/utils/clickhouse.js | 8 ++++++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/app/page.js b/src/app/page.js index c151f93..0733e48 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -10,7 +10,8 @@ import { getRecentReleases, getPopularEmergingRepos, getPopularReposNeedingRefresh, - hotPackages + hotPackages, + installationsPerInstaller, } from '@/utils/clickhouse'; import 'server-only'; @@ -24,12 +25,13 @@ export const revalidate = 3600 export default async function Home() { const total_downloads = await getTotalDownloads(); const projects = await getProjectCount(); - const [recent_releases, emerging_repos, needing_refresh, hot_packages] = + const [recent_releases, emerging_repos, needing_refresh, hot_packages, installations_per_installer] = await Promise.all([ getRecentReleases(projects[1].map((p) => p.project)), getPopularEmergingRepos(), getPopularReposNeedingRefresh(), - hotPackages() + hotPackages(), + installationsPerInstaller(), ]); @@ -67,6 +69,7 @@ export default async function Home() { emerging_repos={emerging_repos} needing_refresh={needing_refresh} hot_packages={hot_packages} + installations_per_installer={installations_per_installer} /> diff --git a/src/components/Charts/MultiLine.jsx b/src/components/Charts/MultiLine.jsx index 2f76078..308b2b3 100644 --- a/src/components/Charts/MultiLine.jsx +++ b/src/components/Charts/MultiLine.jsx @@ -9,7 +9,7 @@ import { } from '@heroicons/react/20/solid'; import CopyDropdown from '../CopyDropdown'; -export default function MultiLine({ data, stack, fill, onSelect, link, metabaseLink }) { +export default function MultiLine({ data, stack, fill, onSelect, link, metabaseLink, disableBrush = false, formatYAxis }) { const [loading, setLoading] = useState(true); const xAxis = Array.from(new Set(data.map((p) => p.x))); const values = data.reduce((accumulator, val) => { @@ -105,10 +105,15 @@ export default function MultiLine({ data, stack, fill, onSelect, link, metabaseL color: '#808691', opacity: 0.3 } + }, + axisLabel: { + formatter: (value, index) => { + return formatYAxis ? formatYAxis(value) : undefined; + } } }, series: series, - brush: { + brush: disableBrush ? null : { toolbox: ['lineX'], brushType: 'lineX', brushMode: 'single', diff --git a/src/components/Summary.jsx b/src/components/Summary.jsx index aa3b087..189e739 100644 --- a/src/components/Summary.jsx +++ b/src/components/Summary.jsx @@ -1,5 +1,6 @@ 'use client'; import HeatMap from './Charts/HeatMap'; +import MultiLine from './Charts/MultiLine'; import HorizontalBar from './Charts/HorizontalBar'; import SimpleList from './Charts/SimpleList'; import Image from 'next/image'; @@ -11,12 +12,17 @@ import { ArrowTopRightOnSquareIcon, } from '@heroicons/react/20/solid'; +function formatQuantityForInstallationsPerManager(value) { + return `${Math.round(value / 1000000)}M` +}; + export default function Summary({ packages, recent_releases, emerging_repos, needing_refresh, - hot_packages + hot_packages, + installations_per_installer }) { const router = useRouter(); @@ -151,6 +157,17 @@ export default function Summary({ link = {hot_packages[0]} /> +
+

+ Downloads by package manager over time +

+ +
); } diff --git a/src/utils/clickhouse.js b/src/utils/clickhouse.js index 7181734..a2a4968 100644 --- a/src/utils/clickhouse.js +++ b/src/utils/clickhouse.js @@ -756,6 +756,14 @@ export async function getPackageRanking(package_name, min_date, max_date, countr }) } +export async function installationsPerInstaller() { + return query('installationsPerInstaller', `SELECT toStartOfWeek(date) AS x, installer AS name, sum(count) AS y + FROM pypi.pypi_downloads_per_day_by_version_by_installer_by_type + WHERE date > toStartOfMonth(now() - toIntervalMonth(18)) and x != toStartOfWeek(now()) AND installer IN ('pip', 'uv', 'poetry') + GROUP BY x, name + ORDER BY x ASC`) +} + export const revalidate = 3600;