Xianbao QIAN commited on
Commit
e2e991a
·
1 Parent(s): 1f1c117

fix a few minor issues

Browse files
Files changed (4) hide show
  1. bun.lockb +0 -0
  2. package.json +1 -0
  3. src/pages/heatmap/index.tsx +22 -20
  4. src/utils/modelData.ts +16 -26
bun.lockb CHANGED
Binary files a/bun.lockb and b/bun.lockb differ
 
package.json CHANGED
@@ -13,6 +13,7 @@
13
  "@emotion/styled": "^11.13.0",
14
  "@mui/material": "^5.16.6",
15
  "next": "14.2.5",
 
16
  "react": "^18",
17
  "react-activity-calendar": "^2.2.11",
18
  "react-dom": "^18",
 
13
  "@emotion/styled": "^11.13.0",
14
  "@mui/material": "^5.16.6",
15
  "next": "14.2.5",
16
+ "next-themes": "^0.4.3",
17
  "react": "^18",
18
  "react-activity-calendar": "^2.2.11",
19
  "react-dom": "^18",
src/pages/heatmap/index.tsx CHANGED
@@ -1,35 +1,35 @@
1
- import React, { useState, useEffect } from 'react';
2
  import ActivityCalendar from 'react-activity-calendar';
3
  import { Tooltip } from '@mui/material';
4
- import { PROVIDERS_MAP } from '../../utils/providers';
5
- import { CalendarData, fetchAllModelData, generateCalendarData, aggregateCalendarData } from '../../utils/modelData';
6
  import Link from 'next/link';
 
 
7
 
8
  interface OpenSourceHeatmapProps {
9
- calendarData: CalendarData;
10
  }
11
 
12
  export const getStaticProps = async () => {
13
  try {
14
  const modelData = await fetchAllModelData();
15
  const calendarData = generateCalendarData(modelData);
16
- const aggregatedData = aggregateCalendarData(calendarData);
17
-
18
  return {
19
  props: {
20
- calendarData: aggregatedData,
 
 
 
21
  },
22
- // Revalidate every 12 hours
23
- revalidate: 43200,
24
  };
25
  } catch (error) {
26
- console.error('Error in getStaticProps:', error);
27
  return {
28
  props: {
29
- calendarData: {},
30
  },
31
- // Retry more frequently if there was an error
32
- revalidate: 3600,
33
  };
34
  }
35
  };
@@ -38,7 +38,7 @@ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({ calendarData }) =
38
  const [isLoading, setIsLoading] = useState(true);
39
 
40
  useEffect(() => {
41
- if (calendarData && Object.keys(calendarData).length > 0) {
42
  setIsLoading(false);
43
  }
44
  }, [calendarData]);
@@ -69,11 +69,12 @@ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({ calendarData }) =
69
  <div className="w-full overflow-x-auto">
70
  <div className="inline-block mx-auto">
71
  <ActivityCalendar
72
- data={calendarData}
73
  theme={{
74
  dark: ['#161b22', '#4CAF50'],
75
- light: ['#e0e0e0', '#4CAF50'],
76
  }}
 
77
  hideTotalCount
