File size: 4,618 Bytes
e2e991a
98f8d8e
 
1f1c117
e2e991a
 
98f8d8e
 
e2e991a
98f8d8e
 
 
1f1c117
 
 
e2e991a
1f1c117
 
e2e991a
 
 
 
1f1c117
e2e991a
1f1c117
 
e2e991a
1f1c117
 
e2e991a
1f1c117
e2e991a
1f1c117
 
98f8d8e
 
 
 
 
 
e2e991a
98f8d8e
 
 
 
 
 
1f1c117
 
 
 
 
 
 
 
 
 
 
 
 
 
98f8d8e
 
 
 
 
 
 
 
 
 
e2e991a
98f8d8e
 
e2e991a
98f8d8e
e2e991a
98f8d8e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e2e991a
 
98f8d8e
 
 
 
 
 
 
e2e991a
98f8d8e
 
e2e991a
98f8d8e
e2e991a
98f8d8e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { useState, useEffect } from 'react';
import ActivityCalendar from 'react-activity-calendar';
import { Tooltip } from '@mui/material';
import Link from 'next/link';
import { fetchAllModelData, generateCalendarData, aggregateCalendarData, CalendarData, Activity } from '@/utils/modelData';
import { PROVIDERS_MAP } from '@/utils/providers';

interface OpenSourceHeatmapProps {
  calendarData: CalendarData & { total: Activity[] };
}

export const getStaticProps = async () => {
  try {
    const modelData = await fetchAllModelData();
    const calendarData = generateCalendarData(modelData);
    
    return {
      props: {
        calendarData: {
          total: aggregateCalendarData(calendarData),
          ...calendarData
        }
      },
      revalidate: process.env.VERCEL_ENV === 'production' ? 43200 : 3600, // 12 hours in production, 1 hour in development
    };
  } catch (error) {
    console.error('Error fetching model data:', error);
    return {
      props: {
        calendarData: { total: [] }
      },
      revalidate: 3600, // 1 hour on error
    };
  }
};

const OpenSourceHeatmap: React.FC<OpenSourceHeatmapProps> = ({ calendarData }) => {
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    if (calendarData && calendarData.total && calendarData.total.length > 0) {
      setIsLoading(false);
    }
  }, [calendarData]);

  return (
    <div className="w-full max-w-screen-lg mx-auto p-4">
      <div className="flex justify-between items-center mb-8">
        <div>
          <h1 className="text-3xl lg:text-4xl font-bold mb-2">Chinese AI Open Source Heatmap 🤗</h1>
          <p className="text-gray-600 dark:text-gray-400">
            Visualize the activity of Chinese AI models and datasets
          </p>
        </div>
        <Link 
          href="/trend"
          className="px-4 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors"
        >
          View Trends
        </Link>
      </div>
      {isLoading ? (
        <p className="text-center">Loading...</p>
      ) : (
        <div className="space-y-8 mx-10">
          {/* Total Activity Heatmap */}
          <div className="flex flex-col">
            <h2 className="text-2xl font-bold mb-2">Total Activity</h2>
            <div className="w-full overflow-x-auto">
              <div className="inline-block mx-auto">
                <ActivityCalendar
                  data={calendarData.total}
                  theme={{
                    dark: ['#161b22', '#4CAF50'],
                    light: ['#161b22', '#4CAF50'],
                  }}
                  colorScheme="dark"
                  hideTotalCount
                  renderBlock={(block, activity) => (
                    <Tooltip
                      title={`${activity.count} total models created on ${activity.date}`}
                      arrow
                    >
                      {block}
                    </Tooltip>
                  )}
                />
              </div>
            </div>
          </div>

          <h2 className="text-2xl font-bold mt-12 mb-6">Activity by Organization</h2>
          
          {/* Individual Provider Heatmaps */}
          {Object.entries(PROVIDERS_MAP)
            .sort(([keyA], [keyB]) =>
              (calendarData[keyB] || []).reduce((sum, day) => sum + day.count, 0) -
              (calendarData[keyA] || []).reduce((sum, day) => sum + day.count, 0)
            )
            .map(([providerName, { color }]) => (
              <div key={providerName} className="flex flex-col">
                <h2 className="text-xl font-bold mb-2">{providerName}</h2>
                <div className="w-full overflow-x-auto">
                  <div className="inline-block mx-auto">
                    <ActivityCalendar
                      data={calendarData[providerName] || []}
                      theme={{
                        dark: ['#161b22', color],
                        light: ['#161b22', color],
                      }}
                      colorScheme="dark"
                      hideTotalCount
                      renderBlock={(block, activity) => (
                        <Tooltip
                          title={`${activity.count} models created on ${activity.date}`}
                          arrow
                        >
                          {block}
                        </Tooltip>
                      )}
                    />
                  </div>
                </div>
              </div>
            ))}
        </div>
      )}
    </div>
  );
};

export default OpenSourceHeatmap;