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

feat(rxjs.dev): add api list deprecated filter #7383

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ describe('ApiListComponent', () => {
});
}

/**
* Expectation Utility: Assert that filteredSections has no items
*
* Subscribes to `filteredSections` and performs expectation within subscription callback.
*/
function expectNoItems() {
component.filteredSections.subscribe(filtered => {
expect(filtered.some(section => !!section.items)).toBeFalsy();
});
}



describe('#filteredSections', () => {

Expand Down Expand Up @@ -95,11 +107,17 @@ describe('ApiListComponent', () => {
});
});

it('should have no sections and no items visible when there is no match', () => {
it('should have no sections or items visible when there is no query match', () => {
component.setQuery('fizzbuzz');
component.filteredSections.subscribe(filtered => {
expect(filtered.some(section => !!section.items)).toBeFalsy();
});

expectNoItems();
});

it('should have no sections or items visible when there is no non-deprecated match', () => {
component.setQuery('function_1');
component.setIncludeDeprecated(false);

expectNoItems();
});
});

Expand Down Expand Up @@ -182,6 +200,20 @@ describe('ApiListComponent', () => {
expect(search.query).toBe('foo');
});

it('should have includeDeprecated', () => {
component.setIncludeDeprecated(false);

const search = locationService.setSearch.calls.mostRecent().args[1];
expect(search.includeDeprecated).toBe('false');
});

it('should not have includeDeprecated', () => {
component.setIncludeDeprecated(true);

const search = locationService.setSearch.calls.mostRecent().args[1];
expect(search.includeDeprecated).toBe(undefined);
});

it('should keep last of multiple query settings (in lowercase)', () => {
component.setQuery('foo');
component.setQuery('fooBar');
Expand All @@ -190,15 +222,17 @@ describe('ApiListComponent', () => {
expect(search.query).toBe('foobar');
});

it('should have query, status, and type', () => {
it('should have query, status, type, and includeDeprecated', () => {
component.setQuery('foo');
component.setStatus({value: 'stable', title: 'Stable'});
component.setType({value: 'class', title: 'Class'});
component.setIncludeDeprecated(false);

const search = locationService.setSearch.calls.mostRecent().args[1];
expect(search.query).toBe('foo');
expect(search.status).toBe('stable');
expect(search.type).toBe('class');
expect(search.includeDeprecated).toBe('false');
});
});
});
Expand Down
32 changes: 28 additions & 4 deletions apps/rxjs.dev/src/app/custom-elements/api/api-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class SearchCriteria {
query? = '';
status? = 'all';
type? = 'all';
includeDeprecated? = true;
}

@Component({
Expand All @@ -31,6 +32,11 @@ class SearchCriteria {
<input #filter placeholder="Filter" aria-label="Filter" (input)="setQuery(filter.value)" />
<i class="material-icons">search</i>
</div>

<label class="form-select-button show-deprecated">
Show deprecated:
<input type="checkbox" aria-label="Show Deprecated" [(ngModel)]="includeDeprecated" (change)="onIncludeDeprecatedChange()" />
</label>
</div>

<article class="api-list-container l-content-small docs-content">
Expand Down Expand Up @@ -62,6 +68,7 @@ export class ApiListComponent implements OnInit {

status: Option;
type: Option;
includeDeprecated: boolean;

// API types
types: Option[] = [
Expand Down Expand Up @@ -99,6 +106,16 @@ export class ApiListComponent implements OnInit {
this.setSearchCriteria({ query: (query || '').toLowerCase().trim() });
}

// NOTE includeDeprecated is model bound - the following method is used for testing
setIncludeDeprecated(includeDeprecated: boolean) {
this.includeDeprecated = includeDeprecated;
this.onIncludeDeprecatedChange();
}

onIncludeDeprecatedChange() {
this.setSearchCriteria({ includeDeprecated: this.includeDeprecated });
}

setStatus(status: Option) {
this.toggleStatusMenu();
this.status = status;
Expand All @@ -121,9 +138,9 @@ export class ApiListComponent implements OnInit {

//////// Private //////////

private filterSection(section: ApiSection, { query, status, type }: SearchCriteria) {
private filterSection(section: ApiSection, { query, status, type, includeDeprecated }: SearchCriteria) {
const items = section.items!.filter((item) => {
return matchesType() && matchesStatus() && matchesQuery();
return matchesType() && matchesStatus() && matchesQuery() && matchesStability();

function matchesQuery() {
return !query || section.name.indexOf(query) !== -1 || item.name.indexOf(query) !== -1;
Expand All @@ -136,6 +153,10 @@ export class ApiListComponent implements OnInit {
function matchesType() {
return type === 'all' || type === item.docType;
}

function matchesStability() {
return includeDeprecated || item.stability !== 'deprecated';
}
});

// If there are no items we still return an empty array if the section name matches and the type is 'package'
Expand All @@ -144,30 +165,33 @@ export class ApiListComponent implements OnInit {

// Get initial search criteria from URL search params
private initializeSearchCriteria() {
const { query, status, type } = this.locationService.search();
const { query, status, type, includeDeprecated } = this.locationService.search();

const q = (query || '').toLowerCase();
// Hack: can't bind to query because input cursor always forced to end-of-line.
this.queryEl.nativeElement.value = q;

this.status = this.statuses.find((x) => x.value === status) || this.statuses[0];
this.type = this.types.find((x) => x.value === type) || this.types[0];
this.includeDeprecated = includeDeprecated === 'false' ? false : true;

this.searchCriteria = {
query: q,
status: this.status.value,
type: this.type.value,
includeDeprecated: this.includeDeprecated,
};

this.criteriaSubject.next(this.searchCriteria);
}

private setLocationSearch() {
const { query, status, type } = this.searchCriteria;
const { query, status, type, includeDeprecated } = this.searchCriteria;
const params = {
query: query ? query : undefined,
status: status !== 'all' ? status : undefined,
type: type !== 'all' ? type : undefined,
includeDeprecated: includeDeprecated ? undefined : 'false',
};

this.locationService.setSearch('API Search', params);
Expand Down
3 changes: 2 additions & 1 deletion apps/rxjs.dev/src/app/custom-elements/api/api-list.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NgModule, Type } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { SharedModule } from '../../shared/shared.module';
Expand All @@ -7,7 +8,7 @@ import { ApiService } from './api.service';
import { WithCustomElementComponent } from '../element-registry';

@NgModule({
imports: [ CommonModule, SharedModule, HttpClientModule ],
imports: [ CommonModule, FormsModule, SharedModule, HttpClientModule ],
declarations: [ ApiListComponent ],
providers: [ ApiService ]
})
Expand Down
6 changes: 6 additions & 0 deletions apps/rxjs.dev/src/styles/2-modules/_api-list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@ aio-api-list {
margin-top: 16px;
}
}

label.show-deprecated {
margin-left: auto;
width: unset;
}
}

.api-filter {
display: flex;
align-items: center;
margin: 0 auto;

@media (max-width: 600px) {
Expand Down
Loading