78
  renderBlock={(block, activity) => (
79
  <Tooltip
@@ -93,8 +94,8 @@ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({ calendarData }) =
93
  {/* Individual Provider Heatmaps */}
94
  {Object.entries(PROVIDERS_MAP)
95
  .sort(([keyA], [keyB]) =>
96
- calendarData[keyB].reduce((sum, day) => sum + day.count, 0) -
97
- calendarData[keyA].reduce((sum, day) => sum + day.count, 0)
98
  )
99
  .map(([providerName, { color }]) => (
100
  <div key={providerName} className="flex flex-col">
@@ -102,11 +103,12 @@ const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({ calendarData }) =
102
  <div className="w-full overflow-x-auto">
103
  <div className="inline-block mx-auto">
104
  <ActivityCalendar
105
- data={calendarData[providerName]}
106
  theme={{
107
  dark: ['#161b22', color],
108
- light: ['#e0e0e0', color],
109
  }}
 
110
  hideTotalCount
111
  renderBlock={(block, activity) => (
112
  <Tooltip
 
1
+ import { useState, useEffect } from 'react';
2
  import ActivityCalendar from 'react-activity-calendar';
3
  import { Tooltip } from '@mui/material';
 
 
4
  import Link from 'next/link';
5
+ import { fetchAllModelData, generateCalendarData, aggregateCalendarData, CalendarData, Activity } from '@/utils/modelData';
6
+ import { PROVIDERS_MAP } from '@/utils/providers';
7
 
8
  interface OpenSourceHeatmapProps {
9
+ calendarData: CalendarData & { total: Activity[] };
10
  }
11
 
12
  export const getStaticProps = async () => {
13
  try {
14
  const modelData = await fetchAllModelData();
15
  const calendarData = generateCalendarData(modelData);
16
+
 
17
  return {
18
  props: {
19
+ calendarData: {
20
+ total: aggregateCalendarData(calendarData),
21
+ ...calendarData
22
+ }
23
  },
24
+ revalidate: process.env.VERCEL_ENV === 'production' ? 43200 : 3600, // 12 hours in production, 1 hour in development
 
25
  };
26
  } catch (error) {
27
+ console.error('Error fetching model data:', error);
28
  return {
29
  props: {
30
+ calendarData: { total: [] }
31
  },
32
+ revalidate: 3600, // 1 hour on error
 
33
  };
34
  }
35
  };
 
38
  const [isLoading, setIsLoading] = useState(true);
39
 
40
  useEffect(() => {
41
+ if (calendarData && calendarData.total && calendarData.total.length > 0) {
42
  setIsLoading(false);
43
  }
44
  }, [calendarData]);
 
69
  <div className="w-full overflow-x-auto">
70
  <div className="inline-block mx-auto">
71
  <ActivityCalendar
72
+ data={calendarData.total}
73
  theme={{
74
  dark: ['#161b22', '#4CAF50'],
75
+ light: ['#161b22', '#4CAF50'],
76
  }}
77
+ colorScheme="dark"
78
  hideTotalCount
79
  renderBlock={(block, activity) => (
80
  <Tooltip
 
94
  {/* Individual Provider Heatmaps */}
95
  {Object.entries(PROVIDERS_MAP)
96
  .sort(([keyA], [keyB]) =>
97
+ (calendarData[keyB] || []).reduce((sum, day) => sum + day.count, 0) -
98
+ (calendarData[keyA] || []).reduce((sum, day) => sum + day.count, 0)
99
  )
100
  .map(([providerName, { color }]) => (
101
  <div key={providerName} className="flex flex-col">
 
103
  <div className="w-full overflow-x-auto">
104
  <div className="inline-block mx-auto">
105
  <ActivityCalendar
106
+ data={calendarData[providerName] || []}
107
  theme={{
108
  dark: ['#161b22', color],
109
+ light: ['#161b22', color],
110
  }}
111
+ colorScheme="dark"
112
  hideTotalCount
113
  renderBlock={(block, activity) => (
114
  <Tooltip
src/utils/modelData.ts CHANGED
@@ -1,10 +1,13 @@
1
  import { PROVIDERS_MAP } from './providers';
2
 
3
  export interface ModelData {
4
- createdAt: string;
5
  id: string;
6
- likes?: number;
 
 
 
7
  isDataset?: boolean;
 
8
  }
9
 
10
  export interface Activity {
@@ -25,8 +28,10 @@ export interface MonthlyActivity {
25
  name?: string;
26
  }
27
 
28
- export interface DetailedModelData extends ModelData {
 
29
  name: string;
 
30
  likes: number;
31
  downloads: number;
32
  monthKey: string; // YYYY-MM
@@ -136,7 +141,7 @@ export const generateMonthlyData = (modelData: ModelData[]): MonthlyActivity[] =
136
  date: monthKey,
137
  count: 0,
138
  provider,
139
- isDataset: model.isDataset,
140
  name: model.name
141
  };
142
  }
@@ -243,38 +248,23 @@ export const fetchAllModelData = async (): Promise<ModelData[]> => {
243
  };
244
 
245
  export function processDetailedModelData(models: ModelData[]): DetailedModelData[] {
246
- if (!models || models.length === 0) {
247
- return [];
248
- }
249
-
250
  return models.map(model => {
251
  const date = new Date(model.createdAt);
252
- const monthKey = date.toLocaleDateString('en-US', {
253
- year: 'numeric',
254
- month: 'long'
255
- });
256
- const sortKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
257
- const [org] = model.id.split('/');
258
- const provider = Object.entries(PROVIDERS_MAP).find(([_, info]) =>
259
- info.authors.includes(org)
260
- )?.[0] || 'unknown';
261
 
262
  return {
263
- ...model,
264
  name: model.name || model.id,
 
265
  likes: model.likes || 0,
266
- downloads: model.downloads || 0,
267
  monthKey,
268
  provider,
269
  sortKey,
270
- isDataset: model.isDataset || false
271
  };
272
- }).sort((a, b) => {
273
- // First sort by sortKey (year-month) in descending order
274
- const dateCompare = b.sortKey.localeCompare(a.sortKey);
275
- if (dateCompare !== 0) return dateCompare;
276
- // Then by likes for items in the same month
277
- return (b.likes || 0) - (a.likes || 0);
278
  });
279
  }
280
 
 
1
  import { PROVIDERS_MAP } from './providers';
2
 
3
  export interface ModelData {
 
4
  id: string;
5
+ name: string;
6
+ createdAt: string;
7
+ likes: number;
8
+ downloads?: number;
9
  isDataset?: boolean;
10
+ provider: string;
11
  }
12
 
13
  export interface Activity {
 
28
  name?: string;
29
  }
30
 
31
+ export interface DetailedModelData {
32
+ id: string;
33
  name: string;
34
+ createdAt: string;
35
  likes: number;
36
  downloads: number;
37
  monthKey: string; // YYYY-MM
 
141
  date: monthKey,
142
  count: 0,
143
  provider,
144
+ isDataset: model.isDataset ?? false, // Use nullish coalescing to provide a default
145
  name: model.name
146
  };
147
  }
 
248
  };
249
 
250
  export function processDetailedModelData(models: ModelData[]): DetailedModelData[] {
 
 
 
 
251
  return models.map(model => {
252
  const date = new Date(model.createdAt);
253
+ const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
254
+ const provider = model.provider || 'unknown';
255
+ const sortKey = `${monthKey}-${model.name}`;
 
 
 
 
 
 
256
 
257
  return {
258
+ id: model.id,
259
  name: model.name || model.id,
260
+ createdAt: model.createdAt,
261
  likes: model.likes || 0,
262
+ downloads: model.downloads || 0, // Set downloads to 0 if it's undefined
263
  monthKey,
264
  provider,
265
  sortKey,
266
+ isDataset: model.isDataset ?? false
267
  };
 
 
 
 
 
 
268
  });
269
  }
270