cfahlgren1 HF staff commited on
Commit
c798beb
1 Parent(s): 17388ad

add path param for user page

Browse files
next.config.mjs CHANGED
@@ -1,6 +1,6 @@
1
  /** @type {import('next').NextConfig} */
2
  const nextConfig = {
3
- output: 'standalone',
4
  reactStrictMode: true,
5
  };
6
 
 
1
  /** @type {import('next').NextConfig} */
2
  const nextConfig = {
3
+ output: "standalone",
4
  reactStrictMode: true,
5
  };
6
 
src/pages/[author]/index.tsx ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from "react";
2
+ import ActivityCalendar from "react-activity-calendar";
3
+ import { Tooltip } from "@mui/material";
4
+ import { GetServerSidePropsContext } from "next";
5
+ import { OpenSourceHeatmapProps } from "../../types/heatmap";
6
+ import { generateCalendarData } from "../../utils/calendar";
7
+
8
+ const DEFAULT_COLOR = "#DB4437";
9
+
10
+ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({
11
+ calendarData,
12
+ providers,
13
+ }) => {
14
+ const [isLoading, setIsLoading] = useState(true);
15
+
16
+ useEffect(() => {
17
+ if (calendarData && Object.keys(calendarData).length > 0) {
18
+ setIsLoading(false);
19
+ }
20
+ }, [calendarData]);
21
+
22
+ return (
23
+ <div className="w-full max-w-screen-lg mx-auto p-4">
24
+
25
+ {isLoading ? (
26
+ <p className="text-center">Loading...</p>
27
+ ) : (
28
+ <div className="space-y-8">
29
+ {Object.entries(providers)
30
+ .sort(
31
+ ([keyA], [keyB]) =>
32
+ calendarData[keyB].reduce((sum, day) => sum + day.count, 0) -
33
+ calendarData[keyA].reduce((sum, day) => sum + day.count, 0),
34
+ )
35
+ .map(([providerName, { color }]) => (
36
+ <div key={providerName} className="flex flex-col items-center">
37
+ <h2 className="text-xl font-bold mb-4">{providerName}</h2>
38
+ <div className="w-full overflow-x-auto flex justify-center">
39
+ <ActivityCalendar
40
+ data={calendarData[providerName]}
41
+ theme={{
42
+ dark: ["#161b22", color],
43
+ light: ["#e0e0e0", color],
44
+ }}
45
+ hideTotalCount
46
+ renderBlock={(block, activity) => (
47
+ <Tooltip
48
+ title={`${activity.count} models created on ${activity.date}`}
49
+ arrow
50
+ >
51
+ {block}
52
+ </Tooltip>
53
+ )}
54
+ />
55
+ </div>
56
+ </div>
57
+ ))}
58
+ </div>
59
+ )}
60
+ </div>
61
+ );
62
+ };
63
+
64
+ export async function getServerSideProps(context: GetServerSidePropsContext) {
65
+ const { author, color } = context.query;
66
+
67
+ const authorColor = color || DEFAULT_COLOR;
68
+
69
+ const providers = {
70
+ [author as string]: {
71
+ color: authorColor as string,
72
+ authors: [author as string],
73
+ },
74
+ };
75
+
76
+ try {
77
+ const response = await fetch(
78
+ `https://huggingface.co/api/models?author=${author}&sort=createdAt&direction=-1`
79
+ );
80
+ const data = await response.json();
81
+
82
+ const modelData = data.map((item: any) => ({
83
+ createdAt: item.createdAt,
84
+ id: item.id,
85
+ }));
86
+
87
+ const calendarData = generateCalendarData(modelData, providers);
88
+
89
+ return {
90
+ props: {
91
+ calendarData,
92
+ color: authorColor,
93
+ providers,
94
+ },
95
+ };
96
+ } catch (error) {
97
+ console.error("Error fetching data:", error);
98
+ return {
99
+ props: {
100
+ calendarData: {},
101
+ color: authorColor,
102
+ providers,
103
+ },
104
+ };
105
+ }
106
+ }
107
+
108
+
109
+ export default OpenSourceHeatmap;
src/pages/_document.tsx CHANGED
@@ -10,4 +10,4 @@ export default function Document() {
10
  </body>
11
  </Html>
12
  );
13
- }
 
10
  </body>
11
  </Html>
12
  );
13
+ }
src/pages/index.tsx CHANGED
@@ -1,11 +1,8 @@
1
  import React, { useState, useEffect } from 'react';
2
  import ActivityCalendar from "react-activity-calendar";
3
  import { Tooltip } from '@mui/material';
4
-
5
- interface ProviderInfo {
6
- color: string;
7
- authors: string[];
8
- }
9
 
