Skip to content

Commit 193867f

Browse files
authored
Merge pull request #120 from ArjinAlbay/main
add monitoring dashboard
2 parents 8ebd1cc + 9ff2240 commit 193867f

File tree

5 files changed

+137
-40
lines changed

5 files changed

+137
-40
lines changed

src/app/action-required/page.tsx

Lines changed: 82 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
77
import { Button } from "@/components/ui/button";
88
import { Badge } from "@/components/ui/badge";
99
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
10+
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
1011
import {
1112
Table,
1213
TableBody,
@@ -23,7 +24,6 @@ import {
2324
Zap,
2425
ExternalLink,
2526
RefreshCw,
26-
Star,
2727
LucideIcon,
2828
} from "lucide-react";
2929
import { useActionItemsStore } from "@/stores";
@@ -38,16 +38,34 @@ interface ActionItem {
3838
url?: string;
3939
repo: string;
4040
type: string;
41-
author?: string;
41+
author: {
42+
login: string;
43+
avatarUrl: string;
44+
};
45+
labels: Array<{ name: string; color?: string }>;
4246
priority: "urgent" | "high" | "medium" | "low";
4347
daysOld?: number;
48+
updatedAt: string;
4449
comments?: number;
4550
stars?: number;
4651
}
4752

4853
const VALID_TABS = ["assigned", "mentions", "stale"] as const;
4954
type ValidTab = (typeof VALID_TABS)[number];
5055

56+
function formatTimeAgo(dateString: string): string {
57+
const now = new Date();
58+
const past = new Date(dateString);
59+
const diffInSeconds = Math.floor((now.getTime() - past.getTime()) / 1000);
60+
61+
if (diffInSeconds < 60) return "just now";
62+
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
63+
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
64+
if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
65+
if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 604800)}w ago`;
66+
return `${Math.floor(diffInSeconds / 2592000)}mo ago`;
67+
}
68+
5169
function ActionRequiredContent() {
5270
const {
5371
assignedItems,
@@ -144,12 +162,13 @@ function ActionRequiredContent() {
144162
<Table>
145163
<TableHeader>
146164
<TableRow>
147-
<TableHead className="w-[35%]">Title / Repository</TableHead>
148-
<TableHead className="w-[12%]">Priority</TableHead>
149-
<TableHead className="w-[12%]">Activity</TableHead>
150-
<TableHead className="w-[13%]">Repo Popularity</TableHead>
151-
<TableHead className="w-[13%]">Type</TableHead>
152-
<TableHead className="w-[15%]">Actions</TableHead>
165+
<TableHead className="w-[30%]">Title / Repository</TableHead>
166+
<TableHead className="w-[10%]">Author</TableHead>
167+
<TableHead className="w-[18%]">Labels</TableHead>
168+
<TableHead className="w-[10%]">Priority</TableHead>
169+
<TableHead className="w-[8%]">Activity</TableHead>
170+
<TableHead className="w-[10%]">Updated</TableHead>
171+
<TableHead className="w-[14%]">Actions</TableHead>
153172
</TableRow>
154173
</TableHeader>
155174
<TableBody>
@@ -162,16 +181,22 @@ function ActionRequiredContent() {
162181
</div>
163182
</TableCell>
164183
<TableCell>
165-
<div className="w-16 h-6 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
184+
<div className="w-8 h-8 bg-gray-300 dark:bg-gray-600 rounded-full animate-pulse" />
166185
</TableCell>
167186
<TableCell>
168-
<div className="w-12 h-4 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
187+
<div className="flex gap-1">
188+
<div className="w-16 h-6 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
189+
<div className="w-16 h-6 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
190+
</div>
191+
</TableCell>
192+
<TableCell>
193+
<div className="w-16 h-6 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
169194
</TableCell>
170195
<TableCell>
171196
<div className="w-12 h-4 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
172197
</TableCell>
173198
<TableCell>
174-
<div className="w-16 h-6 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
199+
<div className="w-16 h-4 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
175200
</TableCell>
176201
<TableCell>
177202
<div className="w-8 h-8 bg-gray-300 dark:bg-gray-600 rounded animate-pulse" />
@@ -221,12 +246,13 @@ function ActionRequiredContent() {
221246
<Table>
222247
<TableHeader>
223248
<TableRow>
224-
<TableHead className="w-[35%]">Title / Repository</TableHead>
225-
<TableHead className="w-[12%]">Priority</TableHead>
226-
<TableHead className="w-[12%]">Activity</TableHead>
227-
<TableHead className="w-[13%]">Repo Popularity</TableHead>
228-
<TableHead className="w-[13%]">Type</TableHead>
229-
<TableHead className="w-[15%]">Actions</TableHead>
249+
<TableHead className="w-[30%]">Title / Repository</TableHead>
250+
<TableHead className="w-[10%]">Author</TableHead>
251+
<TableHead className="w-[18%]">Labels</TableHead>
252+
<TableHead className="w-[10%]">Priority</TableHead>
253+
<TableHead className="w-[8%]">Activity</TableHead>
254+
<TableHead className="w-[10%]">Updated</TableHead>
255+
<TableHead className="w-[14%]">Actions</TableHead>
230256
</TableRow>
231257
</TableHeader>
232258
<TableBody>
@@ -253,11 +279,47 @@ function ActionRequiredContent() {
253279
</div>
254280
<p className="text-sm text-gray-500 dark:text-gray-400 truncate">
255281
{item.repo}
256-
{item.author && ` • ${item.author}`}
257282
</p>
258283
</div>
259284
</div>
260285
</TableCell>
286+
<TableCell>
287+
<div className="flex items-center gap-2">
288+
<Avatar className="w-8 h-8">
289+
<AvatarImage src={item.author.avatarUrl} alt={item.author.login} />
290+
<AvatarFallback>
291+
{item.author.login.substring(0, 2).toUpperCase()}
292+
</AvatarFallback>
293+
</Avatar>
294+
</div>
295+
</TableCell>
296+
<TableCell>
297+
<div className="flex flex-wrap gap-1">
298+
{item.labels.slice(0, 3).map((label, idx) => (
299+
<Badge
300+
key={idx}
301+
variant="outline"
302+
className="text-xs"
303+
style={
304+
label.color
305+
? {
306+
borderColor: `#${label.color}`,
307+
backgroundColor: `#${label.color}20`,
308+
color: `#${label.color}`,
309+
}
310+
: undefined
311+
}
312+
>
313+
{label.name}
314+
</Badge>
315+
))}
316+
{item.labels.length > 3 && (
317+
<Badge variant="outline" className="text-xs">
318+
+{item.labels.length - 3}
319+
</Badge>
320+
)}
321+
</div>
322+
</TableCell>
261323
<TableCell>
262324
<Badge
263325
variant={
@@ -281,16 +343,10 @@ function ActionRequiredContent() {
281343
</div>
282344
</TableCell>
283345
<TableCell>
284-
<div className="flex items-center gap-1 text-gray-600 dark:text-gray-300">
285-
<Star className="w-4 h-4 text-yellow-500" />
286-
<span>{item.stars || 0}</span>
346+
<div className="text-sm text-gray-500 dark:text-gray-400">
347+
{formatTimeAgo(item.updatedAt)}
287348
</div>
288349
</TableCell>
289-
<TableCell>
290-
<Badge variant="outline" className="capitalize">
291-
{item.type === "pullRequest" ? "PR" : "Issue"}
292-
</Badge>
293-
</TableCell>
294350
<TableCell>
295351
<AddToKanbanButton item={item as StoreActionItem} />
296352
</TableCell>

src/components/quick-wins/hooks/useQuickWins.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@ export function useQuickWins() {
4646
url: issue.url,
4747
createdAt: issue.created_at,
4848
updatedAt: issue.updated_at,
49-
author: issue.author.login,
50-
labels: issue.labels.map((l) => l.name),
49+
author: {
50+
login: issue.author.login,
51+
avatarUrl: issue.author.avatar_url,
52+
},
53+
labels: issue.labels.map((l) => ({ name: l.name, color: l.color })),
5154
daysOld: Math.floor(
5255
(Date.now() - new Date(issue.created_at).getTime()) /
5356
(1000 * 60 * 60 * 24)
@@ -69,8 +72,11 @@ export function useQuickWins() {
6972
url: issue.url,
7073
createdAt: issue.created_at,
7174
updatedAt: issue.updated_at,
72-
author: issue.author.login,
73-
labels: issue.labels.map((l) => l.name),
75+
author: {
76+
login: issue.author.login,
77+
avatarUrl: issue.author.avatar_url,
78+
},
79+
labels: issue.labels.map((l) => ({ name: l.name, color: l.color })),
7480
daysOld: Math.floor(
7581
(Date.now() - new Date(issue.created_at).getTime()) /
7682
(1000 * 60 * 60 * 24)

src/lib/api/github-graphql-client.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ interface GitHubActionItem {
6464
url: string;
6565
repo: string;
6666
type: "issue" | "pullRequest";
67-
author: string;
67+
author: {
68+
login: string;
69+
avatarUrl: string;
70+
};
71+
labels: Array<{ name: string; color?: string }>;
6872
priority: "urgent" | "high" | "medium" | "low";
6973
daysOld: number;
7074
createdAt: string;
@@ -107,9 +111,10 @@ interface ActionItem {
107111
};
108112
author: {
109113
login: string;
114+
avatarUrl: string;
110115
} | null;
111116
labels: {
112-
nodes: Array<{ name: string }>;
117+
nodes: Array<{ name: string; color?: string }>;
113118
};
114119
comments: {
115120
totalCount: number;
@@ -129,12 +134,13 @@ interface PullRequest {
129134
};
130135
author: {
131136
login: string;
137+
avatarUrl: string;
132138
} | null;
133139
assignees: {
134140
nodes: Array<{ login: string }>;
135141
};
136142
labels: {
137-
nodes: Array<{ name: string }>;
143+
nodes: Array<{ name: string; color?: string }>;
138144
};
139145
comments: {
140146
totalCount: number;
@@ -499,10 +505,12 @@ class GitHubGraphQLClient {
499505
}
500506
author {
501507
login
508+
avatarUrl
502509
}
503510
labels(first: 10) {
504511
nodes {
505512
name
513+
color
506514
}
507515
}
508516
comments {
@@ -525,6 +533,7 @@ class GitHubGraphQLClient {
525533
}
526534
author {
527535
login
536+
avatarUrl
528537
}
529538
assignees(first: 10) {
530539
nodes {
@@ -534,6 +543,7 @@ class GitHubGraphQLClient {
534543
labels(first: 10) {
535544
nodes {
536545
name
546+
color
537547
}
538548
}
539549
comments {
@@ -562,10 +572,12 @@ class GitHubGraphQLClient {
562572
}
563573
author {
564574
login
575+
avatarUrl
565576
}
566577
labels(first: 10) {
567578
nodes {
568579
name
580+
color
569581
}
570582
}
571583
comments {
@@ -595,10 +607,12 @@ class GitHubGraphQLClient {
595607
}
596608
author {
597609
login
610+
avatarUrl
598611
}
599612
labels(first: 10) {
600613
nodes {
601614
name
615+
color
602616
}
603617
}
604618
comments {
@@ -618,10 +632,12 @@ class GitHubGraphQLClient {
618632
}
619633
author {
620634
login
635+
avatarUrl
621636
}
622637
labels(first: 10) {
623638
nodes {
624639
name
640+
color
625641
}
626642
}
627643
comments {
@@ -659,10 +675,12 @@ class GitHubGraphQLClient {
659675
}
660676
author {
661677
login
678+
avatarUrl
662679
}
663680
labels(first: 10) {
664681
nodes {
665682
name
683+
color
666684
}
667685
}
668686
comments {
@@ -773,7 +791,11 @@ class GitHubGraphQLClient {
773791
(Date.now() - new Date(item.createdAt).getTime()) / (1000 * 60 * 60 * 24)
774792
);
775793
const labels =
776-
item.labels?.nodes?.map((l: { name: string }) => l.name) || [];
794+
item.labels?.nodes?.map((l: { name: string; color?: string }) => ({
795+
name: l.name,
796+
color: l.color,
797+
})) || [];
798+
const labelNames = labels.map((l) => l.name);
777799

778800
const isPR = this.isPullRequest(item);
779801

@@ -783,8 +805,12 @@ class GitHubGraphQLClient {
783805
url: item.url,
784806
repo: item.repository.nameWithOwner,
785807
type: isPR ? "pullRequest" : "issue",
786-
author: item.author?.login || "unknown",
787-
priority: this.calculateActionPriority(labels, daysOld),
808+
author: {
809+
login: item.author?.login || "unknown",
810+
avatarUrl: item.author?.avatarUrl || "",
811+
},
812+
labels,
813+
priority: this.calculateActionPriority(labelNames, daysOld, mentionType),
788814
daysOld,
789815
createdAt: item.createdAt,
790816
updatedAt: item.updatedAt,
@@ -796,8 +822,13 @@ class GitHubGraphQLClient {
796822

797823
private calculateActionPriority(
798824
labels: string[],
799-
daysOld: number
825+
daysOld: number,
826+
mentionType?: "mention" | "review_request" | "comment"
800827
): "urgent" | "high" | "medium" | "low" {
828+
if (mentionType === "review_request") {
829+
return "urgent";
830+
}
831+
801832
const lowerLabels = labels.map((l) => l.toLowerCase());
802833

803834
if (

src/stores/actionItems.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ export interface ActionItem {
1313
createdAt: string;
1414
updatedAt: string;
1515
assignee?: string;
16-
author: string;
16+
author: {
17+
login: string;
18+
avatarUrl: string;
19+
};
20+
labels: Array<{ name: string; color?: string }>;
1721
daysOld: number;
1822
comments?: number;
1923
stars?: number;

0 commit comments

Comments
 (0)