Skip to content

Commit 4d058e8

Browse files
feat: add view for my pull requests and overall repository view (#6)
1 parent f0464c1 commit 4d058e8

17 files changed

+452
-44
lines changed

package-lock.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"dependencies": {
77
"@emotion/react": "^11.11.4",
88
"@emotion/styled": "^11.11.0",
9+
"@iconify/react": "^5.2.0",
910
"@mui/icons-material": "^6.1.6",
1011
"@mui/material": "^6.1.6",
1112
"@octokit/rest": "^21.0.2",

src/App.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const ConfigContext = React.createContext<{
1212
repositorySettings: Record<string, boolean>;
1313
handleRepositorySelect: (repository: string, selected: boolean) => void;
1414
saveRawSettings: (settings: Record<string, boolean> | undefined) => void;
15+
user?: { login: string; avatar_url: string; url: string };
1516
}>({
1617
octokit: null,
1718
repositorySettings: {},
@@ -35,7 +36,7 @@ function App() {
3536
const octoKit = new GitService(
3637
(import.meta as any).env.VITE_GITHUB_API_URL ||
3738
"https://api.github.com",
38-
token,
39+
token
3940
);
4041
octoKit.testAuthentication().then((user) => {
4142
if (user.status !== 200) {
@@ -62,8 +63,8 @@ function App() {
6263
new GitService(
6364
(import.meta as any).env.VITE_GITHUB_API_URL ||
6465
"https://api.github.com",
65-
localStorage.getItem("token") || "",
66-
),
66+
localStorage.getItem("token") || ""
67+
)
6768
);
6869
}
6970
}, []);
@@ -88,7 +89,7 @@ function App() {
8889
return newState;
8990
});
9091
},
91-
[],
92+
[]
9293
);
9394

9495
const saveRawSettings = React.useCallback(
@@ -98,12 +99,12 @@ function App() {
9899
setRepositorySettings(settings);
99100
localStorage.setItem("REPOSITORY_CONFIG", JSON.stringify(settings));
100101
},
101-
[],
102+
[]
102103
);
103104

104105
React.useEffect(() => {
105106
const repositoryConfig = JSON.parse(
106-
localStorage.getItem("REPOSITORY_CONFIG") ?? "{}",
107+
localStorage.getItem("REPOSITORY_CONFIG") ?? "{}"
107108
);
108109
setRepositorySettings(repositoryConfig);
109110
}, []);
@@ -116,6 +117,7 @@ function App() {
116117
repositorySettings,
117118
handleRepositorySelect,
118119
saveRawSettings,
120+
user,
119121
}}
120122
>
121123
<AppBar

src/components/AuthHeader.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import BottomNavigation from "@mui/material/BottomNavigation";
44
import BottomNavigationAction from "@mui/material/BottomNavigationAction";
55
import React from "react";
66
import { useLocation, useNavigate } from "react-router-dom";
7+
import { PullRequestIcon } from "./icons/PullRequestIcon";
8+
import { RepositoryIcon } from "./icons/RepositoryIcon";
79

