From 806c69ca9cadf65ed5564a7d9b3da5420d00c14e Mon Sep 17 00:00:00 2001 From: "Felix T.J. Dietrich" Date: Sun, 15 Sep 2024 18:28:53 +0200 Subject: [PATCH] Restructure project and general improments (#91) --- webapp/src/app/app.component.ts | 2 +- webapp/src/app/app.routes.ts | 4 +- .../leaderboard/leaderboard.component.html | 57 ------- .../leaderboard/leaderboard.component.ts | 142 ------------------ .../leaderboard/leaderboard.stories.ts | 18 --- .../theme}/theme-switcher.component.html | 0 .../theme}/theme-switcher.component.ts | 0 .../theme}/theme-switcher.service.ts | 0 .../theme}/theme-switcher.stories.ts | 2 +- webapp/src/app/home/home.component.html | 11 ++ webapp/src/app/home/home.component.ts | 21 +++ webapp/src/app/home/home.stories.ts | 18 +++ .../leaderboard/leaderboard.component.html | 49 ++++++ .../home/leaderboard/leaderboard.component.ts | 42 ++++++ .../home/leaderboard/leaderboard.stories.ts | 69 +++++++++ webapp/src/app/main/main.component.html | 3 - webapp/src/app/main/main.component.ts | 10 -- 17 files changed, 214 insertions(+), 234 deletions(-) delete mode 100644 webapp/src/app/components/leaderboard/leaderboard.component.html delete mode 100644 webapp/src/app/components/leaderboard/leaderboard.component.ts delete mode 100644 webapp/src/app/components/leaderboard/leaderboard.stories.ts rename webapp/src/app/{components/theme-switcher => core/theme}/theme-switcher.component.html (100%) rename webapp/src/app/{components/theme-switcher => core/theme}/theme-switcher.component.ts (100%) rename webapp/src/app/{components/theme-switcher => core/theme}/theme-switcher.service.ts (100%) rename webapp/src/app/{components/theme-switcher => core/theme}/theme-switcher.stories.ts (94%) create mode 100644 webapp/src/app/home/home.component.html create mode 100644 webapp/src/app/home/home.component.ts create mode 100644 webapp/src/app/home/home.stories.ts create mode 100644 webapp/src/app/home/leaderboard/leaderboard.component.html create mode 100644 webapp/src/app/home/leaderboard/leaderboard.component.ts create mode 100644 webapp/src/app/home/leaderboard/leaderboard.stories.ts delete mode 100644 webapp/src/app/main/main.component.html delete mode 100644 webapp/src/app/main/main.component.ts diff --git a/webapp/src/app/app.component.ts b/webapp/src/app/app.component.ts index 41c404cf..eb7377c8 100644 --- a/webapp/src/app/app.component.ts +++ b/webapp/src/app/app.component.ts @@ -2,7 +2,7 @@ import { Component, isDevMode } from '@angular/core'; import { AngularQueryDevtools } from '@tanstack/angular-query-devtools-experimental'; import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router'; import { LucideAngularModule, Hammer } from 'lucide-angular'; -import { ThemeSwitcherComponent } from './components/theme-switcher/theme-switcher.component'; +import { ThemeSwitcherComponent } from 'app/core/theme/theme-switcher.component'; @Component({ selector: 'app-root', diff --git a/webapp/src/app/app.routes.ts b/webapp/src/app/app.routes.ts index 9060460d..4ddba63d 100644 --- a/webapp/src/app/app.routes.ts +++ b/webapp/src/app/app.routes.ts @@ -1,8 +1,8 @@ import { Routes } from '@angular/router'; import { AboutComponent } from 'app/about/about.component'; -import { MainComponent } from 'app/main/main.component'; +import { HomeComponent } from 'app/home/home.component'; export const routes: Routes = [ - { path: '', component: MainComponent }, + { path: '', component: HomeComponent }, { path: 'about', component: AboutComponent } ]; diff --git a/webapp/src/app/components/leaderboard/leaderboard.component.html b/webapp/src/app/components/leaderboard/leaderboard.component.html deleted file mode 100644 index 04815e8a..00000000 --- a/webapp/src/app/components/leaderboard/leaderboard.component.html +++ /dev/null @@ -1,57 +0,0 @@ -
-

Artemis Leaderboard

- @if (query.isPending()) { - Data is loading... - } @else if (query.error()) { - An error has occurred - } - - @if (leaderboard(); as leaderboard) { -
- - - - Rank - Contributor - Score - Activity - - - - @for (entry of leaderboard; track entry.githubName) { - - {{ entry.rank }} - - - - {{ entry.name }} - - - {{ entry.score }} - - @if (entry.changesRequested && entry.changesRequested > 0) { -
- - {{ entry.changesRequested }} -
- } - @if (entry.approvals && entry.approvals > 0) { -
- - {{ entry.approvals }} -
- } - @if (entry.comments && entry.comments > 0) { -
- - {{ entry.comments }} -
- } - - - } - -
-
- } -
diff --git a/webapp/src/app/components/leaderboard/leaderboard.component.ts b/webapp/src/app/components/leaderboard/leaderboard.component.ts deleted file mode 100644 index 24757f6f..00000000 --- a/webapp/src/app/components/leaderboard/leaderboard.component.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core'; -import { injectQuery } from '@tanstack/angular-query-experimental'; -import { NgIconComponent } from '@ng-icons/core'; -import { octFileDiff, octCheck, octComment } from '@ng-icons/octicons'; -import { LeaderboardEntry, LeaderboardService } from 'app/core/modules/openapi'; -import { TableBodyDirective } from 'app/ui/table/table-body.directive'; -import { TableCaptionDirective } from 'app/ui/table/table-caption.directive'; -import { TableCellDirective } from 'app/ui/table/table-cell.directive'; -import { TableFooterDirective } from 'app/ui/table/table-footer.directive'; -import { TableHeadDirective } from 'app/ui/table/table-head.directive'; -import { TableHeaderDirective } from 'app/ui/table/table-header.directive'; -import { TableRowDirective } from 'app/ui/table/table-row.directive'; -import { TableComponent } from 'app/ui/table/table.component'; -import { lastValueFrom } from 'rxjs'; - -const defaultData: LeaderboardEntry[] = [ - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'I', - score: 90, - changesRequested: 0, - approvals: 0, - comments: 0 - }, - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'A', - score: 10, - changesRequested: 1, - approvals: 0, - comments: 0 - }, - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'B', - score: 20, - changesRequested: 0, - approvals: 1, - comments: 0 - }, - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'C', - score: 30, - changesRequested: 0, - approvals: 0, - comments: 1 - }, - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'D', - score: 40, - changesRequested: 0, - approvals: 0, - comments: 0 - }, - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'E', - score: 50, - changesRequested: 0, - approvals: 0, - comments: 0 - }, - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'F', - score: 60, - changesRequested: 0, - approvals: 0, - comments: 0 - }, - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'G', - score: 70, - changesRequested: 0, - approvals: 0, - comments: 0 - }, - { - githubName: 'shadcn', - avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', - type: LeaderboardEntry.TypeEnum.User, - name: 'H', - score: 80, - changesRequested: 0, - approvals: 0, - comments: 0 - } -]; - -@Component({ - selector: 'app-leaderboard', - standalone: true, - imports: [ - TableComponent, - TableBodyDirective, - TableCaptionDirective, - TableCellDirective, - TableFooterDirective, - TableHeaderDirective, - TableHeadDirective, - TableRowDirective, - NgIconComponent - ], - templateUrl: './leaderboard.component.html', - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class LeaderboardComponent { - protected octFileDiff = octFileDiff; - protected octCheck = octCheck; - protected octComment = octComment; - - leaderboardService = inject(LeaderboardService); - - query = injectQuery(() => ({ - queryKey: ['leaderboard'], - queryFn: async () => lastValueFrom(this.leaderboardService.getLeaderboard()), - gcTime: Infinity - })); - - leaderboard = computed(() => { - return this.query.data() ?? defaultData; - }); -} diff --git a/webapp/src/app/components/leaderboard/leaderboard.stories.ts b/webapp/src/app/components/leaderboard/leaderboard.stories.ts deleted file mode 100644 index 421fb862..00000000 --- a/webapp/src/app/components/leaderboard/leaderboard.stories.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { type Meta, type StoryObj } from '@storybook/angular'; -import { LeaderboardComponent } from './leaderboard.component'; - -const meta: Meta = { - title: 'Components/Leaderboard', - component: LeaderboardComponent, - tags: ['autodocs'] -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - render: (args) => ({ - props: args, - template: `` - }) -}; diff --git a/webapp/src/app/components/theme-switcher/theme-switcher.component.html b/webapp/src/app/core/theme/theme-switcher.component.html similarity index 100% rename from webapp/src/app/components/theme-switcher/theme-switcher.component.html rename to webapp/src/app/core/theme/theme-switcher.component.html diff --git a/webapp/src/app/components/theme-switcher/theme-switcher.component.ts b/webapp/src/app/core/theme/theme-switcher.component.ts similarity index 100% rename from webapp/src/app/components/theme-switcher/theme-switcher.component.ts rename to webapp/src/app/core/theme/theme-switcher.component.ts diff --git a/webapp/src/app/components/theme-switcher/theme-switcher.service.ts b/webapp/src/app/core/theme/theme-switcher.service.ts similarity index 100% rename from webapp/src/app/components/theme-switcher/theme-switcher.service.ts rename to webapp/src/app/core/theme/theme-switcher.service.ts diff --git a/webapp/src/app/components/theme-switcher/theme-switcher.stories.ts b/webapp/src/app/core/theme/theme-switcher.stories.ts similarity index 94% rename from webapp/src/app/components/theme-switcher/theme-switcher.stories.ts rename to webapp/src/app/core/theme/theme-switcher.stories.ts index 3f00cdb2..a524cd0c 100644 --- a/webapp/src/app/components/theme-switcher/theme-switcher.stories.ts +++ b/webapp/src/app/core/theme/theme-switcher.stories.ts @@ -4,7 +4,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; // More on how to set up stories at: https://storybook.js.org/docs/writing-stories const meta: Meta = { - title: 'Components/ThemeSwitcher', + title: 'Components/Core/ThemeSwitcher', component: ThemeSwitcherComponent, tags: ['autodocs'], decorators: [ diff --git a/webapp/src/app/home/home.component.html b/webapp/src/app/home/home.component.html new file mode 100644 index 00000000..470f42fb --- /dev/null +++ b/webapp/src/app/home/home.component.html @@ -0,0 +1,11 @@ +
+

Artemis Leaderboard

+ @if (query.isPending()) { + Data is loading... + } @else if (query.error()) { + An error has occurred + } + @if (query.data()) { + + } +
diff --git a/webapp/src/app/home/home.component.ts b/webapp/src/app/home/home.component.ts new file mode 100644 index 00000000..fe173d4d --- /dev/null +++ b/webapp/src/app/home/home.component.ts @@ -0,0 +1,21 @@ +import { Component, inject } from '@angular/core'; +import { injectQuery } from '@tanstack/angular-query-experimental'; +import { LeaderboardService } from 'app/core/modules/openapi/api/leaderboard.service'; +import { LeaderboardComponent } from 'app/home/leaderboard/leaderboard.component'; +import { lastValueFrom } from 'rxjs'; + +@Component({ + selector: 'app-home', + standalone: true, + imports: [LeaderboardComponent], + templateUrl: './home.component.html' +}) +export class HomeComponent { + leaderboardService = inject(LeaderboardService); + + query = injectQuery(() => ({ + queryKey: ['leaderboard'], + queryFn: async () => lastValueFrom(this.leaderboardService.getLeaderboard()), + gcTime: Infinity + })); +} diff --git a/webapp/src/app/home/home.stories.ts b/webapp/src/app/home/home.stories.ts new file mode 100644 index 00000000..d57e1d07 --- /dev/null +++ b/webapp/src/app/home/home.stories.ts @@ -0,0 +1,18 @@ +import { type Meta, type StoryObj } from '@storybook/angular'; +import { HomeComponent } from './home.component'; + +const meta: Meta = { + title: 'Pages/Home', + component: HomeComponent, + tags: ['autodocs'] +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: (args) => ({ + props: args, + template: `` + }) +}; diff --git a/webapp/src/app/home/leaderboard/leaderboard.component.html b/webapp/src/app/home/leaderboard/leaderboard.component.html new file mode 100644 index 00000000..af9a5c8d --- /dev/null +++ b/webapp/src/app/home/leaderboard/leaderboard.component.html @@ -0,0 +1,49 @@ + + + + Rank + Contributor + Score + Activity + + + + @for (entry of leaderboard(); track entry.githubName) { + + {{ entry.rank }} + + + + + + {{ entry.name?.slice(0, 1)?.toUpperCase() }} + + + {{ entry.name }} + + + {{ entry.score }} + + @if (entry.changesRequested && entry.changesRequested > 0) { +
+ + {{ entry.changesRequested }} +
+ } + @if (entry.approvals && entry.approvals > 0) { +
+ + {{ entry.approvals }} +
+ } + @if (entry.comments && entry.comments > 0) { +
+ + {{ entry.comments }} +
+ } + + + } + +
diff --git a/webapp/src/app/home/leaderboard/leaderboard.component.ts b/webapp/src/app/home/leaderboard/leaderboard.component.ts new file mode 100644 index 00000000..3feb3dc8 --- /dev/null +++ b/webapp/src/app/home/leaderboard/leaderboard.component.ts @@ -0,0 +1,42 @@ +import { Component, input } from '@angular/core'; +import { NgIconComponent } from '@ng-icons/core'; +import { octFileDiff, octCheck, octComment } from '@ng-icons/octicons'; +import { LeaderboardEntry } from 'app/core/modules/openapi'; +import { AvatarFallbackComponent } from 'app/ui/avatar/avatar-fallback.component'; +import { AvatarImageComponent } from 'app/ui/avatar/avatar-image.component'; +import { AvatarComponent } from 'app/ui/avatar/avatar.component'; +import { TableBodyDirective } from 'app/ui/table/table-body.directive'; +import { TableCaptionDirective } from 'app/ui/table/table-caption.directive'; +import { TableCellDirective } from 'app/ui/table/table-cell.directive'; +import { TableFooterDirective } from 'app/ui/table/table-footer.directive'; +import { TableHeadDirective } from 'app/ui/table/table-head.directive'; +import { TableHeaderDirective } from 'app/ui/table/table-header.directive'; +import { TableRowDirective } from 'app/ui/table/table-row.directive'; +import { TableComponent } from 'app/ui/table/table.component'; + +@Component({ + selector: 'app-leaderboard', + standalone: true, + imports: [ + AvatarComponent, + AvatarFallbackComponent, + AvatarImageComponent, + TableComponent, + TableBodyDirective, + TableCaptionDirective, + TableCellDirective, + TableFooterDirective, + TableHeaderDirective, + TableHeadDirective, + TableRowDirective, + NgIconComponent + ], + templateUrl: './leaderboard.component.html' +}) +export class LeaderboardComponent { + protected octFileDiff = octFileDiff; + protected octCheck = octCheck; + protected octComment = octComment; + + leaderboard = input(); +} diff --git a/webapp/src/app/home/leaderboard/leaderboard.stories.ts b/webapp/src/app/home/leaderboard/leaderboard.stories.ts new file mode 100644 index 00000000..c3047a25 --- /dev/null +++ b/webapp/src/app/home/leaderboard/leaderboard.stories.ts @@ -0,0 +1,69 @@ +import { argsToTemplate, type Meta, type StoryObj } from '@storybook/angular'; +import { LeaderboardComponent } from './leaderboard.component'; +import { LeaderboardEntry } from 'app/core/modules/openapi/model/leaderboard-entry'; + +const leaderboardEntries: LeaderboardEntry[] = [ + { + githubName: 'GODrums', + avatarUrl: 'https://avatars.githubusercontent.com/u/21990230?v=4', + type: LeaderboardEntry.TypeEnum.User, + name: 'Armin Stanitzok', + score: 100, + changesRequested: 3, + approvals: 5, + comments: 1, + rank: 1 + }, + { + githubName: 'FelixTJDietrich', + avatarUrl: 'https://avatars.githubusercontent.com/u/5898705?v=4', + type: LeaderboardEntry.TypeEnum.User, + name: 'Felix T.J. Dietrich', + score: 90, + changesRequested: 1, + approvals: 1, + comments: 14, + rank: 2 + }, + { + githubName: 'krusche', + avatarUrl: 'https://avatars.githubusercontent.com/u/744067?v=4', + type: LeaderboardEntry.TypeEnum.User, + name: 'Stephan Krusche', + score: 50, + changesRequested: 0, + approvals: 3, + comments: 1, + rank: 3 + }, + { + githubName: 'shadcn', + avatarUrl: 'https://avatars.githubusercontent.com/u/124599?v=4', + type: LeaderboardEntry.TypeEnum.User, + name: 'shadcn', + score: 20, + changesRequested: 0, + approvals: 0, + comments: 1, + rank: 4 + } +]; + +const meta: Meta = { + title: 'Components/Home/Leaderboard', + component: LeaderboardComponent, + tags: ['autodocs'], + args: { + leaderboard: leaderboardEntries + } +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: (args) => ({ + props: args, + template: `` + }) +}; diff --git a/webapp/src/app/main/main.component.html b/webapp/src/app/main/main.component.html deleted file mode 100644 index 9be02e9a..00000000 --- a/webapp/src/app/main/main.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/webapp/src/app/main/main.component.ts b/webapp/src/app/main/main.component.ts deleted file mode 100644 index b7da7157..00000000 --- a/webapp/src/app/main/main.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { LeaderboardComponent } from 'app/components/leaderboard/leaderboard.component'; - -@Component({ - selector: 'app-main', - standalone: true, - imports: [LeaderboardComponent], - templateUrl: './main.component.html' -}) -export class MainComponent {}