From b3101720e9bca0aa99d85bbbafbfa0973753e9eb Mon Sep 17 00:00:00 2001 From: Nereus Ng Wei Bin Date: Tue, 19 Mar 2024 01:50:06 +0800 Subject: [PATCH 1/4] Refactor Milestone model to implement Group --- src/app/core/models/milestone.model.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/app/core/models/milestone.model.ts b/src/app/core/models/milestone.model.ts index 8f90e505..87421e11 100644 --- a/src/app/core/models/milestone.model.ts +++ b/src/app/core/models/milestone.model.ts @@ -1,7 +1,9 @@ +import { Group } from './github/group.interface'; + /** * Represents a milestone and its attributes fetched from Github. */ -export class Milestone { +export class Milestone implements Group { static DefaultMilestone: Milestone = new Milestone({ title: 'Without a milestone', state: null }); title: string; state: string; @@ -11,7 +13,10 @@ export class Milestone { this.state = milestone.state; } - public equals(milestone: Milestone) { - return this.title === milestone.title; + public equals(other: any) { + if (!(other instanceof Milestone)) { + return false; + } + return this.title === other.title; } } From 567c9a39c93c6134485bd2c2f87b6bd26e38d17b Mon Sep 17 00:00:00 2001 From: Nereus Ng Wei Bin Date: Tue, 19 Mar 2024 01:50:24 +0800 Subject: [PATCH 2/4] Implement MilestoneGroupingStrategy --- .../milestone-grouping-strategy.service.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/app/core/services/grouping/milestone-grouping-strategy.service.ts diff --git a/src/app/core/services/grouping/milestone-grouping-strategy.service.ts b/src/app/core/services/grouping/milestone-grouping-strategy.service.ts new file mode 100644 index 00000000..b75b808d --- /dev/null +++ b/src/app/core/services/grouping/milestone-grouping-strategy.service.ts @@ -0,0 +1,43 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Issue } from '../../models/issue.model'; +import { Milestone } from '../../models/milestone.model'; +import { MilestoneService } from '../milestone.service'; +import { GroupingStrategy } from './grouping-strategy.interface'; + +/** + * A GroupingStrategy that groups issues/prs based on their milestones. + */ +@Injectable({ + providedIn: 'root' +}) +export class MilestoneGroupingStrategy implements GroupingStrategy { + constructor(private milestoneService: MilestoneService) {} + + /** + * Retrieves data for a milestone. + */ + getDataForGroup(issues: Issue[], key: Milestone): Issue[] { + return issues.filter((issue) => issue.milestone.equals(key)); + } + + /** + * Retrieves an Observable emitting milestones available for grouping issues. + */ + getGroups(): Observable { + return this.milestoneService.fetchMilestones().pipe( + map((milestones) => { + return this.milestoneService.parseMilestoneData(milestones); + }) + ); + } + + /** + * Groups other than Default Milestone need to be shown on the + * hidden group list if empty. + */ + isInHiddenList(group: Milestone): boolean { + return group !== Milestone.DefaultMilestone; + } +} From 7c9c4f27ca72b874990c5687f9452a1415538e8c Mon Sep 17 00:00:00 2001 From: Nereus Ng Wei Bin Date: Tue, 19 Mar 2024 01:50:52 +0800 Subject: [PATCH 3/4] Include MilestoneGrouping in GroupingContext --- src/app/core/services/grouping/grouping-context.service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/core/services/grouping/grouping-context.service.ts b/src/app/core/services/grouping/grouping-context.service.ts index de2b355b..17b1ecf9 100644 --- a/src/app/core/services/grouping/grouping-context.service.ts +++ b/src/app/core/services/grouping/grouping-context.service.ts @@ -4,9 +4,11 @@ import { Group } from '../../models/github/group.interface'; import { Issue } from '../../models/issue.model'; import { AssigneeGroupingStrategy } from './assignee-grouping-strategy.service'; import { GroupingStrategy } from './grouping-strategy.interface'; +import { MilestoneGroupingStrategy } from './milestone-grouping-strategy.service'; export enum GroupBy { - Assignee = 'assignee' + Assignee = 'assignee', + Milestone = 'milestone' } export const DEFAULT_GROUPBY = GroupBy.Assignee; @@ -33,6 +35,7 @@ export class GroupingContextService { // Initialize the grouping strategy map with available strategies this.groupingStrategyMap.set(GroupBy.Assignee, this.injector.get(AssigneeGroupingStrategy)); + this.groupingStrategyMap.set(GroupBy.Milestone, this.injector.get(MilestoneGroupingStrategy)); } /** From ed0fc338a6711c02a17876cfb712ccbea90766e0 Mon Sep 17 00:00:00 2001 From: Nereus Ng Wei Bin Date: Tue, 19 Mar 2024 01:51:10 +0800 Subject: [PATCH 4/4] Add template for milestone grouping --- .../card-view/card-view.component.html | 13 +++++++++++++ .../issues-viewer/card-view/card-view.component.ts | 3 +++ .../hidden-groups/hidden-groups.component.html | 8 ++++++++ .../hidden-groups/hidden-groups.component.ts | 3 +++ 4 files changed, 27 insertions(+) diff --git a/src/app/issues-viewer/card-view/card-view.component.html b/src/app/issues-viewer/card-view/card-view.component.html index 65d78bf1..40770db3 100644 --- a/src/app/issues-viewer/card-view/card-view.component.html +++ b/src/app/issues-viewer/card-view/card-view.component.html @@ -48,3 +48,16 @@ + + +
+ + + + {{ milestone.title }} + +
{{ this.issues.count }}
+
+
+
+
diff --git a/src/app/issues-viewer/card-view/card-view.component.ts b/src/app/issues-viewer/card-view/card-view.component.ts index 813911db..041caff7 100644 --- a/src/app/issues-viewer/card-view/card-view.component.ts +++ b/src/app/issues-viewer/card-view/card-view.component.ts @@ -36,6 +36,7 @@ export class CardViewComponent implements OnInit, AfterViewInit, OnDestroy, Filt @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; @ViewChild('defaultHeader') defaultHeaderTemplate: TemplateRef; @ViewChild('assigneeHeader') assigneeHeaderTemplate: TemplateRef; + @ViewChild('milestoneHeader') milestoneHeaderTemplate: TemplateRef; issues: IssuesDataTable; issues$: Observable; @@ -82,6 +83,8 @@ export class CardViewComponent implements OnInit, AfterViewInit, OnDestroy, Filt switch (this.groupingContextService.currGroupBy) { case GroupBy.Assignee: return this.assigneeHeaderTemplate; + case GroupBy.Milestone: + return this.milestoneHeaderTemplate; default: return this.defaultHeaderTemplate; } diff --git a/src/app/issues-viewer/hidden-groups/hidden-groups.component.html b/src/app/issues-viewer/hidden-groups/hidden-groups.component.html index bedec7c1..cf74fd7c 100644 --- a/src/app/issues-viewer/hidden-groups/hidden-groups.component.html +++ b/src/app/issues-viewer/hidden-groups/hidden-groups.component.html @@ -31,3 +31,11 @@ + + + + + {{ milestone.title }} + + + diff --git a/src/app/issues-viewer/hidden-groups/hidden-groups.component.ts b/src/app/issues-viewer/hidden-groups/hidden-groups.component.ts index ffcdabad..094fa6d6 100644 --- a/src/app/issues-viewer/hidden-groups/hidden-groups.component.ts +++ b/src/app/issues-viewer/hidden-groups/hidden-groups.component.ts @@ -12,6 +12,7 @@ export class HiddenGroupsComponent { @ViewChild('defaultCard') defaultCardTemplate: TemplateRef; @ViewChild('assigneeCard') assigneeCardTemplate: TemplateRef; + @ViewChild('milestoneCard') milestoneCardTemplate: TemplateRef; constructor(public groupingContextService: GroupingContextService) {} @@ -19,6 +20,8 @@ export class HiddenGroupsComponent { switch (this.groupingContextService.currGroupBy) { case GroupBy.Assignee: return this.assigneeCardTemplate; + case GroupBy.Milestone: + return this.milestoneCardTemplate; default: return this.defaultCardTemplate; }