Skip to content

Commit

Permalink
create activity dashboard visualizing pull requests and detected bad …
Browse files Browse the repository at this point in the history
…practices(#199)
  • Loading branch information
iam-flo committed Dec 3, 2024
1 parent cf6c6e7 commit 4f1f7c1
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 1 deletion.
4 changes: 3 additions & 1 deletion webapp/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ImprintComponent } from '@app/legal/imprint.component';
import { PrivacyComponent } from '@app/legal/privacy.component';
import { AdminGuard } from '@app/core/security/admin.guard';
import { AuthGuard } from '@app/core/security/auth.guard';
import { ActivityDashboardComponent } from '@app/home/activity/activity-dashboard.component';

export const routes: Routes = [
// Public routes
Expand Down Expand Up @@ -47,7 +48,8 @@ export const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'user/:id', component: UserProfileComponent },
{ path: 'settings', component: SettingsComponent },
{ path: 'workspace', component: WorkspaceComponent, canActivate: [AdminGuard] }
{ path: 'workspace', component: WorkspaceComponent, canActivate: [AdminGuard] },
{ path: 'activity/:id', component: ActivityDashboardComponent }
]
}
];
61 changes: 61 additions & 0 deletions webapp/src/app/home/activity/activity-dashboard.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<div class="flex flex-col items-center">
<div class="">
<div class="grid grid-cols-1 xl:grid-cols-5 gap-y-4 xl:gap-8">
<div class="space-y-2 col-span-1">
<div class="flex flex-col gap-2 mb-4">
<h1 class="text-xl font-semibold">Activities</h1>
<p>
You currently have <span class="font-semibold">{{ numberOfPullRequests() }}</span> open pull requests and <span class="font-semibold">{{ numberOfBadPractices() }}</span> detected bad

Check failure on line 8 in webapp/src/app/home/activity/activity-dashboard.component.html

View workflow job for this annotation

GitHub Actions / Code Quality Checks

Replace `·<span·class="font-semibold">{{·numberOfBadPractices()·}}</span>·detected·bad⏎···········` with `⏎············<span·class="font-semibold">{{·numberOfBadPractices()·}}</span>·detected·bad`
practices.
</p>
</div>
</div>
<div class="col-span-2">
<div class="flex flex-col justify-between">
<h1 class="text-xl font-semibold">Your open pull requests</h1>
<div class="flex flex-col gap-2 m-1 mr-3">
@if (query.data()?.pullRequests) {
@for (pullRequest of query.data()?.pullRequests; track pullRequest.id) {
<app-issue-card
class="w-full"
[title]="pullRequest.title"
[number]="pullRequest.number"
[additions]="pullRequest.additions"
[deletions]="pullRequest.deletions"
[htmlUrl]="pullRequest.htmlUrl"
[repositoryName]="pullRequest.repository?.name"
[createdAt]="pullRequest.createdAt"
[state]="pullRequest.state"
[isDraft]="pullRequest.isDraft"
[isMerged]="pullRequest.isMerged"
[pullRequestLabels]="pullRequest.labels"
>
</app-issue-card>
}
}
</div>
</div>
</div>
<div class="col-span-2">
<div class="flex flex-col justify-between">
<h1 class="text-xl font-semibold">Detected bad practices</h1>
<div class="flex flex-col gap-2 m-1 mr-3">
@if (query.data()?.pullRequests) {
@for (pullRequest of query.data()?.pullRequests; track pullRequest.id) {
@for (badPractice of pullRequest.badPractices; track badPractice.title) {
<app-bad-practice-card
[title]="badPractice.title"
[description]="badPractice.description"
[repositoryName]="pullRequest.repository?.name"
[number]="pullRequest.number"
>
</app-bad-practice-card>
}
}
}
</div>
</div>
</div>
</div>
</div>
</div>
32 changes: 32 additions & 0 deletions webapp/src/app/home/activity/activity-dashboard.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Component, computed, inject } from '@angular/core';
import { ActivityService } from '@app/core/modules/openapi';
import { injectQuery } from '@tanstack/angular-query-experimental';
import { combineLatest, lastValueFrom, map, timer } from 'rxjs';
import { ActivatedRoute } from '@angular/router';
import { IssueCardComponent } from '@app/user/issue-card/issue-card.component';
import { BadPracticeCardComponent } from '@app/user/bad-practice-card/bad-practice-card.component';

@Component({
selector: 'app-activity-dashboard',
standalone: true,
imports: [IssueCardComponent, BadPracticeCardComponent],
templateUrl: './activity-dashboard.component.html',
styles: ``
})
export class ActivityDashboardComponent {
activityService = inject(ActivityService);

protected userLogin: string | null = null;
protected numberOfPullRequests = computed(() => this.query.data()?.pullRequests?.length ?? 0);
protected numberOfBadPractices = computed(() => this.query.data()?.pullRequests?.reduce((acc, pr) => acc + (pr.badPractices?.length ?? 0), 0) ?? 0);

constructor(private route: ActivatedRoute) {
this.userLogin = this.route.snapshot.paramMap.get('id');
}

query = injectQuery(() => ({
queryKey: ['user', { id: this.userLogin }],
enabled: !!this.userLogin,
queryFn: async () => lastValueFrom(combineLatest([this.activityService.getActivityByUser(this.userLogin!), timer(400)]).pipe(map(([activity]) => activity)))
}));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<a hlmCard variant="profile" class="block p-4 border rounded-lg shadow-sm">
<div hlmCardContent variant="profile">
<p class="text-xs font-medium text-github-muted-foreground">{{ repositoryName() }} #{{ number() }}</p>
<h1 class="text-lg font-semibold">{{ title() }}</h1>
<div class="text-sm">{{ description() }}</div>
</div>
</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component, input } from '@angular/core';
import { HlmCardModule } from '@spartan-ng/ui-card-helm';

@Component({
selector: 'app-bad-practice-card',
standalone: true,
imports: [HlmCardModule],
templateUrl: './bad-practice-card.component.html',
styles: ``
})
export class BadPracticeCardComponent {
title = input<string>();
description = input<string>();
repositoryName = input<string>();
number = input<number>();
}
27 changes: 27 additions & 0 deletions webapp/src/app/user/bad-practice-card/bad-practice-card.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Meta, StoryObj } from '@storybook/angular';
import { BadPracticeCardComponent } from './bad-practice-card.component';

const meta: Meta<BadPracticeCardComponent> = {
component: BadPracticeCardComponent,
tags: ['autodocs'] // Auto-generate docs if enabled
};

export default meta;

type Story = StoryObj<BadPracticeCardComponent>;

export const Default: Story = {
args: {
title: 'Avoid using any type',
description: 'Using the any type defeats the purpose of TypeScript.',
repositoryName: 'Hepheastus',
number: 200
}
};
/*
export const isLoading: Story = {
args: {
title: 'Avoid using any type',
description: 'Using the any type defeats the purpose of TypeScript.'
}
};*/

0 comments on commit 4f1f7c1

Please sign in to comment.