810
export type AuthHeaderProps = {
911
user: {
@@ -44,6 +46,21 @@ export const AuthHeader: React.FC<AuthHeaderProps> = ({
4446
value="/"
4547
title="Dashboard"
4648
/>
49+
<BottomNavigationAction
50+
label="My PRs"
51+
icon={<PullRequestIcon />}
52+
sx={{ backgroundColor: "#f5f5f5" }}
53+
value="/my-pull-requests"
54+
title="My PRs"
55+
/>
56+
57+
<BottomNavigationAction
58+
label="Repositories"
59+
icon={<RepositoryIcon />}
60+
sx={{ backgroundColor: "#f5f5f5" }}
61+
value="/repositories"
62+
title="Repositories"
63+
/>
4764
<BottomNavigationAction
4865
label="Coverage"
4966
icon={<Biotech />}

src/components/Dashboard/PullRequestFilters.tsx

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -124,53 +124,46 @@ export const PullRequestFilters: React.FC<PullRequestFiltersProps> = ({
124124
{
125125
name: "Authors",
126126
options: authors,
127-
setSelected: (authors: string[]) => onFilterChange("authors", authors),
127+
onChange: (authors: string[]) => onFilterChange("authors", authors),
128128
},
129129
{
130130
name: "Reviewers",
131131
options: reviewers,
132-
setSelected: (reviewers: string[]) =>
133-
onFilterChange("reviewers", reviewers),
132+
onChange: (reviewers: string[]) => onFilterChange("reviewers", reviewers),
134133
},
135134
{
136135
name: "Assignees",
137136
options: assignees,
138-
setSelected: (assignees: string[]) =>
139-
onFilterChange("assignees", assignees),
137+
onChange: (assignees: string[]) => onFilterChange("assignees", assignees),
140138
},
141139
{
142140
name: "Repositories",
143141
options: repositories,
144-
setSelected: (repositories: string[]) =>
142+
onChange: (repositories: string[]) =>
145143
onFilterChange("repositories", repositories),
146144
},
147145
{
148146
name: "Include Labels",
149147
options: labels.filter(
150148
(label) => !filterValues.excludeLabels.includes(label)
151149
),
152-
setSelected: (includeLabels: string[]) =>
150+
onChange: (includeLabels: string[]) =>
153151
onFilterChange("includeLabels", includeLabels),
154152
},
155153
{
156154
name: "Exclude Lables",
157155
options: labels.filter(
158156
(label) => !filterValues.includeLabels.includes(label)
159157
),
160-
setSelected: (excludeLabels: string[]) =>
158+
onChange: (excludeLabels: string[]) =>
161159
onFilterChange("excludeLabels", excludeLabels),
162160
},
163161
];
164162

165163
return (
166164
<Box>
167165
{multiselectFIlterOptions.map((filter) => (
168-
<MultiselectFilter
169-
key={filter.name}
170-
name={filter.name}
171-
options={filter.options}
172-
onChange={filter.setSelected}
173-
/>
166+
<MultiselectFilter key={filter.name} {...filter} />
174167
))}
175168
</Box>
176169
);

src/components/PATSetupGuide.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Typography, Box } from "@mui/material";
44
const PATSetupGuide = () => {
55
return (
66
<>
7-
<Typography paragraph>
7+
<Typography component="p">
88
A Personal Access Token (PAT) on GitHub allows third-party applications
99
to interact with your GitHub account securely. Follow these steps to
1010
create a PAT:
@@ -35,7 +35,7 @@ const PATSetupGuide = () => {
3535
<Typography variant="body1" component="div">
3636
7. Click <strong>Generate token</strong>.
3737
</Typography>
38-
<Typography paragraph>
38+
<Typography component="p">
3939
After clicking <strong>Generate token</strong>, make sure to copy your
4040
new personal access token. You won’t be able to see it again!
4141
</Typography>

src/components/PullRequestCard.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
Box,
1010
Tooltip,
1111
} from "@mui/material";
12-
import { green, red, amber } from "@mui/material/colors";
1312
import { PullRequest } from "../models/PullRequest";
1413
import {
1514
DesignServices,
@@ -23,23 +22,13 @@ import { PullRequestsApprovals } from "./PullRequestsApprovals";
2322
import { PullRequestMergeCheck } from "./PullRequestMergeCheck";
2423
import getContrastColor from "../utils/getContractColor";
2524
import replaceEmoticons from "../utils/replaceEmoticons";
25+
import { getColorForDaysInReview } from "../utils/getColorsForDaysInReview";
2626

2727
interface PullRequestCardProps {
2828
pr: PullRequest;
2929
}
3030

3131
const PullRequestCard: React.FC<PullRequestCardProps> = ({ pr }) => {
32-
const getColorForDaysInReview = (createdAt: Date) => {
33-
const today = new Date();
34-
const daysInReview = Math.floor(
35-
(today.getTime() - new Date(createdAt).getTime()) / (1000 * 3600 * 24),
36-
);
37-
38-
if (daysInReview < 3) return green[500];
39-
if (daysInReview < 7) return amber[500];
40-
return red[500];
41-
};
42-
4332
return (
4433
<Card sx={{ display: "flex", flexDirection: "column", height: "100%" }}>
4534
<CardActions
@@ -124,7 +113,7 @@ const PullRequestCard: React.FC<PullRequestCardProps> = ({ pr }) => {
124113
<Chip
125114
label={Math.floor(
126115
(new Date().getTime() - new Date(pr.created_at).getTime()) /
127-
(1000 * 3600 * 24),
116+
(1000 * 3600 * 24)
128117
)}
129118
sx={{ bgcolor: getColorForDaysInReview(pr.created_at) }}
130119
size="small"
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import {
2+
Card,
3+
CardContent,
4+
Chip,
5+
Box,
6+
Typography,
7+
Tooltip,
8+
Link,
9+
} from "@mui/material";
10+
import { PullRequest } from "../../models/PullRequest";
11+
import { LanguageIcon } from "../icons/LanguageIcon";
12+
import { useMemo } from "react";
13+
import { getColorForDaysInReview } from "../../utils/getColorsForDaysInReview";
14+
import { Visibility } from "@mui/icons-material";
15+
16+
export type RepositoryCardProps = {
17+
name: string;
18+
pulls: PullRequest[];
19+
};
20+
21+
export const RepositoryCard: React.FC<RepositoryCardProps> = ({ pulls }) => {
22+
const [
23+
{
24+
base: { repo },
25+
},
26+
] = pulls;
27+
28+
const oldestPr = useMemo(() => {
29+
return pulls.sort(
30+
(prA, prB) => prA.created_at.getTime() - prB.created_at.getTime()
31+
)[0];
32+
}, [pulls]);
33+
34+
return (
35+
<Card
36+
sx={{
37+
display: "flex",
38+
flexDirection: "column",
39+
height: "100%",
40+
minWidth: 320,
41+
}}
42+
>
43+
<CardContent
44+
sx={{
45+
display: "flex",
46+
flexDirection: "column",
47+
paddingBottom: 1,
48+
height: "100%",
49+
}}
50+
>
51+
<Box
52+
sx={{
53+
display: "flex",
54+
alignItems: "center",
55+
flexDirection: "row",
56+
gap: 1,
57+
mb: 1,
58+
}}
59+
>
60+
<LanguageIcon language={repo.language} />
61+
<Typography variant="h6">{repo.full_name}</Typography>
62+
</Box>
63+
<Box
64+
sx={{
65+
display: "flex",
66+
alignItems: "center",
67+
flexDirection: "row",
68+
gap: 1,
69+
mt: "auto",
70+
}}
71+
>
72+
<Typography color="text.secondary">Max Days: </Typography>
73+
<Chip
74+
label={Math.floor(
75+
(new Date().getTime() - oldestPr.created_at?.getTime()) /
76+
(1000 * 3600 * 24)
77+
)}
78+
size="small"
79+
sx={{ bgcolor: getColorForDaysInReview(oldestPr.created_at) }}
80+
/>
81+
{"|"}
82+
<Typography color="text.secondary">PRs: </Typography>
83+
<Chip label={pulls.length} size="small" color="primary" />
84+
<Link
85+
href={repo.html_url + "/pulls"}
86+
sx={{ marginLeft: "auto" }}
87+
target="_blank"
88+
rel="noopener"
89+
>
90+
<Tooltip title="View PRs">
91+
<Visibility />
92+
</Tooltip>
93+
</Link>
94+
</Box>
95+
</CardContent>
96+
</Card>
97+
);
98+
};

src/components/RepositorySetupGuide.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const Outline: React.FC<{ text: string }> = ({ text }) => {
1414
const PATSetupGuide = () => {
1515
return (
1616
<>
17-
<Typography paragraph>
17+
<Typography component="p">
1818
To be able to see pull request you would need to pick the project first.
1919
Follow these steps to configure your projects:
2020
</Typography>
@@ -42,7 +42,7 @@ const PATSetupGuide = () => {
4242
<Typography variant="body1" component="div">
4343
7. When finished just click outside the dialog to close it.
4444
</Typography>
45-
<Typography paragraph sx={{ marginTop: 2 }}>
45+
<Typography component="p" sx={{ marginTop: 2 }}>
4646
All the selection would be saved automatically in your browser. As
4747
soon as you select the repositories you would be able to see the pull
4848
requests if any are available.

0 commit comments

Comments
 (0)