hover text showing repo names

#9
by evijit HF Staff - opened
src/components/Heatmap.tsx CHANGED
@@ -106,14 +106,25 @@ const Heatmap: React.FC<HeatmapProps> = ({
106
  blockSize={11}
107
  blockMargin={2}
108
  hideTotalCount
109
- renderBlock={(block, activity) => (
110
- <Tooltip
111
- title={`${activity.count} new repos on ${activity.date}`}
112
- arrow
113
- >
114
- {block}
115
- </Tooltip>
116
- )}
 
 
 
 
 
 
 
 
 
 
 
117
  />
118
  )}
119
  </div>
 
106
  blockSize={11}
107
  blockMargin={2}
108
  hideTotalCount
109
+ renderBlock={(block, activity) => {
110
+ const activityData = activity as any; // Type assertion since react-activity-calendar may not have our extended type
111
+ const itemsText = activityData.items && activityData.items.length > 0
112
+ ? activityData.items.join(', ')
113
+ : 'No releases';
114
+
115
+ const tooltipTitle = activity.count > 0
116
+ ? `${activity.count} new repos on ${activity.date}: ${itemsText}`
117
+ : `No repos on ${activity.date}`;
118
+
119
+ return (
120
+ <Tooltip
121
+ title={tooltipTitle}
122
+ arrow
123
+ >
124
+ {block}
125
+ </Tooltip>
126
+ );
127
+ }}
128
  />
129
  )}
130
  </div>
src/components/WeeklyHeatmap.tsx CHANGED
@@ -7,6 +7,7 @@ type WeeklyActivity = {
7
  date: string;
8
  count: number;
9
  level: number;
 
10
  };
11
 
12
  type WeeklyHeatmapProps = {
@@ -80,20 +81,30 @@ const WeeklyHeatmap: React.FC<WeeklyHeatmapProps> = ({ data, color }) => {
80
  {getMonthName(yearMonth)}
81
  </div>
82
  <div className="flex gap-1">
83
- {monthData.map((activity, index) => (
84
- <Tooltip
85
- key={`${yearMonth}-${index}`}
86
- title={`${activity.count} new repos in week of ${getWeekDateRange(activity.date)}`}
87
- arrow
88
- >
89
- <div
90
- className="w-3 h-3 rounded-sm cursor-pointer transition-opacity hover:opacity-80"
91
- style={{
92
- backgroundColor: activity.level === 0 ? emptyDotColor : getColorIntensity(activity.level),
93
- }}
94
- />
95
- </Tooltip>
96
- ))}
 
 
 
 
 
 
 
 
 
 
97
  </div>
98
  </div>
99
  );
 
7
  date: string;
8
  count: number;
9
  level: number;
10
+ items?: string[];
11
  };
12
 
13
  type WeeklyHeatmapProps = {
 
81
  {getMonthName(yearMonth)}
82
  </div>
83
  <div className="flex gap-1">
84
+ {monthData.map((activity, index) => {
85
+ const itemsText = activity.items && activity.items.length > 0
86
+ ? activity.items.join(', ')
87
+ : 'No releases';
88
+
89
+ const tooltipTitle = activity.count > 0
90
+ ? `${activity.count} new repos in week of ${getWeekDateRange(activity.date)}: ${itemsText}`
91
+ : `No repos in week of ${getWeekDateRange(activity.date)}`;
92
+
93
+ return (
94
+ <Tooltip
95
+ key={`${yearMonth}-${index}`}
96
+ title={tooltipTitle}
97
+ arrow
98
+ >
99
+ <div
100
+ className="w-3 h-3 rounded-sm cursor-pointer transition-opacity hover:opacity-80"
101
+ style={{
102
+ backgroundColor: activity.level === 0 ? emptyDotColor : getColorIntensity(activity.level),
103
+ }}
104
+ />
105
+ </Tooltip>
106
+ );
107
+ })}
108
  </div>
109
  </div>
110
  );
src/types/heatmap.ts CHANGED
@@ -34,6 +34,7 @@ export interface Activity {
34
  date: string;
35
  count: number;
36
  level: number;
 
37
  }
38
 
39
  export interface CalendarData {
 
34
  date: string;
35
  count: number;
36
  level: number;
37
+ items?: string[]; // Array of item names released on this date
38
  }
39
 
