From 78b426efd8e20341d69bf8a81cc1143a49b5ed9c Mon Sep 17 00:00:00 2001 From: Florian Ehrenstorfer Date: Mon, 23 Sep 2024 15:14:48 +0200 Subject: [PATCH] #82: rename, add colors for icons, refactor story --- webapp/package-lock.json | 7 +++ webapp/package.json | 1 + .../core/IssueCard/issue-card.component.html | 37 +++++++++++++ .../core/IssueCard/issue-card.component.ts | 41 +++++++++++++++ .../app/core/IssueCard/issue-card.stories.ts | 40 ++++++++++++++ .../app-issue-card.component.html | 31 ----------- .../app-issue-card.component.ts | 30 ----------- .../app-issue-card/app-issue-card.stories.ts | 52 ------------------- 8 files changed, 126 insertions(+), 113 deletions(-) create mode 100644 webapp/src/app/core/IssueCard/issue-card.component.html create mode 100644 webapp/src/app/core/IssueCard/issue-card.component.ts create mode 100644 webapp/src/app/core/IssueCard/issue-card.stories.ts delete mode 100644 webapp/src/app/ui/app-issue-card/app-issue-card.component.html delete mode 100644 webapp/src/app/ui/app-issue-card/app-issue-card.component.ts delete mode 100644 webapp/src/app/ui/app-issue-card/app-issue-card.stories.ts diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 42280e4f..3a1e52f2 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -24,6 +24,7 @@ "autoprefixer": "10.4.20", "class-variance-authority": "0.7.0", "clsx": "2.1.1", + "dayjs": "^1.11.13", "lucide-angular": "0.429.0", "postcss": "8.4.41", "rxjs": "7.8.1", @@ -9136,6 +9137,12 @@ "node": ">=4.0" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", diff --git a/webapp/package.json b/webapp/package.json index cb31cc2e..db4e66e3 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -36,6 +36,7 @@ "autoprefixer": "10.4.20", "class-variance-authority": "0.7.0", "clsx": "2.1.1", + "dayjs": "^1.11.13", "lucide-angular": "0.429.0", "postcss": "8.4.41", "rxjs": "7.8.1", diff --git a/webapp/src/app/core/IssueCard/issue-card.component.html b/webapp/src/app/core/IssueCard/issue-card.component.html new file mode 100644 index 00000000..a966e74d --- /dev/null +++ b/webapp/src/app/core/IssueCard/issue-card.component.html @@ -0,0 +1,37 @@ +
+
+ + @if (state() === 'OPEN') { + + } @else { + + } + + {{ repositoryName() }} #{{ number() }} on {{ createdAt().format('MMM D') }} + + + +{{ additions() }} + -{{ deletions() }} + +
+ +
+ {{ title() }} + @if (getMostRecentReview(); as review) { + @if (review.state === 'APPROVED') { + + } @else if (review.state === 'DISMISSED') { + + } @else if (review.state === 'COMMENTED') { + + } @else { + + } + } +
+
+ @for (label of pullRequestLabels(); track label.name) { + {{ label.name }} + } +
+
diff --git a/webapp/src/app/core/IssueCard/issue-card.component.ts b/webapp/src/app/core/IssueCard/issue-card.component.ts new file mode 100644 index 00000000..e4fedf96 --- /dev/null +++ b/webapp/src/app/core/IssueCard/issue-card.component.ts @@ -0,0 +1,41 @@ +import { Component, input } from '@angular/core'; +import { PullRequestLabel, PullRequestReview } from '@app/core/modules/openapi'; +import { NgIcon } from '@ng-icons/core'; +import { octCheck, octComment, octFileDiff, octGitPullRequest, octGitPullRequestClosed, octX } from '@ng-icons/octicons'; +import { Dayjs } from 'dayjs'; +import { NgStyle } from '@angular/common'; + +@Component({ + selector: 'app-issue-card', + templateUrl: './issue-card.component.html', + imports: [NgIcon, NgStyle], + standalone: true +}) +export class IssueCardComponent { + title = input.required(); + number = input.required(); + additions = input.required(); + deletions = input.required(); + url = input.required(); + repositoryName = input.required(); + reviews = input.required>(); + createdAt = input.required(); + state = input.required(); + pullRequestLabels = input.required>(); + protected readonly octCheck = octCheck; + protected readonly octX = octX; + protected readonly octComment = octComment; + protected readonly octGitPullRequest = octGitPullRequest; + protected readonly octFileDiff = octFileDiff; + protected readonly octGitPullRequestClosed = octGitPullRequestClosed; + + getMostRecentReview() { + return Array.from(this.reviews() || []).reduce((latest: PullRequestReview, review: PullRequestReview) => { + return new Date(review.updatedAt || 0) > new Date(latest.updatedAt || 0) ? review : latest; + }); + } + + openIssue() { + window.open(this.url()); + } +} diff --git a/webapp/src/app/core/IssueCard/issue-card.stories.ts b/webapp/src/app/core/IssueCard/issue-card.stories.ts new file mode 100644 index 00000000..54b2d620 --- /dev/null +++ b/webapp/src/app/core/IssueCard/issue-card.stories.ts @@ -0,0 +1,40 @@ +import { Meta, StoryObj } from '@storybook/angular'; +import { IssueCardComponent } from './issue-card.component'; +import dayjs from 'dayjs'; + +const meta: Meta = { + title: 'Component/IssueCard', + component: IssueCardComponent, + tags: ['autodocs'] // Auto-generate docs if enabled +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + title: 'Add feature X', + number: 12, + additions: 10, + deletions: 5, + url: 'http://example.com', + state: 'OPEN', + repositoryName: 'Artemis', + createdAt: dayjs('Jan 1'), + pullRequestLabels: [ + { name: 'bug', color: 'red' }, + { name: 'enhancement', color: 'green' } + ], + reviews: [ + { + state: 'APPROVED', + updatedAt: 'Jan 2' + }, + { + state: 'CHANGES_REQUESTED', + updatedAt: 'Jan 4' + } + ] + } +}; diff --git a/webapp/src/app/ui/app-issue-card/app-issue-card.component.html b/webapp/src/app/ui/app-issue-card/app-issue-card.component.html deleted file mode 100644 index 931bbaa2..00000000 --- a/webapp/src/app/ui/app-issue-card/app-issue-card.component.html +++ /dev/null @@ -1,31 +0,0 @@ -
-
- - {{ pullRequest().repository?.name }} #{{ pullRequest().number }} on {{ pullRequest().createdAt }} - - - +{{ pullRequest().additions }} - -{{ pullRequest().deletions }} - -
- -
- {{ pullRequest().title }} - @if (getMostRecentReview(); as review) { - @if (review.state === 'APPROVED') { - - } @else if (review.state === 'DISMISSED') { - - } @else if (review.state === 'COMMENTED') { - - } @else { - - } - } -
-
- @for (label of pullRequest().pullRequestLabels; track label.name) { - {{ label.name }} - } -
-
diff --git a/webapp/src/app/ui/app-issue-card/app-issue-card.component.ts b/webapp/src/app/ui/app-issue-card/app-issue-card.component.ts deleted file mode 100644 index 75c93950..00000000 --- a/webapp/src/app/ui/app-issue-card/app-issue-card.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Component, input } from '@angular/core'; -import { PullRequest, PullRequestReview } from '@app/core/modules/openapi'; -import { NgIcon } from '@ng-icons/core'; -import { octCheck, octComment, octFileDiff, octGitPullRequest, octX } from '@ng-icons/octicons'; - -@Component({ - selector: 'app-issue-card', - templateUrl: './app-issue-card.component.html', - imports: [NgIcon], - standalone: true -}) -export class AppIssueCardComponent { - pullRequest = input.required(); - protected readonly octCheck = octCheck; - protected readonly octX = octX; - protected readonly octComment = octComment; - protected readonly octGitPullRequest = octGitPullRequest; - - getMostRecentReview() { - if (!this.pullRequest() || !this.pullRequest().reviews) { - return null; - } - - return Array.from(this.pullRequest().reviews || []).reduce((latest: PullRequestReview, review: PullRequestReview) => { - return new Date(review.updatedAt || 0) > new Date(latest.updatedAt || 0) ? review : latest; - }); - } - - protected readonly octFileDiff = octFileDiff; -} diff --git a/webapp/src/app/ui/app-issue-card/app-issue-card.stories.ts b/webapp/src/app/ui/app-issue-card/app-issue-card.stories.ts deleted file mode 100644 index 8e5f0eac..00000000 --- a/webapp/src/app/ui/app-issue-card/app-issue-card.stories.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Meta, StoryObj } from '@storybook/angular'; -import { AppIssueCardComponent } from './app-issue-card.component'; -import { PullRequest, PullRequestReview, Repository } from '@app/core/modules/openapi'; - -const meta: Meta = { - title: 'UI/AppIssueCard', - component: AppIssueCardComponent, - tags: ['autodocs'] // Auto-generate docs if enabled -}; - -export default meta; - -type Story = StoryObj; - -const repo: Repository = { - name: 'Artemis', - nameWithOwner: 'artemis-education/artemis', - defaultBranch: 'master', - visibility: 'PUBLIC', - url: 'http://example.com' -}; - -const reviews = new Set([ - { - state: 'APPROVED', - updatedAt: 'Jan 2' - }, - { - state: 'CHANGES_REQUESTED', - updatedAt: 'Jan 4' - } -]); - -const pullRequest: PullRequest = { - title: 'Add feature X', - number: 12, - additions: 10, - deletions: 5, - url: 'http://example.com', - state: 'OPEN', - repository: repo, - createdAt: 'Jan 1', - pullRequestLabels: new Set([ - { name: 'bug', color: 'red' }, - { name: 'enhancement', color: 'green' } - ]), - reviews: reviews -}; - -export const Default: Story = { - args: { pullRequest } -};