10
  const PROVIDERS_MAP: Record<string, ProviderInfo> = {
11
  "Mistral AI": { color: "#ff7000", authors: ["mistralai"] },
@@ -24,77 +21,6 @@ const PROVIDERS_MAP: Record<string, ProviderInfo> = {
24
  "Stability AI": { color: "#A020F0", authors: ["stabilityai"] },
25
  };
26
 
27
- interface ModelData {
28
- createdAt: string;
29
- id: string;
30
- }
31
-
32
- interface Activity {
33
- date: string;
34
- count: number;
35
- level: number;
36
- }
37
-
38
- interface CalendarData {
39
- [key: string]: Activity[];
40
- }
41
-
42
- const generateCalendarData = (modelData: ModelData[]): CalendarData => {
43
- const data: Record<string, Activity[]> = Object.fromEntries(
44
- Object.keys(PROVIDERS_MAP).map(provider => [provider, []])
45
- );
46
-
47
- const today = new Date();
48
- const startDate = new Date(today);
49
- startDate.setMonth(today.getMonth() - 11);
50
- startDate.setDate(1);
51
-
52
- // create a map to store counts for each provider and date
53
- const countMap: Record<string, Record<string, number>> = {};
54
-
55
- modelData.forEach(item => {
56
- const dateString = item.createdAt.split('T')[0];
57
- Object.entries(PROVIDERS_MAP).forEach(([provider, { authors }]) => {
58
- if (authors.some(author => item.id.startsWith(author))) {
59
- countMap[provider] = countMap[provider] || {};
60
- countMap[provider][dateString] = (countMap[provider][dateString] || 0) + 1;
61
- }
62
- });
63
- });
64
-
65
- // fill in with 0s for days with no activity
66
- for (let d = new Date(startDate); d <= today; d.setDate(d.getDate() + 1)) {
67
- const dateString = d.toISOString().split('T')[0];
68
-
69
- Object.entries(PROVIDERS_MAP).forEach(([provider]) => {
70
- const count = countMap[provider]?.[dateString] || 0;
71
- data[provider].push({ date: dateString, count, level: 0 });
72
- });
73
- }
74
-
75
- // calculate average counts for each provider
76
- const avgCounts = Object.fromEntries(
77
- Object.entries(data).map(([provider, days]) => [
78
- provider,
79
- days.reduce((sum, day) => sum + day.count, 0) / days.length || 0
80
- ])
81
- );
82
-
83
- // assign levels based on count relative to average
84
- Object.entries(data).forEach(([provider, days]) => {
85
- const avgCount = avgCounts[provider];
86
- days.forEach(day => {
87
- day.level =
88
- day.count === 0 ? 0 :
89
- day.count <= avgCount * 0.5 ? 1 :
90
- day.count <= avgCount ? 2 :
91
- day.count <= avgCount * 1.5 ? 3 : 4;
92
- });
93
- });
94
-
95
- return data;
96
- }
97
-
98
  export async function getStaticProps() {
99
  try {
100
  const allAuthors = Object.values(PROVIDERS_MAP).flatMap(({ authors }) => authors);
@@ -111,12 +37,13 @@ export async function getStaticProps() {
111
  })
112
  );
113
 
114
- const flatModelData = allModelData.flat();
115
- const calendarData = generateCalendarData(flatModelData);
116
 
117
  return {
118
  props: {
119
  calendarData,
 
120
  },
121
  revalidate: 3600, // regenerate every hour
122
  };
@@ -125,17 +52,14 @@ export async function getStaticProps() {
125
  return {
126
  props: {
127
  calendarData: {},
 
128
  },
129
  revalidate: 60, // retry after 1 minute if there was an error
130
  };
131
  }
132
  }
133
 
