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

Status filter checkboxes #310

Merged
merged 9 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 12 additions & 29 deletions src/app/core/services/filters.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { SimpleLabel } from '../models/label.model';

export type Filter = {
title: string;
status: string;
status: string[];
type: string;
sort: Sort;
labels: string[];
Expand All @@ -16,7 +16,7 @@ export type Filter = {

export const DEFAULT_FILTER: Filter = {
title: '',
status: 'all',
status: ['open pullrequest', 'merged pullrequest', 'open issue', 'closed issue'],
type: 'all',
sort: { active: 'id', direction: 'asc' },
labels: [],
Expand All @@ -35,21 +35,16 @@ export const DEFAULT_FILTER: Filter = {
export class FiltersService {
public filter$ = new BehaviorSubject<Filter>(DEFAULT_FILTER);

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

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

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

nextFilter = this._validateFilter(nextFilter);

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

sanitizeLabels(allLabels: SimpleLabel[]) {
Expand All @@ -62,27 +57,15 @@ export class FiltersService {
}
}

const newLabels = this.filter$.value.labels.filter((label) => allLabelsSet.has(label));

this.updateFilters({ labels: newLabels, hiddenLabels: newHiddenLabels });
}
/**
* Changes type to a valid, default value when an incompatible combination of type and status is encountered.
*/
updateTypePairing(filter: Filter): Filter {
if (filter.status === 'merged') {
filter.type = 'pullrequest';
const newDeselectedLabels: Set<string> = new Set();
for (const deselectedLabel of this.filter$.value.deselectedLabels) {
if (allLabelsSet.has(deselectedLabel)) {
newDeselectedLabels.add(deselectedLabel);
}
}
return filter;
}

/**
* Changes status to a valid, default value when an incompatible combination of type and status is encountered.
*/
updateStatusPairing(filter: Filter): Filter {
if (filter.status === 'merged' && filter.type === 'issue') {
filter.status = 'all';
}
return filter;
const newLabels = this.filter$.value.labels.filter((label) => allLabelsSet.has(label));

this.updateFilters({ labels: newLabels, hiddenLabels: newHiddenLabels, deselectedLabels: newDeselectedLabels });
}
}
11 changes: 6 additions & 5 deletions src/app/shared/filter-bar/filter-bar.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
<div class="dropdown-filters">
<mat-form-field appearance="standard">
<mat-label>Status</mat-label>
<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>
<mat-option value="merged" *ngIf="isNotFilterIssue()">Merged</mat-option>
<mat-select [value]="this.filter.status" (selectionChange)="this.filtersService.updateFilters({ status: $event.value })" multiple>
<mat-option *ngIf="isFilterPullRequest()" value="open pullrequest">Open Pull Requests</mat-option>
<mat-option *ngIf="isFilterPullRequest()" value="merged pullrequest">Merged Pull Requests</mat-option>
<mat-option *ngIf="isFilterPullRequest()" value="closed pullrequest">Closed Pull Request</mat-option>
<mat-option *ngIf="isFilterIssue()" value="open issue">Open Issues</mat-option>
<mat-option *ngIf="isFilterIssue()" value="closed issue">Closed Issues</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="standard">
Expand Down
8 changes: 6 additions & 2 deletions src/app/shared/filter-bar/filter-bar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,12 @@ export class FilterBarComponent implements OnInit, OnDestroy {
/**
* Checks if program is filtering by type issue.
*/
isNotFilterIssue() {
return this.filter.type !== 'issue';
isFilterIssue() {
return this.filter.type === 'issue' || this.filter.type === 'all';
}

isFilterPullRequest() {
return this.filter.type === 'pullrequest' || this.filter.type === 'all';
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class LabelFilterBarComponent implements OnInit, AfterViewInit, OnDestroy
this.allLabels = labels;
this.filtersService.sanitizeLabels(this.allLabels);
this.selectedLabelNames = new Set<string>(this.filtersService.filter$.value.labels);
this.deselectedLabelNames = this.filtersService.filter$.value.deselectedLabels;
this.hiddenLabelNames = this.filtersService.filter$.value.hiddenLabels;
});
});
Expand Down
28 changes: 20 additions & 8 deletions src/app/shared/issue-tables/dropdownfilter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import { Issue } from '../../core/models/issue.model';
import { Filter } from '../../core/services/filters.service';

type StatusInfo = {
type: string;
status: string;
};

/**
* Converts a status string into an info object
*/
const infoFromStatus = (statusString: string): StatusInfo => {
const [status, type] = statusString.split(' ');
return { status, type };
};

/**
* This module serves to improve separation of concerns in IssuesDataTable.ts and IssueList.ts module by containing the logic for
* applying dropdownFilter to the issues data table in this module.
Expand All @@ -11,14 +24,13 @@ export function applyDropdownFilter(filter: Filter, data: Issue[]): Issue[] {
const filteredData: Issue[] = data.filter((issue) => {
let ret = true;

if (filter.status === 'open') {
ret = ret && issue.state === 'OPEN';
} else if (filter.status === 'closed') {
// there is apparently also a status called 'all' based on github api
ret = ret && issue.state === 'CLOSED';
} else if (filter.status === 'merged') {
ret = ret && issue.state === 'MERGED';
}
// status can either be 'open', 'closed', or 'merged'
ret =
ret &&
filter.status.some((item) => {
const statusInfo = infoFromStatus(item);
return statusInfo.status === issue.state.toLowerCase() && statusInfo.type === issue.issueOrPr.toLowerCase();
});

if (filter.type === 'issue') {
ret = ret && issue.issueOrPr === 'Issue';
Expand Down
Loading