@stoked-ui/github 0.0.0-a.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CHANGELOG.md +15014 -0
  2. package/GithubCalendar/GithubCalendar.d.ts +7 -0
  3. package/GithubCalendar/GithubCalendar.js +330 -0
  4. package/GithubCalendar/index.d.ts +2 -0
  5. package/GithubCalendar/index.js +2 -0
  6. package/GithubCalendar/package.json +6 -0
  7. package/GithubEvents/EventTypes/CreateEvent.d.ts +7 -0
  8. package/GithubEvents/EventTypes/CreateEvent.js +72 -0
  9. package/GithubEvents/EventTypes/DeleteEvent.d.ts +7 -0
  10. package/GithubEvents/EventTypes/DeleteEvent.js +65 -0
  11. package/GithubEvents/EventTypes/ForkEvent.d.ts +7 -0
  12. package/GithubEvents/EventTypes/ForkEvent.js +77 -0
  13. package/GithubEvents/EventTypes/IssueCommentEvent.d.ts +7 -0
  14. package/GithubEvents/EventTypes/IssueCommentEvent.js +210 -0
  15. package/GithubEvents/EventTypes/IssuesEvent.d.ts +7 -0
  16. package/GithubEvents/EventTypes/IssuesEvent.js +97 -0
  17. package/GithubEvents/EventTypes/ProjectsV2ColumnEvent.d.ts +7 -0
  18. package/GithubEvents/EventTypes/ProjectsV2ColumnEvent.js +69 -0
  19. package/GithubEvents/EventTypes/ProjectsV2Event.d.ts +7 -0
  20. package/GithubEvents/EventTypes/ProjectsV2Event.js +74 -0
  21. package/GithubEvents/EventTypes/ProjectsV2FieldEvent.d.ts +7 -0
  22. package/GithubEvents/EventTypes/ProjectsV2FieldEvent.js +77 -0
  23. package/GithubEvents/EventTypes/ProjectsV2ItemEvent.d.ts +7 -0
  24. package/GithubEvents/EventTypes/ProjectsV2ItemEvent.js +79 -0
  25. package/GithubEvents/EventTypes/PullRequest/CommitsList.d.ts +17 -0
  26. package/GithubEvents/EventTypes/PullRequest/CommitsList.js +99 -0
  27. package/GithubEvents/EventTypes/PullRequest/FileChanges.d.ts +17 -0
  28. package/GithubEvents/EventTypes/PullRequest/FileChanges.js +182 -0
  29. package/GithubEvents/EventTypes/PullRequest/PullRequestEvent.d.ts +8 -0
  30. package/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +374 -0
  31. package/GithubEvents/EventTypes/PullRequest/PullRequestView.d.ts +29 -0
  32. package/GithubEvents/EventTypes/PullRequest/PullRequestView.js +132 -0
  33. package/GithubEvents/EventTypes/PushEvent.d.ts +7 -0
  34. package/GithubEvents/EventTypes/PushEvent.js +106 -0
  35. package/GithubEvents/GithubEvents.d.ts +49 -0
  36. package/GithubEvents/GithubEvents.js +1454 -0
  37. package/GithubEvents/index.d.ts +2 -0
  38. package/GithubEvents/index.js +2 -0
  39. package/GithubEvents/package.json +6 -0
  40. package/LICENSE +21 -0
  41. package/README.md +29 -0
  42. package/apiHandlers/getPullRequestDetails.d.ts +7 -0
  43. package/apiHandlers/getPullRequestDetails.js +120 -0
  44. package/apiHandlers/index.d.ts +1 -0
  45. package/apiHandlers/index.js +1 -0
  46. package/apiHandlers/package.json +6 -0
  47. package/index.d.ts +3 -0
  48. package/index.js +10 -0
  49. package/modern/GithubCalendar/GithubCalendar.js +330 -0
  50. package/modern/GithubCalendar/index.js +2 -0
  51. package/modern/GithubEvents/EventTypes/CreateEvent.js +72 -0
  52. package/modern/GithubEvents/EventTypes/DeleteEvent.js +65 -0
  53. package/modern/GithubEvents/EventTypes/ForkEvent.js +77 -0
  54. package/modern/GithubEvents/EventTypes/IssueCommentEvent.js +210 -0
  55. package/modern/GithubEvents/EventTypes/IssuesEvent.js +97 -0
  56. package/modern/GithubEvents/EventTypes/ProjectsV2ColumnEvent.js +69 -0
  57. package/modern/GithubEvents/EventTypes/ProjectsV2Event.js +74 -0
  58. package/modern/GithubEvents/EventTypes/ProjectsV2FieldEvent.js +77 -0
  59. package/modern/GithubEvents/EventTypes/ProjectsV2ItemEvent.js +79 -0
  60. package/modern/GithubEvents/EventTypes/PullRequest/CommitsList.js +99 -0
  61. package/modern/GithubEvents/EventTypes/PullRequest/FileChanges.js +182 -0
  62. package/modern/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +374 -0
  63. package/modern/GithubEvents/EventTypes/PullRequest/PullRequestView.js +132 -0
  64. package/modern/GithubEvents/EventTypes/PushEvent.js +106 -0
  65. package/modern/GithubEvents/GithubEvents.js +1454 -0
  66. package/modern/GithubEvents/index.js +2 -0
  67. package/modern/apiHandlers/getPullRequestDetails.js +120 -0
  68. package/modern/apiHandlers/index.js +1 -0
  69. package/modern/index.js +10 -0
  70. package/modern/types/github.js +1 -0
  71. package/node/GithubCalendar/GithubCalendar.js +337 -0
  72. package/node/GithubCalendar/index.js +9 -0
  73. package/node/GithubEvents/EventTypes/CreateEvent.js +80 -0
  74. package/node/GithubEvents/EventTypes/DeleteEvent.js +73 -0
  75. package/node/GithubEvents/EventTypes/ForkEvent.js +85 -0
  76. package/node/GithubEvents/EventTypes/IssueCommentEvent.js +218 -0
  77. package/node/GithubEvents/EventTypes/IssuesEvent.js +105 -0
  78. package/node/GithubEvents/EventTypes/ProjectsV2ColumnEvent.js +77 -0
  79. package/node/GithubEvents/EventTypes/ProjectsV2Event.js +82 -0
  80. package/node/GithubEvents/EventTypes/ProjectsV2FieldEvent.js +85 -0
  81. package/node/GithubEvents/EventTypes/ProjectsV2ItemEvent.js +87 -0
  82. package/node/GithubEvents/EventTypes/PullRequest/CommitsList.js +107 -0
  83. package/node/GithubEvents/EventTypes/PullRequest/FileChanges.js +188 -0
  84. package/node/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +381 -0
  85. package/node/GithubEvents/EventTypes/PullRequest/PullRequestView.js +138 -0
  86. package/node/GithubEvents/EventTypes/PushEvent.js +114 -0
  87. package/node/GithubEvents/GithubEvents.js +1463 -0
  88. package/node/GithubEvents/index.js +9 -0
  89. package/node/apiHandlers/getPullRequestDetails.js +127 -0
  90. package/node/apiHandlers/index.js +13 -0
  91. package/node/index.js +27 -0
  92. package/node/types/github.js +5 -0
  93. package/package.json +71 -0
  94. package/types/github.d.ts +107 -0
  95. package/types/github.js +1 -0