134
- interface OpenSourceHeatmapProps {
135
- calendarData: CalendarData;
136
- }
137
-
138
- const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({ calendarData }) => {
139
  const [isLoading, setIsLoading] = useState(true);
140
 
141
  useEffect(() => {
@@ -164,7 +88,7 @@ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({ calendarData }) =
164
  <p className="text-center">Loading...</p>
165
  ) : (
166
  <div className="space-y-8">
167
- {Object.entries(PROVIDERS_MAP)
168
  .sort(([keyA], [keyB]) =>
169
  calendarData[keyB].reduce((sum, day) => sum + day.count, 0) -
170
  calendarData[keyA].reduce((sum, day) => sum + day.count, 0)
 
1
  import React, { useState, useEffect } from 'react';
2
  import ActivityCalendar from "react-activity-calendar";
3
  import { Tooltip } from '@mui/material';
4
+ import { generateCalendarData } from "../utils/calendar";
5
+ import { OpenSourceHeatmapProps, ProviderInfo, ModelData, CalendarData } from "../types/heatmap";
 
 
 
6
 
7
  const PROVIDERS_MAP: Record<string, ProviderInfo> = {
8
  "Mistral AI": { color: "#ff7000", authors: ["mistralai"] },
 
21
  "Stability AI": { color: "#A020F0", authors: ["stabilityai"] },
22
  };
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  export async function getStaticProps() {
25
  try {
26
  const allAuthors = Object.values(PROVIDERS_MAP).flatMap(({ authors }) => authors);
 
37
  })
38
  );
39
 
40
+ const flatModelData: ModelData[] = allModelData.flat();
41
+ const calendarData = generateCalendarData(flatModelData, PROVIDERS_MAP);
42
 
43
  return {
44
  props: {
45
  calendarData,
46
+ providers: PROVIDERS_MAP,
47
  },
48
  revalidate: 3600, // regenerate every hour
49
  };
 
52
  return {
53
  props: {
54
  calendarData: {},
55
+ providers: PROVIDERS_MAP,
56
  },
57
  revalidate: 60, // retry after 1 minute if there was an error
58
  };
59
  }
60
  }
61
 
62
+ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({ calendarData, providers }) => {
 
 
 
 
63
  const [isLoading, setIsLoading] = useState(true);
64
 
65
  useEffect(() => {
 
88
  <p className="text-center">Loading...</p>
89
  ) : (
90
  <div className="space-y-8">
91
+ {Object.entries(providers)
92
  .sort(([keyA], [keyB]) =>
93
  calendarData[keyB].reduce((sum, day) => sum + day.count, 0) -
94
  calendarData[keyA].reduce((sum, day) => sum + day.count, 0)
src/types/heatmap.ts ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export interface ProviderInfo {
2
+ color: string;
3
+ authors: string[];
4
+ }
5
+
6
+ export interface ModelData {
7
+ createdAt: string;
8
+ id: string;
9
+ }
10
+
11
+ export interface Activity {
12
+ date: string;
13
+ count: number;
14
+ level: number;
15
+ }
16
+
17
+ export interface CalendarData {
18
+ [key: string]: Activity[];
19
+ }
20
+
21
+ export interface OpenSourceHeatmapProps {
22
+ calendarData: CalendarData;
23
+ author: string;
24
+ color: string;
25
+ providers: Record<string, ProviderInfo>;
26
+ }
src/utils/calendar.ts ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ModelData, ProviderInfo, CalendarData, Activity } from "../types/heatmap";
2
+
3
+ export const generateCalendarData = (
4
+ modelData: ModelData[],
5
+ providers: Record<string, ProviderInfo>,
6
+ ): CalendarData => {
7
+ const data: Record<string, Activity[]> = Object.fromEntries(
8
+ Object.keys(providers).map((provider) => [provider, []]),
9
+ );
10
+
11
+ const today = new Date();
12
+ const startDate = new Date(today);
13
+ startDate.setMonth(today.getMonth() - 11);
14
+ startDate.setDate(1);
15
+
16
+ // create a map to store counts for each provider and date
17
+ const countMap: Record<string, Record<string, number>> = {};
18
+
19
+ modelData.forEach((item) => {
20
+ const dateString = item.createdAt.split("T")[0];
21
+ Object.entries(providers).forEach(([provider, { authors }]) => {
22
+ if (authors.some((author) => item.id.startsWith(author))) {
23
+ countMap[provider] = countMap[provider] || {};
24
+ countMap[provider][dateString] =
25
+ (countMap[provider][dateString] || 0) + 1;
26
+ }
27
+ });
28
+ });
29
+
30
+ // fill in with 0s for days with no activity
31
+ for (let d = new Date(startDate); d <= today; d.setDate(d.getDate() + 1)) {
32
+ const dateString = d.toISOString().split("T")[0];
33
+
34
+ Object.entries(providers).forEach(([provider]) => {
35
+ const count = countMap[provider]?.[dateString] || 0;
36
+ data[provider].push({ date: dateString, count, level: 0 });
37
+ });
38
+ }
39
+
40
+ // calculate average counts for each provider
41
+ const avgCounts = Object.fromEntries(
42
+ Object.entries(data).map(([provider, days]) => [
43
+ provider,
44
+ days.reduce((sum, day) => sum + day.count, 0) / days.length || 0,
45
+ ]),
46
+ );
47
+
48
+ // assign levels based on count relative to average
49
+ Object.entries(data).forEach(([provider, days]) => {
50
+ const avgCount = avgCounts[provider];
51
+ days.forEach((day) => {
52
+ day.level =
53
+ day.count === 0
54
+ ? 0
55
+ : day.count <= avgCount * 0.5
56
+ ? 1
57
+ : day.count <= avgCount
58
+ ? 2
59
+ : day.count <= avgCount * 1.5
60
+ ? 3
61
+ : 4;
62
+ });
63
+ });
64
+
65
+ return data;
66
+ };
tailwind.config.ts CHANGED
@@ -17,4 +17,4 @@ const config: Config = {
17
  },
18
  plugins: [],
19
  };
20
- export default config;
 
17
  },
18
  plugins: [],
19
  };
20
+ export default config;