-
Notifications
You must be signed in to change notification settings - Fork 23
Feature: users activity #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,2 @@ | ||
| export { sendActionRun } from "./sendActionRun"; | ||
| export { sendActionError } from "./sendActionError"; | ||
| export { sendDiscussionUsage } from "./sendDiscussionUsage"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,8 @@ export const sendActionRun = () => { | |
| ), | ||
| MERGE_TIME_INTERVALS: getMultipleValuesInput("MERGE_TIME_INTERVALS"), | ||
| USE_CHARTS: getValueAsIs("USE_CHARTS"), | ||
| SHOW_CORRELATION_GRAPHS: getValueAsIs("SHOW_CORRELATION_GRAPHS"), | ||
| SHOW_ACTIVITY_TIME_GRAPHS: getValueAsIs("SHOW_ACTIVITY_TIME_GRAPHS"), | ||
|
Comment on lines
+42
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Consider adding type safety for analytics properties. To improve maintainability and prevent potential issues, consider defining an interface for the analytics properties. interface ActionAnalytics {
distinct_id: string;
SHOW_CORRELATION_GRAPHS: string;
SHOW_ACTIVITY_TIME_GRAPHS: string;
// ... other existing properties
} |
||
| }); | ||
| } else { | ||
| mixpanel.track("Anomymous action run", { distinct_id: "anonymous" }); | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ import { | |||||||||||||||||||||||||||||||
| preparePullRequestTimeline, | ||||||||||||||||||||||||||||||||
| prepareResponseTime, | ||||||||||||||||||||||||||||||||
| prepareRequestedReviews, | ||||||||||||||||||||||||||||||||
| prepareActionsTime, | ||||||||||||||||||||||||||||||||
| } from "./utils"; | ||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||
| invalidUserLogin, | ||||||||||||||||||||||||||||||||
|
|
@@ -47,6 +48,12 @@ export const collectData = ( | |||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| prepareActionsTime( | ||||||||||||||||||||||||||||||||
| pullRequest, | ||||||||||||||||||||||||||||||||
| data.events[index]?.filter((el) => el), | ||||||||||||||||||||||||||||||||
| collection | ||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||
|
Comment on lines
+51
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider enhancing error handling and event filtering The current implementation has a few areas that could be improved:
Consider applying this improvement: - prepareActionsTime(
- pullRequest,
- data.events[index]?.filter((el) => el),
- collection
- );
+ try {
+ prepareActionsTime(
+ pullRequest,
+ data.events[index]?.filter((el) => el?.event), // Be explicit about required fields
+ collection
+ );
+ } catch (error) {
+ console.error('Failed to prepare actions time:', error);
+ // Consider how errors should affect the overall collection
+ }📝 Committable suggestion
Suggested change
🧹 Nitpick (assertive) 💡 Codebase verification Add tests for the prepareActionsTime functionality Based on the codebase analysis:
Please add test coverage for:
🔗 Analysis chainAdd tests for the new functionality The PR objectives indicate that no tests were added. Since this is adding new functionality for user activity visualization, it's important to have test coverage. Let's check the existing test coverage: Would you like me to help create test cases for:
🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Check test coverage for the collectData functionality
# Look for test files related to collectData and actionsTime
echo "Searching for related test files..."
fd -e test.ts -e spec.ts . | grep -i "collect\|action"
echo "Checking for existing test patterns..."
rg -l "describe.*collectData|test.*prepareActionsTime"
Length of output: 281 Script: #!/bin/bash
# Let's try a broader search for test files and patterns
# First, let's find all test files in the repository
echo "All test files in the repository:"
fd -e test.ts -e spec.ts
# Look for any mentions of collectData or prepareActionsTime in the codebase
echo -e "\nSearching for collectData references:"
rg "collectData" -A 2 -B 2
echo -e "\nSearching for prepareActionsTime references:"
rg "prepareActionsTime" -A 2 -B 2
# Let's also check the implementation to understand the scope
echo -e "\nChecking implementation of prepareActionsTime:"
ast-grep --pattern 'function prepareActionsTime($_) { $$$ }'
Length of output: 6707 |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const closedDate = pullRequest.closed_at | ||||||||||||||||||||||||||||||||
| ? parseISO(pullRequest.closed_at) | ||||||||||||||||||||||||||||||||
| : null; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -82,6 +82,16 @@ export type Collection = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| commentsConducted?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| discussions?: Discussion; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| discussionsTypes?: DiscussionType; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| actionsTime?: Record< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| opened?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| merged?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| approved?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| changes_requested?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| commented?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+85
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Add JSDoc comments to document the property. Adding documentation would help other developers understand the purpose and format of the timestamps. Consider adding documentation: + /**
+ * Records timestamps of different PR actions throughout the day.
+ * The outer key represents the hour of the day (0-23).
+ * The inner object contains counts of different actions performed during that hour.
+ * All timestamp values should be in UTC to ensure consistent tracking across timezones.
+ */
actionsTime?: Record<
string,
{
opened?: number;
merged?: number;
approved?: number;
changes_requested?: number;
commented?: number;
}
>;📝 Committable suggestion
Suggested change
🧹 Nitpick (assertive) Consider using a union type for action keys. The type structure is well-designed for tracking timestamps of different PR actions. However, using Consider using a union type to restrict possible keys: + type ActionType = 'opened' | 'merged' | 'approved' | 'changes_requested' | 'commented';
actionsTime?: Record<
- string,
+ ActionType,
{
opened?: number;
merged?: number;
approved?: number;
changes_requested?: number;
commented?: number;
}
>;
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| prSizes?: string[]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sizes?: Record< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,3 +5,4 @@ export { prepareDiscussions } from "./prepareDiscussions"; | |
| export { prepareReviews } from "./prepareReviews"; | ||
| export { prepareResponseTime } from "./prepareResponseTime"; | ||
| export { prepareRequestedReviews } from "./prepareRequestedReviews"; | ||
| export { prepareActionsTime } from "./prepareActionsTime"; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Add unit tests for the new functionality. According to the PR checklist, tests haven't been added for the new changes. Since Would you like me to help generate unit tests for the
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,64 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { getHours, parseISO } from "date-fns"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { makeComplexRequest } from "../../requests"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Collection } from "../types"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { get, set } from "lodash"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { invalidUserLogin, reviewedTimelineEvent } from "../constants"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const prepareActionsTime = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pullRequest: Awaited< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ReturnType<typeof makeComplexRequest> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >["pullRequestInfo"][number], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| events: any[] | undefined = [], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collection: Record<string, Record<string, Collection>> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider adding proper TypeScript types for the events parameter The - events: any[] | undefined = [],
+ events: {
+ event: string;
+ submitted_at?: string;
+ state: string;
+ user?: { login: string };
+ }[] | undefined = [],
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const openingHour = pullRequest?.created_at | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? getHours(parseISO(pullRequest?.created_at)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const mergingHour = pullRequest?.merged_at | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? getHours(parseISO(pullRequest?.merged_at)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+14
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Extract common hour parsing logic and define constants The hour extraction logic is duplicated and uses a magic number (-1) for invalid hours. Consider refactoring to improve maintainability. +const INVALID_HOUR = -1;
+
+const parseEventHour = (dateString?: string): number => {
+ return dateString ? getHours(parseISO(dateString)) : INVALID_HOUR;
+};
+
- const openingHour = pullRequest?.created_at
- ? getHours(parseISO(pullRequest?.created_at))
- : -1;
- const mergingHour = pullRequest?.merged_at
- ? getHours(parseISO(pullRequest?.merged_at))
- : -1;
+ const openingHour = parseEventHour(pullRequest?.created_at);
+ const mergingHour = parseEventHour(pullRequest?.merged_at);📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| events | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ?.filter((el) => el.event === reviewedTimelineEvent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map((el) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const submitHour = el?.submitted_at | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? getHours(parseISO(el?.submitted_at)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (submitHour !== -1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const keys = ["total", "total", "actionsTime", submitHour, el.state]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set(collection, keys, (get(collection, keys, 0) as number) + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userKeys = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| el?.user?.login || invalidUserLogin, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "total", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "actionsTime", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| submitHour, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| el.state, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set(collection, userKeys, (get(collection, userKeys, 0) as number) + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+21
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor event processing to use forEach and extract collection update logic The current implementation has two issues:
+const updateActionCount = (
+ collection: Record<string, Record<string, Collection>>,
+ hour: number,
+ state: string,
+ userLogin: string
+) => {
+ const totalKeys = ["total", "total", "actionsTime", hour, state];
+ const userKeys = [userLogin, "total", "actionsTime", hour, state];
+
+ set(collection, totalKeys, (get(collection, totalKeys, 0) as number) + 1);
+ set(collection, userKeys, (get(collection, userKeys, 0) as number) + 1);
+};
+
events
?.filter((el) => el.event === reviewedTimelineEvent)
- .map((el) => {
+ .forEach((el) => {
const submitHour = el?.submitted_at
? getHours(parseISO(el?.submitted_at))
: -1;
if (submitHour !== -1) {
- const keys = ["total", "total", "actionsTime", submitHour, el.state];
- set(collection, keys, (get(collection, keys, 0) as number) + 1);
- const userKeys = [
- el?.user?.login || invalidUserLogin,
- "total",
- "actionsTime",
- submitHour,
- el.state,
- ];
- set(collection, userKeys, (get(collection, userKeys, 0) as number) + 1);
+ updateActionCount(
+ collection,
+ submitHour,
+ el.state,
+ el?.user?.login || invalidUserLogin
+ );
}
});📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (openingHour !== -1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const keys = ["total", "total", "actionsTime", openingHour, "opened"]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set(collection, keys, get(collection, keys, 0) + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userKeys = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pullRequest?.user.login || invalidUserLogin, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "total", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "actionsTime", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openingHour, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "opened", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set(collection, userKeys, get(collection, userKeys, 0) + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (mergingHour !== -1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const keys = ["total", "total", "actionsTime", mergingHour, "merged"]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set(collection, keys, get(collection, keys, 0) + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userKeys = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pullRequest?.user.login || invalidUserLogin, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "total", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "actionsTime", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openingHour, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "merged", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set(collection, userKeys, get(collection, userKeys, 0) + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+52
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix critical bug: Merge action recorded with wrong hour There's a critical bug in the merge action recording logic. The code is using const userKeys = [
pullRequest?.user.login || invalidUserLogin,
"total",
"actionsTime",
- openingHour,
+ mergingHour,
"merged",
];📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+7
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Consider architectural improvements for better maintainability The current implementation could benefit from the following architectural improvements:
Would you like me to provide an example of how to implement these improvements? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ import { | |
| } from "./view/utils"; | ||
| import { octokit } from "./octokit"; | ||
| import { showStatsTypes } from "./common/constants"; | ||
| import { createActivityTimeMarkdown } from "./view/utils/createActivityTimeMarkdown"; | ||
|
|
||
| export const createOutput = async ( | ||
| data: Record<string, Record<string, Collection>> | ||
|
|
@@ -75,6 +76,23 @@ export const createOutput = async ( | |
| title: "Correlation Graphs", | ||
| }); | ||
| } | ||
| if (getValueAsIs("SHOW_ACTIVITY_TIME_GRAPHS") === "true") { | ||
AlexSim93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const activityComment = await octokit.rest.issues.createComment({ | ||
| repo: getValueAsIs("GITHUB_REPO_FOR_ISSUE"), | ||
| owner: getValueAsIs("GITHUB_OWNER_FOR_ISSUE"), | ||
| issue_number: issue.data.number, | ||
| body: createActivityTimeMarkdown(data, users, [ | ||
| { | ||
| title: "Pull Request report total", | ||
| link: `${issue.data.html_url}#`, | ||
| }, | ||
| ]), | ||
| }); | ||
AlexSim93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| comments.push({ | ||
| comment: activityComment, | ||
| title: "Activity time Graphs", | ||
| }); | ||
| } | ||
|
Comment on lines
+79
to
+95
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Add unit tests for the new functionality. The PR objectives mention that no tests were added. Please add unit tests to cover:
Would you like me to help generate the test cases for this new functionality? |
||
| console.log("Issue successfully created."); | ||
| for (let date of dates) { | ||
| if (date === "total") continue; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,18 @@ | ||||||||||||||||||||||||||||||||||
| import { Collection } from "../../converters"; | ||||||||||||||||||||||||||||||||||
| import { createActivityXYChart } from "./createActivityXYChart"; | ||||||||||||||||||||||||||||||||||
| import { createReferences } from "./createReferences"; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| export const createActivityTimeMarkdown = ( | ||||||||||||||||||||||||||||||||||
| data: Record<string, Record<string, Collection>>, | ||||||||||||||||||||||||||||||||||
| users: string[], | ||||||||||||||||||||||||||||||||||
| references: { title: string; link: string }[] = [] | ||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Consider adding input validation and improving type definitions.
Consider applying these improvements: +type ActivityData = Record<string, Record<string, Collection>>;
+type Reference = { title: string; link: string };
+
export const createActivityTimeMarkdown = (
- data: Record<string, Record<string, Collection>>,
- users: string[],
- references: { title: string; link: string }[] = []
+ data: ActivityData,
+ users: string[],
+ references: Reference[] = []
) => {
+ if (!data || !users) {
+ throw new Error('Required parameters "data" and "users" must be provided');
+ }📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
| const activity = users | ||||||||||||||||||||||||||||||||||
| .filter( | ||||||||||||||||||||||||||||||||||
| (user) => Object.keys(data[user]?.total?.actionsTime || {}).length > 1 | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| .map((user) => createActivityXYChart(data, user)) | ||||||||||||||||||||||||||||||||||
| .join("\n"); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return [createReferences(references)].concat(activity).join("\n").trim(); | ||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Consider improving readability and handling empty results. The current implementation could be more explicit and handle edge cases better. Consider this alternative: - return [createReferences(references)].concat(activity).join("\n").trim();
+ const parts = [
+ createReferences(references),
+ activity
+ ].filter(Boolean);
+
+ if (parts.length === 0) {
+ return "No activity data available.";
+ }
+
+ return parts.join("\n").trim();📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Add unit tests for the activity time markdown generation. The PR objectives indicate that no tests were added. Given the complexity of data processing and the importance of this feature for visualizing user activity, unit tests are essential to ensure reliability. Would you like me to help generate unit tests for this file? The tests should cover:
|
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,60 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Collection } from "../../converters"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { createXYChart } from "./common/createXYChart"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const createActivityXYChart = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data: Record<string, Record<string, Collection>>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Enhance type safety with more specific types Consider defining a more specific type for the nested data structure instead of using +type ActivityData = {
+ [user: string]: {
+ total?: {
+ actionsTime?: {
+ [hour: string]: {
+ opened?: number;
+ merged?: number;
+ approved?: number;
+ changes_requested?: number;
+ commented?: number;
+ };
+ };
+ };
+ };
+};
-export const createActivityXYChart = (
- data: Record<string, Record<string, Collection>>,
+export const createActivityXYChart = (
+ data: ActivityData,
user: string
) => {📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const hours = Array.from({ length: 24 }, (_, i) => i.toString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Consider memoizing the hours array Since the hours array is constant and used in multiple map operations, consider moving it outside the function to avoid recreation on each call. +const HOURS = Array.from({ length: 24 }, (_, i) => i.toString());
+
export const createActivityXYChart = (
data: ActivityData,
user: string
) => {
- const hours = Array.from({ length: 24 }, (_, i) => i.toString());
+ const hours = HOURS;📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return createXYChart({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: `Activity ${user}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xAxis: hours, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| yAxis: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| min: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max: Math.max( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...Object.values(data[user]?.total?.actionsTime || {}).map((value) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Math.max(...Object.values(value), 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: "Amount", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+9
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve chart configuration robustness and clarity Several improvements could enhance the chart configuration:
+const calculateMaxValue = (actionsTime: Record<string, Record<string, number>> = {}) => {
+ const values = Object.values(actionsTime).flatMap(hourData => Object.values(hourData));
+ return values.length ? Math.max(...values) : 1;
+};
+
return createXYChart({
- title: `Activity ${user}`,
+ title: `Activity Throughout the Day - ${user}`,
xAxis: hours,
yAxis: {
min: 0,
- max: Math.max(
- ...Object.values(data[user]?.total?.actionsTime || {}).map((value) =>
- Math.max(...Object.values(value), 0)
- ),
- 1
- ),
+ max: calculateMaxValue(data[user]?.total?.actionsTime),
title: "Amount",
},📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lines: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "Opened", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: "black", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| values: hours.map( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (el) => data[user]?.total?.actionsTime?.[el]?.opened || 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "Merged", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: "purple", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| values: hours.map( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (el) => data[user]?.total?.actionsTime?.[el]?.merged || 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "Approved", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: "green", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| values: hours.map( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (el) => data[user]?.total?.actionsTime?.[el]?.approved || 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "Changes Requested", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: "red", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| values: hours.map( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (el) => data[user]?.total?.actionsTime?.[el]?.changes_requested || 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "Commented", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: "blue", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| values: hours.map( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (el) => data[user]?.total?.actionsTime?.[el]?.commented || 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+22
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor repeated code and improve accessibility The lines configuration has several areas for improvement:
+const ACTIVITY_TYPES = [
+ { name: 'Opened', color: '#000000', key: 'opened' },
+ { name: 'Merged', color: '#9333EA', key: 'merged' },
+ { name: 'Approved', color: '#16A34A', key: 'approved' },
+ { name: 'Changes Requested', color: '#DC2626', key: 'changes_requested' },
+ { name: 'Commented', color: '#2563EB', key: 'commented' }
+] as const;
+
+const getActivityValues = (
+ actionsTime: Record<string, Record<string, number>> = {},
+ hours: string[],
+ key: string
+) => hours.map(hour => actionsTime[hour]?.[key] || 0);
+
lines: [
- {
- name: "Opened",
- color: "black",
- values: hours.map(
- (el) => data[user]?.total?.actionsTime?.[el]?.opened || 0
- ),
- },
- // ... other repeated blocks
+ ...ACTIVITY_TYPES.map(({ name, color, key }) => ({
+ name,
+ color,
+ values: getActivityValues(data[user]?.total?.actionsTime, hours, key)
+ }))
],Also, consider adding a check for completely missing data: if (!data[user]?.total?.actionsTime) {
throw new Error(`No activity data found for user: ${user}`);
} |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+4
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Add tests for the visualization logic As mentioned in the PR description, tests haven't been added for this new feature. Given that this is a critical visualization component, please add tests to verify:
Would you like me to help create a test suite for this component? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
💡 Codebase verification
Add type definitions for the new analytics properties
The properties are consistently used across the codebase in:
action.yml)README.md)sendActionRun.ts,sendActionError.ts)createOutput.ts)createConfigParamsCode.ts)However, no type definitions were found for these properties. Add them to the analytics event interface:
🔗 Analysis chain
LGTM! Consider adding type definitions.
The new analytics properties follow the existing implementation pattern correctly. However, consider adding these properties to your analytics event type definitions for better type safety.
Let's verify the consistency of these property names across the codebase:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 8152