@@ -0,0 +1,1454 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ var _div, _Chip, _SmalMi, _SmalMi2, _SmalMi3, _SmalMi4, _SmalMi5, _TableRow, _TableRow2;
3
+ import * as React from 'react';
4
+ import { RequestError } from '@octokit/request-error';
5
+ import Box from "@mui/material/Box";
6
+ import TextField from "@mui/material/TextField";
7
+ import Table from "@mui/material/Table";
8
+ import TableBody from "@mui/material/TableBody";
9
+ import TableCell from "@mui/material/TableCell";
10
+ import TableContainer from "@mui/material/TableContainer";
11
+ import TableHead from "@mui/material/TableHead";
12
+ import TableRow from "@mui/material/TableRow";
13
+ import Paper from "@mui/material/Paper";
14
+ import Typography from "@mui/material/Typography";
15
+ import CircularProgress from "@mui/material/CircularProgress";
16
+ import Select from '@mui/material/Select';
17
+ import MenuItem from '@mui/material/MenuItem';
18
+ import FormControl from '@mui/material/FormControl';
19
+ import { format, parse, parseISO } from 'date-fns';
20
+ import { toZonedTime } from 'date-fns-tz';
21
+ import { styled, useTheme } from '@mui/material/styles';
22
+ import Autocomplete from '@mui/material/Autocomplete';
23
+ import Pagination from '@mui/material/Pagination';
24
+ import dynamic from 'next/dynamic';
25
+ import PullRequestEvent from './EventTypes/PullRequest/PullRequestEvent';
26
+ import PushEvent from './EventTypes/PushEvent';
27
+ import DeleteEvent from './EventTypes/DeleteEvent';
28
+ import CreateEvent from './EventTypes/CreateEvent';
29
+ import IssuesEvent from './EventTypes/IssuesEvent';
30
+ import IssueCommentEvent from './EventTypes/IssueCommentEvent';
31
+ import Chip from '@mui/material/Chip';
32
+ // Extend the EventDetails interface for internal component use
33
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
34
+ // Import react-json-view dynamically to avoid SSR issues
35
+ const ReactJson = dynamic(() => import('react-json-view'), {
36
+ ssr: false,
37
+ loading: () => _div || (_div = /*#__PURE__*/_jsx("div", {
38
+ children: "Loading JSON viewer..."
39
+ }))
40
+ });
41
+ const MetadataDisplay = styled(Box)(({
42
+ theme
43
+ }) => {
44
+ return {
45
+ backgroundColor: 'rgba(255, 255, 255, 0.06)',
46
+ borderRadius: theme.shape.borderRadius,
47
+ boxShadow: theme.shadows[2],
48
+ padding: theme.spacing(2),
49
+ position: 'sticky',
50
+ width: '672px',
51
+ maxWidth: '692px',
52
+ minWidth: '300px',
53
+ top: '84px',
54
+ maxHeight: 'calc(100vh - 100px)',
55
+ overflow: 'auto'
56
+ };
57
+ });
58
+ function parseLinkHeader(header) {
59
+ if (!header) return {};
60
+ return header.split(',').reduce((links, part) => {
61
+ const match = part.match(/<(.+)>;\s*rel="([\w]+)"/);
62
+ if (match) {
63
+ const [, url, rel] = match;
64
+ if (rel === 'next' || rel === 'last') {
65
+ links[rel] = url;
66
+ }
67
+ }
68
+ return links;
69
+ }, {});
70
+ }
71
+ export async function githubEventsQuery({
72
+ query,
73
+ githubUser,
74
+ githubToken
75
+ }) {
76
+ try {
77
+ const {
78
+ page = query.page || 1,
79
+ per_page = query.per_page || 100,
80
+ // Default to 100 per page to minimize API calls
81
+ repo,
82
+ action,
83
+ date,
84
+ description
85
+ } = query;
86
+ const queryParams = new URLSearchParams(_extends({
87
+ page: String(page),
88
+ per_page: String(per_page)
89
+ }, repo && {
90
+ repo
91
+ }, action && {
92
+ action
93
+ }, date && {
94
+ date
95
+ }, description && {
96
+ description
97
+ }));
98
+
99
+ // Get GitHub token from environment variables
100
+ console.log(`Fetching events for user: ${githubUser}, page: ${page}, per_page: ${per_page}`);
101
+
102
+ // Fetch all available pages from GitHub API
103
+ let allEvents = [];
104
+ let hasMore = true;
105
+ let githubPage = 1;
106
+ const maxPages = 30; // GitHub's maximum for events endpoint
107
+
108
+ while (hasMore && githubPage <= maxPages) {
109
+ console.log(`Fetching page ${githubPage}...`);
110
+ const fetchOptions = {
111
+ headers: {
112
+ 'User-Agent': 'brianstoker.com-website'
113
+ }
114
+ };
115
+ if (githubToken) {
116
+ fetchOptions.headers.Authorization = `token ${githubToken}`;
117
+ }
118
+ const response = await fetch(`https://api.github.com/users/${githubUser}/events?${queryParams}`, fetchOptions);
119
+ if (!response.ok) {
120
+ const errorText = await response.text();
121
+ console.error(`GitHub API error: ${response.status}`, errorText);
122
+ throw new Error(`GitHub API error: ${response.status} - ${errorText}`);
123
+ }
124
+ const data = await response.json();
125
+ console.log(`Page ${githubPage}: Received ${data.length} events`);
126
+ if (data.length === 0) {
127
+ hasMore = false;
128
+ } else {
129
+ allEvents = [...allEvents, ...data];
130
+ console.log(`Total events so far: ${allEvents.length}`);
131
+
132
+ // Check Link header to see if there are more pages
133
+ const linkHeader = response.headers.get('Link');
134
+ const links = parseLinkHeader(linkHeader);
135
+ hasMore = !!links.next; // Simplified logic
136
+
137
+ githubPage++;
138
+ }
139
+ }
140
+ console.log(`Final total events: ${allEvents.length}`);
141
+
142
+ // Apply filters
143
+ let filteredEvents = allEvents;
144
+ if (repo) {
145
+ filteredEvents = filteredEvents.filter(event => event.repo.name === repo);
146
+ }
147
+ if (action) {
148
+ filteredEvents = filteredEvents.filter(event => {
149
+ const eventAction = event.type.replace('Event', '');
150
+ return eventAction === action;
151
+ });
152
+ }
153
+ if (date) {
154
+ const now = new Date();
155
+ let cutoffDate;
156
+ switch (date) {
157
+ case 'today':
158
+ cutoffDate = new Date(now.setHours(0, 0, 0, 0));
159
+ break;
160
+ case 'yesterday':
161
+ cutoffDate = new Date(now);
162
+ cutoffDate.setDate(cutoffDate.getDate() - 1);
163
+ cutoffDate.setHours(0, 0, 0, 0);
164
+ break;
165
+ case 'week':
166
+ cutoffDate = new Date(now);
167
+ cutoffDate.setDate(cutoffDate.getDate() - 7);
168
+ cutoffDate.setHours(0, 0, 0, 0);
169
+ break;
170
+ case 'month':
171
+ cutoffDate = new Date(now);
172
+ cutoffDate.setMonth(cutoffDate.getMonth() - 1);
173
+ cutoffDate.setHours(0, 0, 0, 0);
174
+ break;
175
+ default:
176
+ cutoffDate = new Date(0);
177
+ }
178
+ filteredEvents = filteredEvents.filter(event => {
179
+ const eventDate = new Date(event.created_at);
180
+ return eventDate >= cutoffDate;
181
+ });
182
+ }
183
+ if (description) {
184
+ filteredEvents = filteredEvents.filter(event => {
185
+ var _event$payload$commit, _event$payload$pull_r, _event$payload$issue, _event$payload$issue2;
186
+ let eventDescription = '';
187
+ if (event.type === 'PushEvent' && (_event$payload$commit = event.payload.commits) != null && _event$payload$commit.length) {
188
+ eventDescription = `Pushed ${event.payload.commits.length} commits`;
189
+ } else if (event.type === 'PullRequestEvent' && (_event$payload$pull_r = event.payload.pull_request) != null && _event$payload$pull_r.title) {
190
+ eventDescription = event.payload.pull_request.title;
191
+ } else if (event.type === 'IssuesEvent' && (_event$payload$issue = event.payload.issue) != null && _event$payload$issue.title) {
192
+ eventDescription = event.payload.issue.title;
193
+ } else if (event.type === 'IssueCommentEvent' && (_event$payload$issue2 = event.payload.issue) != null && _event$payload$issue2.title) {
194
+ eventDescription = `Commented on issue: ${event.payload.issue.title}`;
195
+ }
196
+ return eventDescription.toLowerCase().includes(description.toLowerCase());
197
+ });
198
+ }
199
+
200
+ // Calculate pagination
201
+ const pageNum = Number(page);
202
+ const perPage = Number(per_page);
203
+ const startIndex = (pageNum - 1) * perPage;
204
+ const endIndex = startIndex + perPage;
205
+ const paginatedEvents = filteredEvents.slice(startIndex, endIndex);
206
+
207
+ // Extract unique values for filters (only on first page)
208
+ const repositories = [...new Set(allEvents.map(event => event.repo.name))].sort();
209
+ const actionTypes = [...new Set(allEvents.map(event => event.type.replace('Event', '')))].sort();
210
+
211
+ // Return paginated results with metadata
212
+ return {
213
+ events: paginatedEvents,
214
+ total: filteredEvents.length,
215
+ repositories,
216
+ actionTypes,
217
+ page: pageNum,
218
+ per_page: perPage,
219
+ total_pages: Math.ceil(filteredEvents.length / perPage),
220
+ total_fetched_events: allEvents.length,
221
+ max_pages_fetched: githubPage - 1
222
+ };
223
+ } catch (error) {
224
+ console.error('Error fetching GitHub events:', error);
225
+ throw new Error(`${error instanceof Error ? error.message : String(error)}`);
226
+ }
227
+ }
228
+ async function getEvents({
229
+ githubUser,
230
+ githubToken,
231
+ apiUrl = undefined,
232
+ query
233
+ }) {
234
+ const {
235
+ page,
236
+ perPage,
237
+ repo,
238
+ action,
239
+ description,
240
+ date
241
+ } = query;
242
+ console.log(`getEvents called - page: ${page}, perPage: ${perPage}`);
243
+ const queryParams = new URLSearchParams(_extends({
244
+ page: page.toString(),
245
+ per_page: perPage.toString()
246
+ }, repo && {
247
+ repo
248
+ }, action && {
249
+ action
250
+ }, date && {
251
+ date
252
+ }, description && {
253
+ description
254
+ }));
255
+ if (apiUrl) {
256
+ const url = apiUrl;
257
+ console.log(`Fetching from custom API URL: ${url}?${queryParams}`);
258
+ const response = await fetch(`${url}?${queryParams}`);
259
+ return response.json();
260
+ }
261
+ return githubEventsQuery({
262
+ query: {
263
+ page,
264
+ per_page: perPage,
265
+ repo,
266
+ action,
267
+ date,
268
+ description
269
+ },
270
+ githubUser,
271
+ githubToken
272
+ });
273
+ }
274
+ export function ErrorDetails({
275
+ error
276
+ }) {
277
+ const date = format(new Date(), 'MMM d, yyyy h:mm a');
278
+ const [errorDetails, setErrorDetails] = React.useState({
279
+ type: 'Error: Unknown Error',
280
+ message: 'Sorry but your princess is in another castle',
281
+ status: undefined
282
+ });
283
+ React.useEffect(() => {
284
+ if (error instanceof RequestError) {
285
+ var _error$response;
286
+ console.log('request error', error);
287
+ setErrorDetails({
288
+ type: 'Error: Request Error',
289
+ message: error.message,
290
+ status: (_error$response = error.response) == null ? void 0 : _error$response.status // Add optional chaining
291
+ });
292
+ } else if (typeof error === 'string') {
293
+ // Handle string errors
294
+ setErrorDetails({
295
+ type: 'Error',
296
+ message: error
297
+ });
298
+ } else {
299
+ // Fallback
300
+ setErrorDetails({
301
+ type: 'Unknown Error',
302
+ message: 'An unknown error occurred'
303
+ });
304
+ }
305
+ }, [error]);
306
+ return /*#__PURE__*/_jsxs(Box, {
307
+ sx: {
308
+ p: '8px',
309
+ display: 'content'
310
+ },
311
+ children: [/*#__PURE__*/_jsxs(Box, {
312
+ sx: {
313
+ display: 'flex',
314
+ alignItems: 'center',
315
+ gap: '16px'
316
+ },
317
+ children: [/*#__PURE__*/_jsx(Typography, {
318
+ variant: "caption",
319
+ color: "text.secondary",
320
+ children: date
321
+ }), _Chip || (_Chip = /*#__PURE__*/_jsx(Chip, {
322
+ label: 'Error',
323
+ size: "small",
324
+ color: "error"
325
+ }))]
326
+ }), /*#__PURE__*/_jsxs(Typography, {
327
+ variant: "h6",
328
+ component: "h3",
329
+ sx: {
330
+ mb: 1
331
+ },
332
+ children: [errorDetails.type, " ", errorDetails.status ? `(${errorDetails.status})` : '']
333
+ }), /*#__PURE__*/_jsx(Box, {
334
+ sx: {
335
+ alignItems: 'center'
336
+ },
337
+ children: /*#__PURE__*/_jsx(Typography, {
338
+ variant: "body2",
339
+ color: "text.secondary",
340
+ children: errorDetails.message
341
+ })
342
+ })]
343
+ });
344
+ }
345
+ const SmalMi = styled(MenuItem)({
346
+ fontSize: '12px'
347
+ });
348
+ export default function GithubEvents({
349
+ apiUrl,
350
+ eventsPerPage = 40,
351
+ hideMetadata = false,
352
+ githubUser,
353
+ githubToken
354
+ }) {
355
+ const [events, setEvents] = React.useState([]);
356
+ const [loading, setLoading] = React.useState(true);
357
+ const [error, setError] = React.useState(null);
358
+ const [repoFilter, setRepoFilter] = React.useState('');
359
+ const [actionFilter, setActionFilter] = React.useState('');
360
+ const [repositories, setRepositories] = React.useState([]);
361
+ const [actionTypes, setActionTypes] = React.useState([]);
362
+ const [dateFilter, setDateFilter] = React.useState('');
363
+ // @ts-ignore -- setter kept for future use
364
+ const [descriptionFilter, _setDescriptionFilter] = React.useState('');
365
+ // @ts-ignore -- state kept for future use
366
+ const [_descriptions, setDescriptions] = React.useState([]);
367
+ const [page, setPage] = React.useState(1);
368
+ const [totalCount, setTotalCount] = React.useState(0);
369
+ const [cachedEvents, setCachedEvents] = React.useState([]);
370
+ const [lastUpdated, setLastUpdated] = React.useState('');
371
+ const [selectedEvent, selectEvent] = React.useState({
372
+ id: ''
373
+ });
374
+ const theme = useTheme();
375
+ const scrollRef = React.useRef(null);
376
+ // @ts-ignore -- state kept for future use
377
+ const [_showAttached, setShowAttached] = React.useState(false);
378
+ // @ts-ignore -- state kept for future use
379
+ const [_scrollTop, setScrollTop] = React.useState(0);
380
+ const initializedRef = React.useRef(false);
381
+ const isFilterChangeRef = React.useRef(false);
382
+ const isPageChangeRef = React.useRef(false);
383
+
384
+ // Create a more specific cache key with consistent format
385
+ const cacheKey = React.useMemo(() => `github_events_${githubUser.toLowerCase()}`, [githubUser]);
386
+
387
+ // Add a ref to track if we've fetched from API in this session
388
+ const fetchedThisSessionRef = React.useRef(false);
389
+
390
+ // Debug function to clear cache (for development)
391
+ // const clearCache = () => {
392
+ // console.log(`Clearing cache for ${cacheKey}`);
393
+ // localStorage.removeItem(cacheKey);
394
+ // setCachedEvents([]);
395
+ // setEvents([]);
396
+ // fetchedThisSessionRef.current = false;
397
+ // initializedRef.current = false;
398
+ // };
399
+
400
+ React.useEffect(() => {
401
+ const el = scrollRef.current;
402
+ if (!el) return;
403
+ const onScroll = () => {
404
+ setScrollTop(el.scrollTop);
405
+ setShowAttached(true);
406
+ console.log(el.scrollTop);
407
+
408
+ // Hide after 1s of inactivity
409
+ clearTimeout(onScroll.hideTimeout);
410
+ onScroll.hideTimeout = setTimeout(() => {
411
+ setShowAttached(false);
412
+ }, 1000);
413
+ };
414
+ el.addEventListener('scroll', onScroll);
415
+ return () => el.removeEventListener('scroll', onScroll);
416
+ }, []);
417
+ const buildFilterOptionsFromEvents = events => {
418
+ const uniqueRepos = new Set();
419
+ const uniqueActions = new Set();
420
+ const uniqueDescriptions = new Set();
421
+ events.forEach(event => {
422
+ uniqueRepos.add(event.repo.name);
423
+ uniqueActions.add(event.type.replace('Event', ''));
424
+ if (event.payload) {
425
+ var _event$payload$commit2, _event$payload$pull_r2, _event$payload$issue3, _event$payload$issue4;
426
+ if (event.type === 'PushEvent' && (_event$payload$commit2 = event.payload.commits) != null && _event$payload$commit2.length) {
427
+ uniqueDescriptions.add(`Pushed ${event.payload.commits.length} commits`);
428
+ } else if (event.type === 'PullRequestEvent' && (_event$payload$pull_r2 = event.payload.pull_request) != null && _event$payload$pull_r2.title) {
429
+ uniqueDescriptions.add(event.payload.pull_request.title);
430
+ } else if (event.type === 'IssuesEvent' && (_event$payload$issue3 = event.payload.issue) != null && _event$payload$issue3.title) {
431
+ uniqueDescriptions.add(event.payload.issue.title);
432
+ } else if (event.type === 'IssueCommentEvent' && (_event$payload$issue4 = event.payload.issue) != null && _event$payload$issue4.title) {
433
+ uniqueDescriptions.add(`Commented on issue: ${event.payload.issue.title}`);
434
+ }
435
+ }
436
+ });
437
+ setRepositories(Array.from(uniqueRepos).sort());
438
+ setActionTypes(Array.from(uniqueActions).sort());
439
+ setDescriptions(Array.from(uniqueDescriptions).sort());
440
+ };
441
+ const processEvents = rawEvents => {
442
+ console.log('Processing events, count:', rawEvents.length);
443
+ if (rawEvents.length === 0) {
444
+ console.log('No events to process');
445
+ return [];
446
+ }
447
+ try {
448
+ // Log sample event to debug format
449
+ if (rawEvents.length > 0) {
450
+ console.log('Sample raw event to process:', JSON.stringify(rawEvents[0]).substring(0, 500) + '...');
451
+ }
452
+ return rawEvents.map((event, index) => {
453
+ var _event$payload$commit3;
454
+ try {
455
+ var _event$repo2;
456
+ if (!event) {
457
+ console.error(`Event at index ${index} is undefined`);
458
+ return null;
459
+ }
460
+ if (!event.created_at) {
461
+ console.error(`Event at index ${index} missing created_at:`, event);
462
+ return null;
463
+ }
464
+ const dateTime = toZonedTime(parseISO(event.created_at), 'America/Chicago');
465
+ const date = format(dateTime, 'MM-dd-yyyy');
466
+ const formattedDate = format(dateTime, 'MMM d, yyyy h:mm a');
467
+ let action = '';
468
+ let description = '';
469
+ let link = '';
470
+ let id = event.id;
471
+ try {
472
+ switch (event.type) {
473
+ case 'PushEvent':
474
+ action = 'Push';
475
+ description = `Pushed ${((_event$payload$commit3 = event.payload.commits) == null ? void 0 : _event$payload$commit3.length) || 0} commits`;
476
+ link = `https://github.com/${event.repo.name}/commit/${event.payload.head}`;
477
+ break;
478
+ case 'PullRequestEvent':
479
+ action = 'Pull Request';
480
+ description = event.payload.pull_request.title;
481
+ link = event.payload.pull_request.html_url;
482
+ break;
483
+ case 'IssuesEvent':
484
+ action = 'Issue';
485
+ description = event.payload.issue.title;
486
+ link = event.payload.issue.html_url;
487
+ break;
488
+ case 'IssueCommentEvent':
489
+ action = 'Comment';
490
+ description = `Commented on issue: ${event.payload.issue.title}`;
491
+ link = event.payload.comment.html_url;
492
+ break;
493
+ default:
494
+ action = event.type.replace('Event', '');
495
+ description = '';
496
+ link = `https://github.com/${event.repo.name}`;
497
+ }
498
+ } catch (err) {
499
+ var _event$type, _event$repo;
500
+ console.error(`Error processing event type ${event.type} at index ${index}:`, err);
501
+ action = ((_event$type = event.type) == null ? void 0 : _event$type.replace('Event', '')) || 'Unknown';
502
+ description = 'Error processing event details';
503
+ link = (_event$repo = event.repo) != null && _event$repo.name ? `https://github.com/${event.repo.name}` : '';
504
+ }
505
+ const eventDetails = {
506
+ id: id || `event-${index}`,
507
+ date: formattedDate,
508
+ dateOnly: date,
509
+ repo: ((_event$repo2 = event.repo) == null ? void 0 : _event$repo2.name) || 'unknown-repo',
510
+ action,
511
+ actionType: event.type || 'UnknownEvent',
512
+ description,
513
+ url: link,
514
+ state: 'open',
515
+ user: '',
516
+ avatarUrl: '',
517
+ number: 0,
518
+ merged: false,
519
+ comments: 0,
520
+ commits: 0,
521
+ ref: '',
522
+ commitsList: [],
523
+ payload: event.payload
524
+ };
525
+ return eventDetails;
526
+ } catch (err) {
527
+ console.error(`Error processing event at index ${index}:`, err, event);
528
+ // Return a placeholder event to avoid breaking the UI
529
+ return {
530
+ id: `error-${index}`,
531
+ date: format(new Date(), 'MMM d, yyyy h:mm a'),
532
+ dateOnly: format(new Date(), 'MM-dd-yyyy'),
533
+ repo: 'Error processing event',
534
+ action: 'Error',
535
+ actionType: 'ErrorEvent',
536
+ description: err instanceof Error ? err.message : 'Unknown error',
537
+ url: '',
538
+ state: 'open',
539
+ user: '',
540
+ avatarUrl: '',
541
+ number: 0,
542
+ merged: false,
543
+ comments: 0,
544
+ commits: 0,
545
+ ref: '',
546
+ commitsList: [],
547
+ payload: {}
548
+ };
549
+ }
550
+ }).filter(Boolean); // Filter out any null values
551
+ } catch (err) {
552
+ console.error('Fatal error in processEvents:', err);
553
+ return [];
554
+ }
555
+ };
556
+ const filterEvents = events => {
557
+ return events.filter(event => {
558
+ const matchesRepo = !repoFilter || event.repo.name === repoFilter;
559
+ const matchesAction = !actionFilter || event.type.replace('Event', '') === actionFilter;
560
+ let matchesDescription = true;
561
+ if (descriptionFilter) {
562
+ const eventDescription = getEventDescription(event);
563
+ matchesDescription = eventDescription.includes(descriptionFilter);
564
+ }
565
+ if (dateFilter) {
566
+ const filterDate = getFilteredDate(dateFilter);
567
+ if (filterDate) {
568
+ const eventDate = new Date(event.created_at);
569
+ if (eventDate < filterDate) return false;
570
+ }
571
+ }
572
+ return matchesRepo && matchesAction && matchesDescription;
573
+ });
574
+ };
575
+ const getEventDescription = event => {
576
+ if (event.type === 'PushEvent') {
577
+ var _event$payload$commit4;
578
+ return `Pushed ${((_event$payload$commit4 = event.payload.commits) == null ? void 0 : _event$payload$commit4.length) || 0} commits`;
579
+ } else if (event.type === 'PullRequestEvent') {
580
+ return event.payload.pull_request.title;
581
+ } else if (event.type === 'IssuesEvent') {
582
+ return event.payload.issue.title;
583
+ } else if (event.type === 'IssueCommentEvent') {
584
+ return `Commented on issue: ${event.payload.issue.title}`;
585
+ }
586
+ return '';
587
+ };
588
+
589
+ // Filter events based on date
590
+ const getFilteredDate = filter => {
591
+ const now = new Date();
592
+ switch (filter) {
593
+ case 'today':
594
+ return new Date(now.setHours(0, 0, 0, 0));
595
+ case 'yesterday':
596
+ {
597
+ const yesterday = new Date(now);
598
+ yesterday.setDate(yesterday.getDate() - 1);
599
+ return yesterday;
600
+ }
601
+ case 'week':
602
+ {
603
+ const weekAgo = new Date(now);
604
+ weekAgo.setDate(weekAgo.getDate() - 7);
605
+ return weekAgo;
606
+ }
607
+ default:
608
+ return null;
609
+ }
610
+ };
611
+ const fetchAllGitHubEvents = async () => {
612
+ // Skip if we've already fetched this session
613
+ if (fetchedThisSessionRef.current) {
614
+ console.log('Already fetched events this session, using cached data');
615
+ return;
616
+ }
617
+ setLoading(true);
618
+ setError(null);
619
+ try {
620
+ console.log('Fetching ALL GitHub events (all pages)');
621
+ const allEvents = [];
622
+ let hasMore = true;
623
+ let pageNum = 1;
624
+ const maxPages = 10; // GitHub API typically limits to 10 pages max
625
+
626
+ while (hasMore && pageNum <= maxPages) {
627
+ console.log(`Fetching page ${pageNum} of GitHub events (100 per page)`);
628
+ const queryParams = _extends({
629
+ page: pageNum,
630
+ perPage: 100
631
+ }, repoFilter && {
632
+ repo: repoFilter
633
+ }, actionFilter && {
634
+ action: actionFilter
635
+ }, dateFilter && {
636
+ date: dateFilter
637
+ }, descriptionFilter && {
638
+ description: descriptionFilter
639
+ });
640
+ try {
641
+ console.log(`API call for page ${pageNum}`);
642
+ const data = await getEvents({
643
+ query: queryParams,
644
+ apiUrl,
645
+ githubUser,
646
+ githubToken
647
+ });
648
+ if (data.events && data.events.length > 0) {
649
+ console.log(`Received ${data.events.length} events for page ${pageNum}`);
650
+ allEvents.push(...data.events);
651
+ pageNum++;
652
+ console.log(`Total events so far: ${allEvents.length}`);
653
+
654
+ // Check if we've reached the end
655
+ if (data.events.length < 100) {
656
+ hasMore = false;
657
+ console.log('Received less than 100 events, reached the end');
658
+ }
659
+ } else {
660
+ hasMore = false;
661
+ console.log('Received 0 events, reached the end');
662
+ }
663
+ } catch (err) {
664
+ console.error(`Error fetching page ${pageNum}:`, err);
665
+ // Break the loop on error but don't fail the whole operation
666
+ hasMore = false;
667
+ }
668
+ }
669
+ console.log(`Fetched a total of ${allEvents.length} events from ${pageNum - 1} pages`);
670
+ if (allEvents.length > 0) {
671
+ // Save all events to cache with user-specific key
672
+ setCachedEvents(allEvents);
673
+ localStorage.setItem(cacheKey, JSON.stringify({
674
+ events: allEvents,
675
+ lastFetched: Date.now(),
676
+ totalCount: allEvents.length
677
+ }));
678
+
679
+ // Mark that we've fetched this session
680
+ sessionStorage.setItem(`${cacheKey}_session_fetched`, 'true');
681
+ fetchedThisSessionRef.current = true;
682
+
683
+ // Update filter options with all data
684
+ buildFilterOptionsFromEvents(allEvents);
685
+
686
+ // Display first page
687
+ const filteredEvents = filterEvents(allEvents);
688
+ setTotalCount(filteredEvents.length);
689
+ const paginatedEvents = filteredEvents.slice(0, eventsPerPage);
690
+ const processedEvents = processEvents(paginatedEvents);
691
+ setEvents(processedEvents);
692
+
693
+ // Select the most recent event by default
694
+ if (processedEvents.length > 0) {
695
+ selectEvent(processedEvents[0]);
696
+ setTimeout(() => {
697
+ const firstRow = document.getElementById(processedEvents[0].id);
698
+ if (firstRow) {
699
+ firstRow.classList.add('selected');
700
+ }
701
+ }, 0);
702
+ }
703
+ } else {
704
+ console.log('No events found, setting empty state');
705
+ setEvents([]);
706
+ setTotalCount(0);
707
+ }
708
+ } catch (err) {
709
+ console.error('Error in fetchAllGitHubEvents:', err);
710
+ if (err instanceof RequestError) {
711
+ setError(err);
712
+ } else if (err instanceof Error) {
713
+ setError(err.message);
714
+ } else {
715
+ setError(String(err));
716
+ }
717
+ setEvents([]);
718
+ setTotalCount(0);
719
+ } finally {
720
+ setLoading(false);
721
+ }
722
+ };
723
+ const fetchNewEvents = async () => {
724
+ // Skip if we've already fetched this session
725
+ if (fetchedThisSessionRef.current) {
726
+ console.log('Already fetched events this session, using cached data');
727
+ return;
728
+ }
729
+ setLoading(true);
730
+ try {
731
+ // First, get the most recent event date from our cache
732
+ let mostRecentDate = new Date(0);
733
+ if (cachedEvents.length > 0) {
734
+ mostRecentDate = new Date(Math.max(...cachedEvents.map(e => new Date(e.created_at).getTime())));
735
+ }
736
+ console.log('Fetching new events since', format(mostRecentDate, 'MMM d, yyyy h:mm a'));
737
+
738
+ // Fetch all new events
739
+ let allNewEvents = [];
740
+ let hasMore = true;
741
+ let pageNum = 1;
742
+ const maxPages = 10; // GitHub API typically limits to 10 pages max
743
+
744
+ while (hasMore && pageNum <= maxPages) {
745
+ const query = {
746
+ page: pageNum,
747
+ perPage: 100 // Maximum allowed by GitHub API
748
+ };
749
+ console.log(`Fetching page ${pageNum} of new events (100 per page)`);
750
+ try {
751
+ const data = await getEvents({
752
+ apiUrl,
753
+ githubUser,
754
+ githubToken,
755
+ query
756
+ });
757
+ if (data.events && data.events.length > 0) {
758
+ // Check if we've reached events we already have
759
+ const allOldEvents = data.events.every(event => {
760
+ const eventDate = new Date(event.created_at);
761
+ return eventDate <= mostRecentDate;
762
+ });
763
+ if (allOldEvents) {
764
+ console.log('All events on this page are already in cache, stopping fetch');
765
+ hasMore = false;
766
+ } else {
767
+ // Filter out events older than our most recent cached event
768
+ const newEvents = data.events.filter(event => {
769
+ const eventDate = new Date(event.created_at);
770
+ return eventDate > mostRecentDate;
771
+ });
772
+ allNewEvents.push(...newEvents);
773
+ console.log(`Found ${newEvents.length} new events on page ${pageNum}`);
774
+ if (data.events.length < 100) {
775
+ console.log('Received less than 100 events, reached the end');
776
+ hasMore = false;
777
+ }
778
+ pageNum++;
779
+ }
780
+ } else {
781
+ hasMore = false;
782
+ console.log('Received 0 events, reached the end');
783
+ }
784
+ } catch (err) {
785
+ console.error(`Error fetching page ${pageNum} in fetchNewEvents:`, err);
786
+ hasMore = false; // Stop on error but continue processing what we've got
787
+ }
788
+ }
789
+ if (allNewEvents.length > 0) {
790
+ console.log(`Fetched ${allNewEvents.length} new events`);
791
+
792
+ // Combine with existing events and sort by date (newest first)
793
+ const updatedEvents = [...allNewEvents, ...cachedEvents];
794
+ updatedEvents.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
795
+
796
+ // Mark that we've fetched this session
797
+ sessionStorage.setItem(`${cacheKey}_session_fetched`, 'true');
798
+ fetchedThisSessionRef.current = true;
799
+
800
+ // Update cache with new events using user-specific key
801
+ setCachedEvents(updatedEvents);
802
+ localStorage.setItem(cacheKey, JSON.stringify({
803
+ events: updatedEvents,
804
+ lastFetched: Date.now(),
805
+ totalCount: updatedEvents.length
806
+ }));
807
+
808
+ // Update UI
809
+ buildFilterOptionsFromEvents(updatedEvents);
810
+
811
+ // Display first page with updated data
812
+ const filteredEvents = filterEvents(updatedEvents);
813
+ setTotalCount(filteredEvents.length);
814
+ const paginatedEvents = filteredEvents.slice(0, eventsPerPage);
815
+ const processedEvents = processEvents(paginatedEvents);
816
+ setEvents(processedEvents);
817
+ setLastUpdated(format(new Date(), 'MMM d, yyyy h:mm a'));
818
+ console.log('Updated display with new events');
819
+ } else {
820
+ console.log('No new events found');
821
+
822
+ // Mark that we've fetched this session even if no new events
823
+ sessionStorage.setItem(`${cacheKey}_session_fetched`, 'true');
824
+ fetchedThisSessionRef.current = true;
825
+
826
+ // Just update the last fetched time with user-specific key
827
+ const currentCache = JSON.parse(localStorage.getItem(cacheKey) || '{}');
828
+ localStorage.setItem(cacheKey, JSON.stringify(_extends({}, currentCache, {
829
+ lastFetched: Date.now()
830
+ })));
831
+ setLastUpdated(format(new Date(), 'MMM d, yyyy h:mm a'));
832
+
833
+ // Use existing cached data for display
834
+ const filteredEvents = filterEvents(cachedEvents);
835
+ const paginatedEvents = filteredEvents.slice(0, eventsPerPage);
836
+ const processedEvents = processEvents(paginatedEvents);
837
+ console.log('Using existing events for display, count:', processedEvents.length);
838
+ setEvents(processedEvents);
839
+ }
840
+ } catch (err) {
841
+ console.error('Failed to fetch new events:', err);
842
+ if (err instanceof RequestError) {
843
+ setError(err);
844
+ } else if (err instanceof Error) {
845
+ setError(err.message);
846
+ } else {
847
+ setError(String(err));
848
+ }
849
+
850
+ // Use existing cached data for display if available
851
+ if (cachedEvents.length > 0) {
852
+ console.log('Using existing cached data after error');
853
+ const filteredEvents = filterEvents(cachedEvents);
854
+ const paginatedEvents = filteredEvents.slice(0, eventsPerPage);
855
+ const processedEvents = processEvents(paginatedEvents);
856
+ setEvents(processedEvents);
857
+ }
858
+ } finally {
859
+ setLoading(false);
860
+ }
861
+ };
862
+ const fetchGitHubEvents = async (pageNum = 1, isFilterChange = false) => {
863
+ // Always use cached data for pagination and filtering
864
+ if (cachedEvents.length > 0) {
865
+ console.log(`Using ${cachedEvents.length} cached events for pagination/filtering (page ${pageNum})`);
866
+ setLoading(true);
867
+ try {
868
+ const filteredCachedEvents = filterEvents(cachedEvents);
869
+ console.log('Filtered cached events:', filteredCachedEvents.length);
870
+ const startIndex = (pageNum - 1) * eventsPerPage;
871
+ const endIndex = startIndex + eventsPerPage;
872
+ const paginatedEvents = filteredCachedEvents.slice(startIndex, endIndex);
873
+ console.log(`Showing events ${startIndex + 1}-${Math.min(endIndex, filteredCachedEvents.length)} of ${filteredCachedEvents.length}`);
874
+ const processedEvents = processEvents(paginatedEvents);
875
+ console.log('Processed events count:', processedEvents.length);
876
+ setEvents(processedEvents);
877
+ setTotalCount(filteredCachedEvents.length);
878
+
879
+ // Select the most recent event by default if none selected
880
+ if (processedEvents.length > 0 && !selectedEvent.id) {
881
+ selectEvent(processedEvents[0]);
882
+ setTimeout(() => {
883
+ const firstRow = document.getElementById(processedEvents[0].id);
884
+ if (firstRow) {
885
+ firstRow.classList.add('selected');
886
+ }
887
+ }, 0);
888
+ }
889
+ } catch (err) {
890
+ console.error('Error processing cached events:', err);
891
+ if (err instanceof RequestError) {
892
+ setError(err);
893
+ } else if (err instanceof Error) {
894
+ setError(err.message);
895
+ } else {
896
+ setError(String(err));
897
+ }
898
+ } finally {
899
+ setLoading(false);
900
+ }
901
+ return;
902
+ }
903
+
904
+ // If we don't have cached data, fetch from API
905
+ console.log('No cached data available in component state, fetching from API');
906
+ fetchAllGitHubEvents();
907
+ };
908
+
909
+ // Single initialization effect to handle all initial data loading
910
+ React.useEffect(() => {
911
+ // Skip if already initialized
912
+ if (initializedRef.current) {
913
+ console.log('Component already initialized, skipping initialization');
914
+ return;
915
+ }
916
+ initializedRef.current = true;
917
+ console.log('Initializing GithubEvents component once');
918
+ console.log(`Using cache key: "${cacheKey}" for GitHub user: ${githubUser}`);
919
+
920
+ // Check session storage to see if we've already fetched this session
921
+ const sessionKey = `${cacheKey}_session_fetched`;
922
+ const fetchedThisSession = sessionStorage.getItem(sessionKey) === 'true';
923
+ console.log('Already fetched this session:', fetchedThisSession);
924
+ fetchedThisSessionRef.current = fetchedThisSession;
925
+
926
+ // Debug all localStorage keys to make sure we're looking at the right one
927
+ console.log('All localStorage keys:', Object.keys(localStorage));
928
+ const cached = localStorage.getItem(cacheKey);
929
+ console.log(`LocalStorage for "${cacheKey}" exists:`, !!cached);
930
+ if (cached) {
931
+ try {
932
+ const parsedCache = JSON.parse(cached);
933
+ console.log('Cache parsed successfully, events count:', parsedCache.events.length);
934
+ console.log('Last fetch time:', new Date(parsedCache.lastFetched).toLocaleString());
935
+ if (!Array.isArray(parsedCache.events) || parsedCache.events.length === 0) {
936
+ console.log('Cached events array is empty or invalid, fetching all events');
937
+ fetchAllGitHubEvents();
938
+ return;
939
+ }
940
+
941
+ // Set cached events state
942
+ setCachedEvents(parsedCache.events);
943
+ setTotalCount(parsedCache.totalCount || parsedCache.events.length);
944
+ buildFilterOptionsFromEvents(parsedCache.events);
945
+
946
+ // Format last updated time
947
+ const lastFetchDate = new Date(parsedCache.lastFetched);
948
+ setLastUpdated(format(lastFetchDate, 'MMM d, yyyy h:mm a'));
949
+
950
+ // Check if we should refresh cache (if it's been more than 8 hours and we haven't fetched this session)
951
+ const hoursSinceLastFetch = (Date.now() - parsedCache.lastFetched) / (1000 * 60 * 60);
952
+ console.log('Hours since last fetch:', hoursSinceLastFetch.toFixed(2));
953
+ console.log('Should refresh cache:', hoursSinceLastFetch >= 8 && !fetchedThisSession);
954
+
955
+ // Apply initial filtering to cached events and display them first
956
+ const filteredCachedEvents = filterEvents(parsedCache.events);
957
+ console.log('Filtered events count:', filteredCachedEvents.length);
958
+ const paginatedEvents = filteredCachedEvents.slice(0, eventsPerPage);
959
+ console.log('Paginated events for display:', paginatedEvents.length);
960
+ const processedEvents = processEvents(paginatedEvents);
961
+ setEvents(processedEvents);
962
+ setLoading(false);
963
+
964
+ // Only fetch new events if it's been more than 8 hours AND we haven't fetched this session
965
+ if (hoursSinceLastFetch >= 8 && !fetchedThisSession) {
966
+ console.log('Cache is stale (>= 8 hours old), fetching new events in background');
967
+ // Fetch new events in background
968
+ setTimeout(() => {
969
+ fetchNewEvents();
970
+ // Mark that we've fetched this session
971
+ sessionStorage.setItem(sessionKey, 'true');
972
+ fetchedThisSessionRef.current = true;
973
+ }, 100);
974
+ } else {
975
+ console.log('Using cached events, no need to refresh');
976
+ }
977
+
978
+ // Select the most recent event by default
979
+ if (processedEvents.length > 0) {
980
+ selectEvent(processedEvents[0]);
981
+ setTimeout(() => {
982
+ const firstRow = document.getElementById(processedEvents[0].id);
983
+ if (firstRow) {
984
+ firstRow.classList.add('selected');
985
+ }
986
+ }, 0);
987
+ } else {
988
+ console.log('No events to display after filtering/pagination');
989
+ }
990
+ } catch (err) {
991
+ console.error('Failed to parse cached events, fetching new data:', err);
992
+ fetchAllGitHubEvents();
993
+ }
994
+ } else {
995
+ console.log('No cache found, fetching ALL GitHub events for first time');
996
+ fetchAllGitHubEvents();
997
+ }
998
+ }, [cacheKey, githubUser, eventsPerPage]);
999
+
1000
+ // Update the filter and pagination effect handlers
1001
+ React.useEffect(() => {
1002
+ // Skip the first render and only respond to actual filter changes
1003
+ if (!initializedRef.current) {
1004
+ console.log('Filter change ignored - component not initialized yet');
1005
+ return;
1006
+ }
1007
+ if (!isFilterChangeRef.current) {
1008
+ console.log('First filter change detected, just setting flag');
1009
+ isFilterChangeRef.current = true;
1010
+ return;
1011
+ }
1012
+ console.log('Filter changed, updating events with the following filters:');
1013
+ console.log(' Repository:', repoFilter || 'None');
1014
+ console.log(' Action type:', actionFilter || 'None');
1015
+ console.log(' Date filter:', dateFilter || 'None');
1016
+ console.log(' Description:', descriptionFilter || 'None');
1017
+ if (page !== 1) {
1018
+ console.log('Resetting to page 1 due to filter change');
1019
+ setPage(1);
1020
+ } else {
1021
+ console.log('Already on page 1, applying filters');
1022
+ fetchGitHubEvents(1, true);
1023
+ }
1024
+ }, [repoFilter, actionFilter, dateFilter, descriptionFilter]);
1025
+
1026
+ // Unified effect to handle page changes
1027
+ React.useEffect(() => {
1028
+ // Skip the first render and only respond to actual page changes
1029
+ if (!initializedRef.current) {
1030
+ console.log('Page change ignored - component not initialized yet');
1031
+ return;
1032
+ }
1033
+ if (!isPageChangeRef.current) {
1034
+ console.log('First page change detected, just setting flag');
1035
+ isPageChangeRef.current = true;
1036
+ return;
1037
+ }
1038
+ console.log(`Page changed to ${page}, fetching events`);
1039
+ fetchGitHubEvents(page, false);
1040
+ }, [page]);
1041
+ const totalPages = React.useMemo(() => {
1042
+ return Math.ceil(totalCount / eventsPerPage);
1043
+ }, [totalCount]);
1044
+ const getTimeOnly = date => {
1045
+ const parsed = parse(date, 'MMM d, yyyy h:mm a', new Date());
1046
+ return format(parsed, 'h:mm a');
1047
+ };
1048
+ let latestDateDisplayed = null;
1049
+ return /*#__PURE__*/_jsxs(Box, {
1050
+ sx: {
1051
+ display: 'flex',
1052
+ flexDirection: 'column',
1053
+ gap: 1
1054
+ },
1055
+ children: [/*#__PURE__*/_jsxs(Box, {
1056
+ sx: {
1057
+ mb: 1,
1058
+ display: 'flex',
1059
+ justifyContent: 'space-between',
1060
+ alignItems: 'end'
1061
+ },
1062
+ children: [/*#__PURE__*/_jsxs(Box, {
1063
+ sx: {
1064
+ display: 'flex',
1065
+ gap: .5,
1066
+ flexDirection: 'column'
1067
+ },
1068
+ children: [/*#__PURE__*/_jsxs(Typography, {
1069
+ variant: "subtitle1",
1070
+ fontWeight: "semiBold",
1071
+ children: [githubUser, "'s Events"]
1072
+ }), lastUpdated && /*#__PURE__*/_jsxs(Typography, {
1073
+ variant: "caption",
1074
+ color: "text.secondary",
1075
+ children: ["Last updated: ", lastUpdated]
1076
+ })]
1077
+ }), totalCount > eventsPerPage && /*#__PURE__*/_jsx(Pagination, {
1078
+ count: totalPages,
1079
+ page: page,
1080
+ onChange: (_, value) => setPage(value),
1081
+ size: "small",
1082
+ sx: {
1083
+ '& .MuiPaginationItem-root': {
1084
+ color: theme.palette.text.secondary,
1085
+ borderColor: theme.palette.divider
1086
+ }
1087
+ }
1088
+ })]
1089
+ }), /*#__PURE__*/_jsxs(Box, {
1090
+ sx: {
1091
+ display: 'flex',
1092
+ gap: '8px',
1093
+ '& .metadata-display': {
1094
+ width: 'max-content',
1095
+ display: 'flex',
1096
+ padding: '0px'
1097
+ },
1098
+ '@media (max-width:813px)': {
1099
+ '& .metadata-display': {
1100
+ display: 'none'
1101
+ }
1102
+ },
1103
+ '@media (max-width:340px)': {
1104
+ '& .metadata-display': {
1105
+ display: 'none'
1106
+ }
1107
+ }
1108
+ },
1109
+ children: [/*#__PURE__*/_jsx(Box, {
1110
+ sx: {
1111
+ minWidth: '340px',
1112
+ flexShrink: 0,
1113
+ display: 'block',
1114
+ position: 'relative'
1115
+ },
1116
+ className: "master-container",
1117
+ children: /*#__PURE__*/_jsx(TableContainer, {
1118
+ component: Paper,
1119
+ sx: {
1120
+ mb: 4,
1121
+ borderRadius: 0,
1122
+ position: 'relative'
1123
+ },
1124
+ className: "overflow-visible",
1125
+ children: /*#__PURE__*/_jsxs(Table, {
1126
+ size: "small",
1127
+ children: [/*#__PURE__*/_jsx(TableHead, {
1128
+ sx: {
1129
+ padding: '6px 8px'
1130
+ },
1131
+ children: /*#__PURE__*/_jsxs(TableRow, {
1132
+ sx: {
1133
+ padding: '6px 8px'
1134
+ },
1135
+ children: [/*#__PURE__*/_jsx(TableCell, {
1136
+ sx: {
1137
+ padding: '6px 8px'
1138
+ },
1139
+ children: /*#__PURE__*/_jsxs(Box, {
1140
+ sx: {
1141
+ display: 'flex',
1142
+ flexDirection: 'column',
1143
+ gap: 1
1144
+ },
1145
+ children: ["Date", /*#__PURE__*/_jsx(FormControl, {
1146
+ size: "small",
1147
+ fullWidth: true,
1148
+ children: /*#__PURE__*/_jsxs(Select, {
1149
+ value: dateFilter,
1150
+ onChange: e => setDateFilter(e.target.value),
1151
+ displayEmpty: true,
1152
+ sx: {
1153
+ '& .MuiSelect-select': {
1154
+ py: 0.5,
1155
+ fontSize: '12px'
1156
+ }
1157
+ },
1158
+ children: [_SmalMi || (_SmalMi = /*#__PURE__*/_jsx(SmalMi, {
1159
+ value: "",
1160
+ children: "All time"
1161
+ })), _SmalMi2 || (_SmalMi2 = /*#__PURE__*/_jsx(SmalMi, {
1162
+ value: "today",
1163
+ children: "Today"
1164
+ })), _SmalMi3 || (_SmalMi3 = /*#__PURE__*/_jsx(SmalMi, {
1165
+ value: "yesterday",
1166
+ children: "Yesterday"
1167
+ })), _SmalMi4 || (_SmalMi4 = /*#__PURE__*/_jsx(SmalMi, {
1168
+ value: "week",
1169
+ children: "Week"
1170
+ })), _SmalMi5 || (_SmalMi5 = /*#__PURE__*/_jsx(SmalMi, {
1171
+ value: "month",
1172
+ children: "Month"
1173
+ }))]
1174
+ })
1175
+ })]
1176
+ })
1177
+ }), /*#__PURE__*/_jsx(TableCell, {
1178
+ children: /*#__PURE__*/_jsxs(Box, {
1179
+ sx: {
1180
+ display: 'flex',
1181
+ flexDirection: 'column',
1182
+ gap: 1
1183
+ },
1184
+ children: ["Repository", /*#__PURE__*/_jsx(Autocomplete, {
1185
+ size: "small",
1186
+ options: repositories,
1187
+ value: repoFilter,
1188
+ onChange: (_, newValue) => setRepoFilter(newValue || ''),
1189
+ renderInput: params => /*#__PURE__*/_jsx(TextField, _extends({}, params, {
1190
+ placeholder: "All",
1191
+ sx: {
1192
+ '& .MuiInputBase-root': {
1193
+ height: '32px',
1194
+ minHeight: '32px',
1195
+ fontSize: '12px',
1196
+ p: '0 8px',
1197
+ '& input': {
1198
+ p: '2.5px 4px'
1199
+ },
1200
+ '& fieldset': {
1201
+ borderColor: 'rgba(255, 255, 255, 0.23)'
1202
+ }
1203
+ }
1204
+ }
1205
+ })),
1206
+ slotProps: {
1207
+ paper: {
1208
+ sx: {
1209
+ fontSize: '12px!important',
1210
+ '& .MuiAutocomplete-listbox': {
1211
+ '& .MuiAutocomplete-option': {
1212
+ whiteSpace: 'nowrap',
1213
+ overflow: 'visible',
1214
+ textOverflow: 'ellipsis',
1215
+ fontSize: '12px!important',
1216
+ width: '100%'
1217
+ }
1218
+ }
1219
+ }
1220
+ }
1221
+ },
1222
+ freeSolo: true,
1223
+ selectOnFocus: true,
1224
+ clearOnBlur: true,
1225
+ sx: {
1226
+ '& .MuiOutlinedInput-root': {
1227
+ p: 0
1228
+ }
1229
+ }
1230
+ })]
1231
+ })
1232
+ }), /*#__PURE__*/_jsx(TableCell, {
1233
+ children: /*#__PURE__*/_jsxs(Box, {
1234
+ sx: {
1235
+ display: 'flex',
1236
+ flexDirection: 'column',
1237
+ gap: 1
1238
+ },
1239
+ children: ["Type", /*#__PURE__*/_jsx(Autocomplete, {
1240
+ size: "small",
1241
+ options: actionTypes,
1242
+ value: actionFilter,
1243
+ onChange: (_, newValue) => setActionFilter(newValue || ''),
1244
+ renderInput: params => /*#__PURE__*/_jsx(TextField, _extends({}, params, {
1245
+ placeholder: "All",
1246
+ sx: {
1247
+ '& .MuiInputBase-root': {
1248
+ height: '32px',
1249
+ minHeight: '32px',
1250
+ fontSize: '12px',
1251
+ p: '0 8px',
1252
+ '& input': {
1253
+ p: '2.5px 4px'
1254
+ },
1255
+ '& fieldset': {
1256
+ borderColor: 'rgba(255, 255, 255, 0.23)'
1257
+ }
1258
+ }
1259
+ }
1260
+ })),
1261
+ freeSolo: true,
1262
+ selectOnFocus: true,
1263
+ clearOnBlur: true,
1264
+ slotProps: {
1265
+ paper: {
1266
+ sx: {
1267
+ fontSize: '12px!important',
1268
+ '& .MuiAutocomplete-listbox': {
1269
+ '& .MuiAutocomplete-option': {
1270
+ whiteSpace: 'nowrap',
1271
+ overflow: 'hidden',
1272
+ textOverflow: 'ellipsis',
1273
+ fontSize: '12px!important'
1274
+ }
1275
+ }
1276
+ }
1277
+ }
1278
+ },
1279
+ sx: {
1280
+ '& .MuiOutlinedInput-root': {
1281
+ p: 0
1282
+ }
1283
+ }
1284
+ })]
1285
+ })
1286
+ })]
1287
+ })
1288
+ }), /*#__PURE__*/_jsxs(TableBody, {
1289
+ sx: {
1290
+ cursor: 'pointer',
1291
+ '& tr:hover td': {
1292
+ backgroundColor: theme.palette.action.hover
1293
+ }
1294
+ },
1295
+ children: [events.map((event, index) => {
1296
+ const showDateRow = event.dateOnly !== latestDateDisplayed;
1297
+ latestDateDisplayed = event.dateOnly;
1298
+ return /*#__PURE__*/_jsxs(React.Fragment, {
1299
+ children: [showDateRow && /*#__PURE__*/_jsx(TableRow, {
1300
+ style: {
1301
+ backgroundColor: theme.palette.mode === 'light' ? 'color-mix(in oklab, rgba(0, 97, 194, 0.5) 25%, rgba(235, 235, 235, 0.5))' : 'color-mix(in oklab, rgba(102, 179, 255, 0.5) 25%, rgba(31, 31, 31, 0.5))'
1302
+ },
1303
+ children: /*#__PURE__*/_jsx(TableCell, {
1304
+ colSpan: 4,
1305
+ children: /*#__PURE__*/_jsx(Typography, {
1306
+ variant: "subtitle2",
1307
+ fontWeight: "semiBold",
1308
+ children: event.dateOnly
1309
+ })
1310
+ })
1311
+ }), /*#__PURE__*/_jsxs(TableRow, {
1312
+ id: event.id,
1313
+ sx: {
1314
+ '& td': {
1315
+ backgroundColor: theme.palette.background.paper,
1316
+ transition: 'all 1s cubic-bezier(1.1, 1.4, 2.1, 1.1, 0.8, 0.7,0.6,0.5,0.4,0.3,0.2,0.1,0.05)'
1317
+ },
1318
+ '&.selected td': {
1319
+ backgroundColor: theme.palette.action.selected,
1320
+ transition: 'all 0.3s cubic-bezier(1.1, 1.4, 2.1, 1.1, 0.8, 0.7,0.6,0.5,0.4,0.3,0.2,0.1,0.05)'
1321
+ },
1322
+ '&.hover td': {
1323
+ backgroundColor: theme.palette.action.hover,
1324
+ transition: 'all 0.3s cubic-bezier(1.1, 1.4, 2.1, 1.1, 0.8, 0.7,0.6,0.5,0.4,0.3,0.2,0.1,0.05)'
1325
+ },
1326
+ '&.selected.hover td': {
1327
+ backgroundColor: theme.palette.action.selected,
1328
+ transition: 'all 0.3s cubic-bezier(1.1, 1.4, 2.1, 1.1, 0.8, 0.7,0.6,0.5,0.4,0.3,0.2,0.1,0.05)'
1329
+ }
1330
+ },
1331
+ onClick: e => {
1332
+ e.preventDefault();
1333
+ const newSelectedRow = e.currentTarget;
1334
+ if (newSelectedRow) {
1335
+ if (selectedEvent.id) {
1336
+ const oldSelectedRow = document.getElementById(selectedEvent.id);
1337
+ if (oldSelectedRow) {
1338
+ oldSelectedRow.classList.remove('selected');
1339
+ }
1340
+ }
1341
+ newSelectedRow.classList.add('selected');
1342
+ selectEvent(event);
1343
+ }
1344
+ },
1345
+ onMouseEnter: e => {
1346
+ const closestRow = e.currentTarget;
1347
+ if (closestRow) {
1348
+ closestRow.classList.add('hover');
1349
+ }
1350
+ },
1351
+ onMouseLeave: e => {
1352
+ const closestRow = e.currentTarget;
1353
+ if (closestRow) {
1354
+ closestRow.classList.remove('hover');
1355
+ }
1356
+ },
1357
+ children: [/*#__PURE__*/_jsx(TableCell, {
1358
+ children: getTimeOnly(event.date)
1359
+ }), /*#__PURE__*/_jsx(TableCell, {
1360
+ children: /*#__PURE__*/_jsx("span", {
1361
+ onClick: e => e.stopPropagation(),
1362
+ style: {
1363
+ textDecoration: 'none',
1364
+ color: theme.palette.primary.main,
1365
+ cursor: 'pointer'
1366
+ },
1367
+ children: event.repo && event.repo.includes('/') ? event.repo.split('/')[1] : event.repo
1368
+ })
1369
+ }), /*#__PURE__*/_jsx(TableCell, {
1370
+ children: /*#__PURE__*/_jsx("span", {
1371
+ onClick: e => e.stopPropagation(),
1372
+ style: {
1373
+ textDecoration: 'none',
1374
+ color: theme.palette.primary.main,
1375
+ cursor: 'pointer'
1376
+ },
1377
+ children: event.action
1378
+ })
1379
+ })]
1380
+ })]
1381
+ }, event.id || `event-${index}`);
1382
+ }), events.length === 0 && !loading && (_TableRow || (_TableRow = /*#__PURE__*/_jsx(TableRow, {
1383
+ children: /*#__PURE__*/_jsx(TableCell, {
1384
+ colSpan: 4,
1385
+ align: "center",
1386
+ children: "No events found"
1387
+ })
1388
+ }))), loading && (_TableRow2 || (_TableRow2 = /*#__PURE__*/_jsx(TableRow, {
1389
+ children: /*#__PURE__*/_jsx(TableCell, {
1390
+ colSpan: 4,
1391
+ align: "center",
1392
+ children: /*#__PURE__*/_jsx(CircularProgress, {
1393
+ size: 40
1394
+ })
1395
+ })
1396
+ })))]
1397
+ })]
1398
+ })
1399
+ })
1400
+ }), !hideMetadata && selectedEvent.id && /*#__PURE__*/_jsx(MetadataDisplay, {
1401
+ className: "metadata-display",
1402
+ sx: {
1403
+ backgroundColor: 'rgba(255, 255, 255, 0.06)',
1404
+ borderRadiusBottomLeft: theme.shape.borderRadius,
1405
+ borderRadiusBottomRight: theme.shape.borderRadius,
1406
+ borderRadiusTopLeft: 0,
1407
+ borderRadiusTopRight: 0,
1408
+ boxShadow: theme.shadows[2],
1409
+ position: 'sticky',
1410
+ width: 'fit-content',
1411
+ maxWidth: '692px',
1412
+ minWidth: '300px',
1413
+ top: '84px',
1414
+ maxHeight: 'calc(100vh - 100px)',
1415
+ overflow: 'auto',
1416
+ height: 'fit-content'
1417
+ },
1418
+ children: error ? /*#__PURE__*/_jsx(ErrorDetails, {
1419
+ error: error
1420
+ }) : selectedEvent.actionType === 'PullRequestEvent' ? /*#__PURE__*/_jsx(PullRequestEvent, {
1421
+ event: selectedEvent
1422
+ }) : selectedEvent.actionType === 'PushEvent' ? /*#__PURE__*/_jsx(PushEvent, {
1423
+ event: selectedEvent
1424
+ }) : selectedEvent.actionType === 'DeleteEvent' ? /*#__PURE__*/_jsx(DeleteEvent, {
1425
+ event: selectedEvent
1426
+ }) : selectedEvent.actionType === 'CreateEvent' ? /*#__PURE__*/_jsx(CreateEvent, {
1427
+ event: selectedEvent
1428
+ }) : selectedEvent.actionType === 'IssuesEvent' ? /*#__PURE__*/_jsx(IssuesEvent, {
1429
+ event: selectedEvent
1430
+ }) : selectedEvent.actionType === 'IssueCommentEvent' ? /*#__PURE__*/_jsx(IssueCommentEvent, {
1431
+ event: selectedEvent
1432
+ }) : /*#__PURE__*/_jsx(ReactJson, {
1433
+ src: selectedEvent,
1434
+ name: false,
1435
+ theme: "monokai",
1436
+ displayDataTypes: false,
1437
+ enableClipboard: false,
1438
+ displayObjectSize: false,
1439
+ collapsed: 1,
1440
+ collapseStringsAfterLength: 50,
1441
+ style: {
1442
+ backgroundColor: 'transparent',
1443
+ fontSize: '0.875rem',
1444
+ fontFamily: 'monospace',
1445
+ padding: '8px',
1446
+ borderRadius: '4px',
1447
+ overflow: 'auto',
1448
+ maxHeight: 'calc(100vh - 200px)'
1449
+ }
1450
+ })
1451
+ })]
1452
+ })]
1453
+ });
1454
+ }