Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploy v1.1.1 #292

Merged
merged 12 commits into from
Mar 14, 2024
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "WATcher",
"version": "1.1.0",
"version": "1.1.1",
"main": "main.js",
"scripts": {
"ng": "ng",
Expand All @@ -24,7 +24,7 @@
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged",
"pre-push": "npm run lint"
"pre-push": "npm run lint && npm run test"
}
},
"dependencies": {
Expand Down
8 changes: 3 additions & 5 deletions src/app/core/models/milestone.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@
* Represents a milestone and its attributes fetched from Github.
*/
export class Milestone {
static DefaultMilestone: Milestone = new Milestone({ number: 'untracked', title: 'Without a milestone', state: null });
readonly number: string; // equivalent to the id of an issue e.g. milestone #1
static DefaultMilestone: Milestone = new Milestone({ title: 'Without a milestone', state: null });
title: string;
state: string;

constructor(milestone: { number: string; title: string; state: string }) {
this.number = milestone.number;
constructor(milestone: { title: string; state: string }) {
this.title = milestone.title;
this.state = milestone.state;
}

public equals(milestone: Milestone) {
return this.number === milestone.number;
return this.title === milestone.title;
}
}
38 changes: 28 additions & 10 deletions src/app/core/services/filters.service.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,57 @@
import { Injectable } from '@angular/core';
import { Sort } from '@angular/material/sort';
import { BehaviorSubject, pipe } from 'rxjs';
import { DEFAULT_DROPDOWN_FILTER, DropdownFilter } from '../../shared/issue-tables/dropdownfilter';

export type Filter = {
title: string;
status: string;
type: string;
sort: Sort;
labels: string[];
milestones: string[];
hiddenLabels?: Set<string>;
};

export const DEFAULT_FILTER: Filter = {
title: '',
status: 'all',
type: 'all',
sort: { active: 'id', direction: 'asc' },
labels: [],
milestones: []
};

@Injectable({
providedIn: 'root'
})

/**
* Responsible for centralising filters
* Filters are subscribed to and emitted from this service
*/
export class FiltersService {
public dropdownFilter$ = new BehaviorSubject<DropdownFilter>(DEFAULT_DROPDOWN_FILTER);
public filter$ = new BehaviorSubject<Filter>(DEFAULT_FILTER);

private _validateFilter = pipe(this.updateStatusPairing, this.updateTypePairing);

clearFilters(): void {
this.dropdownFilter$.next(DEFAULT_DROPDOWN_FILTER);
this.filter$.next(DEFAULT_FILTER);
}

updateFilters(newFilters: Partial<DropdownFilter>): void {
let nextDropdownFilter: DropdownFilter = {
...this.dropdownFilter$.value,
updateFilters(newFilters: Partial<Filter>): void {
let nextDropdownFilter: Filter = {
...this.filter$.value,
...newFilters
};

nextDropdownFilter = this._validateFilter(nextDropdownFilter);

this.dropdownFilter$.next(nextDropdownFilter);
this.filter$.next(nextDropdownFilter);
}

/**
* Changes type to a valid, default value when an incompatible combination of type and status is encountered.
*/
updateTypePairing(dropdownFilter: DropdownFilter): DropdownFilter {
updateTypePairing(dropdownFilter: Filter): Filter {
if (dropdownFilter.status === 'merged') {
dropdownFilter.type = 'pullrequest';
}
Expand All @@ -43,7 +61,7 @@ export class FiltersService {
/**
* Changes status to a valid, default value when an incompatible combination of type and status is encountered.
*/
updateStatusPairing(dropdownFilter: DropdownFilter): DropdownFilter {
updateStatusPairing(dropdownFilter: Filter): Filter {
if (dropdownFilter.status === 'merged' && dropdownFilter.type === 'issue') {
dropdownFilter.status = 'all';
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/issues-viewer/card-view/card-view.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<div class="scrollable-container-wrapper">
<div class="scrollable-container">
<div class="issue-pr-cards" *ngFor="let issue of this.issues$ | async; index as i">
<app-issue-pr-card [issue]="issue" [dropdownFilter]="issues.dropdownFilter"></app-issue-pr-card>
<app-issue-pr-card [issue]="issue" [filter]="issues.filter"></app-issue-pr-card>
</div>
<mat-card class="loading-spinner" *ngIf="this.issues.isLoading$ | async">
<mat-progress-spinner color="primary" mode="indeterminate" diameter="50" strokeWidth="5"></mat-progress-spinner>
Expand Down
12 changes: 6 additions & 6 deletions src/app/shared/filter-bar/filter-bar.component.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<mat-grid-list cols="7" rowHeight="80px">
<mat-grid-tile colspan="3">
<mat-form-field class="search-bar">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Search" />
<input matInput (keyup)="this.filtersService.updateFilters({ title: $event.target.value })" placeholder="Search" />
</mat-form-field>
</mat-grid-tile>

<mat-grid-tile colspan="3">
<div class="dropdown-filters">
<mat-form-field appearance="standard">
<mat-label>Status</mat-label>
<mat-select [value]="this.dropdownFilter.status" (selectionChange)="this.filtersService.updateFilters({ status: $event.value })">
<mat-select [value]="this.filter.status" (selectionChange)="this.filtersService.updateFilters({ status: $event.value })">
<mat-option value="all">All</mat-option>
<mat-option value="open">Open</mat-option>
<mat-option value="closed">Closed</mat-option>
Expand All @@ -18,7 +18,7 @@
</mat-form-field>
<mat-form-field appearance="standard">
<mat-label>Type</mat-label>
<mat-select [value]="this.dropdownFilter.type" (selectionChange)="this.filtersService.updateFilters({ type: $event.value })">
<mat-select [value]="this.filter.type" (selectionChange)="this.filtersService.updateFilters({ type: $event.value })">
<mat-option value="all">All</mat-option>
<mat-option value="issue">Issue</mat-option>
<mat-option value="pullrequest">Pull Request</mat-option>
Expand All @@ -31,7 +31,7 @@
(matSortChange)="this.filtersService.updateFilters({ sort: $event })"
>
<mat-label>Sort</mat-label>
<mat-select [value]="this.dropdownFilter.sort.active">
<mat-select [value]="this.filter.sort.active">
<mat-option value="id">
<span mat-sort-header="id">ID</span>
</mat-option>
Expand All @@ -47,15 +47,15 @@
<mat-label>Milestone</mat-label>
<mat-select
#milestoneSelectorRef
[value]="this.dropdownFilter.milestones"
[value]="this.filter.milestones"
(selectionChange)="this.filtersService.updateFilters({ milestones: $event.value })"
[disabled]="this.milestoneService.hasNoMilestones"
multiple
>
<mat-select-trigger *ngIf="this.milestoneService.hasNoMilestones">
<span>No Milestones</span>
</mat-select-trigger>
<mat-option *ngFor="let milestone of this.milestoneService.milestones" [value]="milestone.number">
<mat-option *ngFor="let milestone of this.milestoneService.milestones" [value]="milestone.title">
{{ milestone.title }}
</mat-option>
</mat-select>
Expand Down
27 changes: 9 additions & 18 deletions src/app/shared/filter-bar/filter-bar.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { AfterViewInit, Component, Input, OnDestroy, OnInit, QueryList, ViewChild } from '@angular/core';
import { MatSelect } from '@angular/material/select';
import { BehaviorSubject, Subscription } from 'rxjs';
import { FiltersService } from '../../core/services/filters.service';
import { DEFAULT_FILTER, Filter, FiltersService } from '../../core/services/filters.service';
import { LoggingService } from '../../core/services/logging.service';
import { MilestoneService } from '../../core/services/milestone.service';
import { PhaseService } from '../../core/services/phase.service';
import { DEFAULT_DROPDOWN_FILTER, DropdownFilter } from '../issue-tables/dropdownfilter';
import { FilterableComponent } from '../issue-tables/filterableTypes';
import { LabelFilterBarComponent } from './label-filter-bar/label-filter-bar.component';

Expand All @@ -24,7 +23,7 @@ export class FilterBarComponent implements OnInit, AfterViewInit, OnDestroy {
repoChangeSubscription: Subscription;

/** Selected dropdown filter value */
dropdownFilter: DropdownFilter = DEFAULT_DROPDOWN_FILTER;
filter: Filter = DEFAULT_FILTER;

/** Milestone subscription */
milestoneSubscription: Subscription;
Expand All @@ -47,9 +46,9 @@ export class FilterBarComponent implements OnInit, AfterViewInit, OnDestroy {
}

ngAfterViewInit(): void {
this.filtersService.dropdownFilter$.subscribe((dropdownFilter) => {
this.dropdownFilter = dropdownFilter;
this.applyDropdownFilter();
this.filtersService.filter$.subscribe((dropdownFilter) => {
this.filter = dropdownFilter;
this.applyFilter();
});
}

Expand All @@ -60,24 +59,16 @@ export class FilterBarComponent implements OnInit, AfterViewInit, OnDestroy {

/**
* Signals to IssuesDataTable that a change has occurred in filter.
* @param filterValue
*/
applyFilter(filterValue: string) {
this.views$?.value?.forEach((v) => (v.retrieveFilterable().filter = filterValue));
}

/**
* Signals to IssuesDataTable that a change has occurred in dropdown filter.
*/
applyDropdownFilter() {
this.views$?.value?.forEach((v) => (v.retrieveFilterable().dropdownFilter = this.dropdownFilter));
applyFilter() {
this.views$?.value?.forEach((v) => (v.retrieveFilterable().filter = this.filter));
}

/**
* Checks if program is filtering by type issue.
*/
isNotFilterIssue() {
return this.dropdownFilter.type !== 'issue';
return this.filter.type !== 'issue';
}

/**
Expand All @@ -88,7 +79,7 @@ export class FilterBarComponent implements OnInit, AfterViewInit, OnDestroy {
this.milestoneSubscription = this.milestoneService.fetchMilestones().subscribe(
(response) => {
this.logger.debug('IssuesViewerComponent: Fetched milestones from Github');
this.milestoneService.milestones.forEach((milestone) => this.dropdownFilter.milestones.push(milestone.number));
this.milestoneService.milestones.forEach((milestone) => this.filter.milestones.push(milestone.title));
},
(err) => {},
() => {}
Expand Down
2 changes: 1 addition & 1 deletion src/app/shared/issue-pr-card/issue-pr-card.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<app-issue-pr-card-header [issue]="issue"></app-issue-pr-card-header>
<mat-card-content>
<app-issue-pr-card-milestone [milestone]="issue.milestone"></app-issue-pr-card-milestone>
<app-issue-pr-card-labels [labels]="issue.githubLabels" [labelSet]="dropdownFilter?.hiddenLabels"></app-issue-pr-card-labels>
<app-issue-pr-card-labels [labels]="issue.githubLabels" [labelSet]="filter?.hiddenLabels"></app-issue-pr-card-labels>
</mat-card-content>
</span>
</a>
Expand Down
4 changes: 2 additions & 2 deletions src/app/shared/issue-pr-card/issue-pr-card.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Component, Input } from '@angular/core';
import { Issue } from '../../core/models/issue.model';
import { Filter } from '../../core/services/filters.service';
import { GithubService } from '../../core/services/github.service';
import { LabelService } from '../../core/services/label.service';
import { LoggingService } from '../../core/services/logging.service';
import { DropdownFilter } from '../issue-tables/dropdownfilter';

@Component({
selector: 'app-issue-pr-card',
Expand All @@ -12,7 +12,7 @@ import { DropdownFilter } from '../issue-tables/dropdownfilter';
})
export class IssuePrCardComponent {
@Input() issue: Issue;
@Input() dropdownFilter?: DropdownFilter;
@Input() filter?: Filter;

constructor(private logger: LoggingService, private githubService: GithubService, public labelService: LabelService) {}

Expand Down
33 changes: 10 additions & 23 deletions src/app/shared/issue-tables/IssuesDataTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ import { BehaviorSubject, merge, Observable, Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import { GithubUser } from '../../core/models/github-user.model';
import { Issue } from '../../core/models/issue.model';
import { DEFAULT_FILTER, Filter } from '../../core/services/filters.service';
import { IssueService } from '../../core/services/issue.service';
import { applyDropdownFilter, DEFAULT_DROPDOWN_FILTER, DropdownFilter } from './dropdownfilter';
import { applyDropdownFilter } from './dropdownfilter';
import { FilterableSource } from './filterableTypes';
import { paginateData } from './issue-paginator';
import { applySort } from './issue-sorter';
import { applySearchFilter } from './search-filter';

export class IssuesDataTable extends DataSource<Issue> implements FilterableSource {
public count = 0;
private filterChange = new BehaviorSubject('');
private dropdownFilterChange = new BehaviorSubject(DEFAULT_DROPDOWN_FILTER);
private teamFilterChange = new BehaviorSubject('');
private filterChange = new BehaviorSubject(DEFAULT_FILTER);
private issuesSubject = new BehaviorSubject<Issue[]>([]);
private issueSubscription: Subscription;

Expand All @@ -36,9 +35,7 @@ export class IssuesDataTable extends DataSource<Issue> implements FilterableSour
}

disconnect() {
this.dropdownFilterChange.complete();
this.filterChange.complete();
this.teamFilterChange.complete();
this.issuesSubject.complete();
this.issueSubscription.unsubscribe();
this.issueService.stopPollIssues();
Expand All @@ -50,9 +47,7 @@ export class IssuesDataTable extends DataSource<Issue> implements FilterableSour
page = this.paginator.page;
}

const displayDataChanges = [this.issueService.issues$, page, this.filterChange, this.dropdownFilterChange].filter(
(x) => x !== undefined
);
const displayDataChanges = [this.issueService.issues$, page, this.filterChange].filter((x) => x !== undefined);

this.issueService.startPollIssues();
this.issueSubscription = merge(...displayDataChanges)
Expand Down Expand Up @@ -80,13 +75,13 @@ export class IssuesDataTable extends DataSource<Issue> implements FilterableSour
});
}

// Dropdown Filters
data = applyDropdownFilter(this.dropdownFilter, data);
// Apply Filters
data = applyDropdownFilter(this.filter, data);

data = applySearchFilter(this.filter, this.displayedColumn, this.issueService, data);
data = applySearchFilter(this.filter.title, this.displayedColumn, this.issueService, data);
this.count = data.length;

data = applySort(this.dropdownFilter.sort, data);
data = applySort(this.filter.sort, data);

if (this.paginator !== undefined) {
data = paginateData(this.paginator, data);
Expand All @@ -99,19 +94,11 @@ export class IssuesDataTable extends DataSource<Issue> implements FilterableSour
});
}

get filter(): string {
get filter(): Filter {
return this.filterChange.value;
}

set filter(filter: string) {
set filter(filter: Filter) {
this.filterChange.next(filter);
}

get dropdownFilter(): DropdownFilter {
return this.dropdownFilterChange.value;
}

set dropdownFilter(filter: DropdownFilter) {
this.dropdownFilterChange.next(filter);
}
}
Loading
Loading