40
  export interface CalendarData {
src/utils/calendar.ts CHANGED
@@ -25,16 +25,27 @@ export const generateCalendarData = (
25
  const dayOfWeek = startDate.getDay();
26
  startDate.setDate(startDate.getDate() - dayOfWeek);
27
 
28
- // create a map to store counts for each provider and date
29
  const countMap: Record<string, Record<string, number>> = {};
 
30
 
31
  modelData.forEach((item) => {
32
  const dateString = item.createdAt.split("T")[0];
33
  providers.forEach(({ authors }) => {
34
  if (authors.some((author) => item.id.startsWith(author))) {
35
- countMap[authors[0]] = countMap[authors[0]] || {};
36
- countMap[authors[0]][dateString] =
37
- (countMap[authors[0]][dateString] || 0) + 1;
 
 
 
 
 
 
 
 
 
 
38
  }
39
  });
40
  });
@@ -44,8 +55,16 @@ export const generateCalendarData = (
44
  const dateString = d.toISOString().split("T")[0];
45
 
46
  providers.forEach(({ authors }) => {
47
- const count = countMap[authors[0]]?.[dateString] || 0;
48
- data[authors[0]].push({ date: dateString, count, level: 0 });
 
 
 
 
 
 
 
 
49
  });
50
  }
51
 
 
25
  const dayOfWeek = startDate.getDay();
26
  startDate.setDate(startDate.getDate() - dayOfWeek);
27
 
28
+ // create a map to store counts and item names for each provider and date
29
  const countMap: Record<string, Record<string, number>> = {};
30
+ const itemsMap: Record<string, Record<string, string[]>> = {};
31
 
32
  modelData.forEach((item) => {
33
  const dateString = item.createdAt.split("T")[0];
34
  providers.forEach(({ authors }) => {
35
  if (authors.some((author) => item.id.startsWith(author))) {
36
+ const providerKey = authors[0];
37
+
38
+ // Initialize maps if needed
39
+ countMap[providerKey] = countMap[providerKey] || {};
40
+ itemsMap[providerKey] = itemsMap[providerKey] || {};
41
+
42
+ // Increment count
43
+ countMap[providerKey][dateString] =
44
+ (countMap[providerKey][dateString] || 0) + 1;
45
+
46
+ // Add item name to the list
47
+ itemsMap[providerKey][dateString] = itemsMap[providerKey][dateString] || [];
48
+ itemsMap[providerKey][dateString].push(item.id);
49
  }
50
  });
51
  });
 
55
  const dateString = d.toISOString().split("T")[0];
56
 
57
  providers.forEach(({ authors }) => {
58
+ const providerKey = authors[0];
59
+ const count = countMap[providerKey]?.[dateString] || 0;
60
+ const items = itemsMap[providerKey]?.[dateString] || [];
61
+
62
+ data[providerKey].push({
63
+ date: dateString,
64
+ count,
65
+ level: 0,
66
+ items
67
+ });
68
  });
69
  }
70
 
src/utils/weeklyCalendar.ts CHANGED
@@ -4,7 +4,7 @@ export const aggregateToWeeklyData = (dailyData: Activity[]): Activity[] => {
4
  if (!dailyData || dailyData.length === 0) return [];
5
 
6
  // Create a map to group activities by week
7
- const weeklyMap = new Map<string, { count: number; level: number; dates: string[] }>();
8
 
9
  for (const dayActivity of dailyData) {
10
  const date = new Date(dayActivity.date);
@@ -14,13 +14,18 @@ export const aggregateToWeeklyData = (dailyData: Activity[]): Activity[] => {
14
  const weekKey = weekStart.toISOString().split('T')[0];
15
 
16
  if (!weeklyMap.has(weekKey)) {
17
- weeklyMap.set(weekKey, { count: 0, level: 0, dates: [] });
18
  }
19
 
20
  const weekData = weeklyMap.get(weekKey)!;
21
  weekData.count += dayActivity.count;
22
  weekData.level = Math.max(weekData.level, dayActivity.level);
23
  weekData.dates.push(dayActivity.date);
 
 
 
 
 
24
  }
25
 
26
  // Convert to true weekly data - one entry per week, not per day
@@ -31,6 +36,7 @@ export const aggregateToWeeklyData = (dailyData: Activity[]): Activity[] => {
31
  date: weekStartDate, // Use the week start date
32
  count: weekInfo.count,
33
  level: weekInfo.level,
 
34
  });
35
  });
36
 
 
4
  if (!dailyData || dailyData.length === 0) return [];
5
 
6
  // Create a map to group activities by week
7
+ const weeklyMap = new Map<string, { count: number; level: number; dates: string[]; items: string[] }>();
8
 
9
  for (const dayActivity of dailyData) {
10
  const date = new Date(dayActivity.date);
 
14
  const weekKey = weekStart.toISOString().split('T')[0];
15
 
16
  if (!weeklyMap.has(weekKey)) {
17
+ weeklyMap.set(weekKey, { count: 0, level: 0, dates: [], items: [] });
18
  }
19
 
20
  const weekData = weeklyMap.get(weekKey)!;
21
  weekData.count += dayActivity.count;
22
  weekData.level = Math.max(weekData.level, dayActivity.level);
23
  weekData.dates.push(dayActivity.date);
24
+
25
+ // Aggregate items from daily data
26
+ if (dayActivity.items) {
27
+ weekData.items.push(...dayActivity.items);
28
+ }
29
  }
30
 
31
  // Convert to true weekly data - one entry per week, not per day
 
36
  date: weekStartDate, // Use the week start date
37
  count: weekInfo.count,
38
  level: weekInfo.level,
39
+ items: weekInfo.items, // Include aggregated items
40
  });
41
  });
42