mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(docs-infra): use reactive APIs in adev components (#58357)
This is a relativelly small refactoring to a couple of adev components. The goal here is to use new reactive APIs in the idiomatic way. PR Close #58357
This commit is contained in:
parent
3d918de05f
commit
3e50842593
9 changed files with 147 additions and 191 deletions
|
|
@ -1,3 +1 @@
|
|||
@if (apiItemType()) {
|
||||
{{ apiItemType()! | adevApiLabel: labelMode() }}
|
||||
}
|
||||
{{ type() | adevApiLabel: mode() }}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ describe('ApiItemLabel', () => {
|
|||
});
|
||||
|
||||
it('should by default display short label for Class', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
fixture.componentRef.setInput('type', ApiItemType.CLASS);
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
|
@ -34,8 +34,8 @@ describe('ApiItemLabel', () => {
|
|||
});
|
||||
|
||||
it('should display full label for Class when labelMode equals full', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
component.mode = 'full';
|
||||
fixture.componentRef.setInput('type', ApiItemType.CLASS);
|
||||
fixture.componentRef.setInput('mode', 'full');
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
|
@ -44,8 +44,8 @@ describe('ApiItemLabel', () => {
|
|||
});
|
||||
|
||||
it('should display short label for Class when labelMode equals short', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
component.mode = 'short';
|
||||
fixture.componentRef.setInput('type', ApiItemType.CLASS);
|
||||
fixture.componentRef.setInput('mode', 'short');
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, Input, signal} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, input} from '@angular/core';
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {ApiLabel} from '../pipes/api-label.pipe';
|
||||
|
||||
|
|
@ -16,19 +16,12 @@ import {ApiLabel} from '../pipes/api-label.pipe';
|
|||
templateUrl: './api-item-label.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: {
|
||||
'[attr.data-type]': 'apiItemType()',
|
||||
'[attr.data-mode]': 'labelMode()',
|
||||
'[attr.data-type]': 'type()',
|
||||
'[attr.data-mode]': 'mode()',
|
||||
},
|
||||
imports: [ApiLabel],
|
||||
})
|
||||
export default class ApiItemLabel {
|
||||
@Input({required: true}) set type(value: ApiItemType) {
|
||||
this.apiItemType.set(value);
|
||||
}
|
||||
@Input({required: true}) set mode(value: 'short' | 'full') {
|
||||
this.labelMode.set(value);
|
||||
}
|
||||
|
||||
protected apiItemType = signal<ApiItemType | undefined>(undefined);
|
||||
protected labelMode = signal<'short' | 'full'>('short');
|
||||
readonly type = input.required<ApiItemType>();
|
||||
readonly mode = input.required<'short' | 'full'>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
<header class="adev-api-items-section-header">
|
||||
<h3 [attr.id]="group.id">
|
||||
@if (group.isFeatured) {
|
||||
<h3 [id]="group().id">
|
||||
@if (group().isFeatured) {
|
||||
<docs-icon aria-hidden>star</docs-icon>
|
||||
}
|
||||
<!-- we use innerHtml because the title can be an html string-->
|
||||
<a
|
||||
routerLink="/api"
|
||||
[fragment]="group.id"
|
||||
[fragment]="group().id"
|
||||
queryParamsHandling="preserve"
|
||||
class="adev-api-anchor"
|
||||
tabindex="-1"
|
||||
[innerHtml]="group.title"
|
||||
[innerHtml]="group().title"
|
||||
></a>
|
||||
</h3>
|
||||
</header>
|
||||
|
||||
<ul class="adev-api-items-section-grid">
|
||||
@for (apiItem of group.items; track apiItem.url) {
|
||||
@for (apiItem of group().items; track apiItem.url) {
|
||||
<li [class.adev-api-items-section-item-deprecated]="apiItem.isDeprecated">
|
||||
<a
|
||||
[routerLink]="'/' + apiItem.url"
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
@if (apiItem.isFeatured) {
|
||||
<docs-icon
|
||||
class="adev-api-items-section-item-featured"
|
||||
[class.adev-api-item-in-featured-section]="group.isFeatured"
|
||||
[class.adev-api-item-in-featured-section]="group().isFeatured"
|
||||
[class.adev-api-items-section-item-featured-active]="apiItem.isFeatured"
|
||||
>
|
||||
star
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ describe('ApiItemsSection', () => {
|
|||
});
|
||||
|
||||
it('should render star icon for featured group', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.componentRef.setInput('group', fakeFeaturedGroup);
|
||||
fixture.detectChanges();
|
||||
|
||||
const starIcon = fixture.debugElement.query(By.css('.adev-api-items-section-header docs-icon'));
|
||||
|
|
@ -75,7 +75,7 @@ describe('ApiItemsSection', () => {
|
|||
});
|
||||
|
||||
it('should not render star icon for standard group', () => {
|
||||
component.group = fakeGroup;
|
||||
fixture.componentRef.setInput('group', fakeGroup);
|
||||
fixture.detectChanges();
|
||||
|
||||
const starIcon = fixture.debugElement.query(By.css('.adev-api-items-section-header docs-icon'));
|
||||
|
|
@ -84,7 +84,7 @@ describe('ApiItemsSection', () => {
|
|||
});
|
||||
|
||||
it('should render list of all APIs of provided group', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.componentRef.setInput('group', fakeFeaturedGroup);
|
||||
fixture.detectChanges();
|
||||
|
||||
const apis = fixture.debugElement.queryAll(By.css('.adev-api-items-section-grid li'));
|
||||
|
|
@ -93,7 +93,7 @@ describe('ApiItemsSection', () => {
|
|||
});
|
||||
|
||||
it('should display deprecated icon for deprecated API', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.componentRef.setInput('group', fakeFeaturedGroup);
|
||||
fixture.detectChanges();
|
||||
|
||||
const deprecatedApiIcons = fixture.debugElement.queryAll(
|
||||
|
|
@ -107,7 +107,7 @@ describe('ApiItemsSection', () => {
|
|||
});
|
||||
|
||||
it('should display star icon for featured API', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.componentRef.setInput('group', fakeFeaturedGroup);
|
||||
fixture.detectChanges();
|
||||
|
||||
const featuredApiIcons = fixture.debugElement.queryAll(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, input} from '@angular/core';
|
||||
import {RouterLink} from '@angular/router';
|
||||
import {ApiItemsGroup} from '../interfaces/api-items-group';
|
||||
import ApiItemLabel from '../api-item-label/api-item-label.component';
|
||||
|
|
@ -21,5 +21,5 @@ import {IconComponent} from '@angular/docs';
|
|||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export default class ApiItemsSection {
|
||||
@Input({required: true}) group!: ApiItemsGroup;
|
||||
group = input.required<ApiItemsGroup>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<div class="adev-header-and-tabs docs-scroll-track-transparent">
|
||||
<docs-viewer [docContent]="headerInnerHtml()" class="docs-reference-header"></docs-viewer>
|
||||
<docs-viewer [docContent]="parsedDocContent().header" class="docs-reference-header"></docs-viewer>
|
||||
|
||||
<mat-tab-group class="docs-reference-tabs" animationDuration="0ms" mat-stretch-tabs="false" [selectedIndex]="selectedTabIndex()">
|
||||
@for (tab of tabs(); track tab) {
|
||||
<mat-tab-group class="docs-reference-tabs" animationDuration="0ms" mat-stretch-tabs="false" [selectedIndex]="selectedTabIndex()" (selectedIndexChange)="tabChange($event)">
|
||||
@for (tab of tabs(); track tab.url) {
|
||||
<mat-tab [label]="tab.title">
|
||||
<div class="adev-reference-tab-body">
|
||||
<docs-viewer [docContent]="tab.content"></docs-viewer>
|
||||
|
|
@ -12,10 +12,10 @@
|
|||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
@if (canDisplayCards() && membersMarginTopInPx() > 0) {
|
||||
@if (isApiTabActive() && membersMarginTopInPx() > 0) {
|
||||
<docs-viewer
|
||||
class="docs-reference-members-container"
|
||||
[docContent]="membersInnerHtml()"
|
||||
[docContent]="parsedDocContent().members"
|
||||
[style.marginTop.px]="membersMarginTopInPx()"
|
||||
(contentLoaded)="membersCardsLoaded()">
|
||||
</docs-viewer>
|
||||
|
|
|
|||
|
|
@ -7,21 +7,15 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
DestroyRef,
|
||||
Injector,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
afterNextRender,
|
||||
inject,
|
||||
signal,
|
||||
input,
|
||||
computed,
|
||||
} from '@angular/core';
|
||||
import {DOCUMENT} from '@angular/common';
|
||||
import {MatTabGroup, MatTabsModule} from '@angular/material/tabs';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {distinctUntilChanged, map} from 'rxjs/operators';
|
||||
import {MatTabsModule} from '@angular/material/tabs';
|
||||
import {DocContent, DocViewer} from '@angular/docs';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {ApiItemType} from './../interfaces/api-item-type';
|
||||
|
|
@ -30,7 +24,6 @@ import {
|
|||
API_REFERENCE_DETAILS_PAGE_HEADER_CLASS_NAME,
|
||||
API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME,
|
||||
API_REFERENCE_TAB_ATTRIBUTE,
|
||||
API_REFERENCE_TAB_QUERY_PARAM,
|
||||
API_REFERENCE_TAB_API_LABEL,
|
||||
API_TAB_CLASS_NAME,
|
||||
API_REFERENCE_TAB_BODY_CLASS_NAME,
|
||||
|
|
@ -47,116 +40,96 @@ import {AppScroller} from '../../../app-scroller';
|
|||
providers: [ReferenceScrollHandler],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export default class ApiReferenceDetailsPage implements OnInit, AfterViewInit {
|
||||
@ViewChild(MatTabGroup, {static: true}) matTabGroup!: MatTabGroup;
|
||||
|
||||
export default class ApiReferenceDetailsPage {
|
||||
private readonly activatedRoute = inject(ActivatedRoute);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly document = inject(DOCUMENT);
|
||||
private readonly router = inject(Router);
|
||||
private readonly scrollHandler = inject(ReferenceScrollHandler);
|
||||
private readonly appScroller = inject(AppScroller);
|
||||
private readonly injector = inject(Injector);
|
||||
|
||||
docContent = input<DocContent | undefined>();
|
||||
tab = input<string | undefined>();
|
||||
|
||||
// aliases
|
||||
ApiItemType = ApiItemType;
|
||||
|
||||
canDisplayCards = signal<boolean>(false);
|
||||
tabs = signal<{url: string; title: string; content: string}[]>([]);
|
||||
headerInnerHtml = signal<string | undefined>(undefined);
|
||||
membersInnerHtml = signal<string | undefined>(undefined);
|
||||
membersMarginTopInPx = this.scrollHandler.membersMarginTopInPx;
|
||||
selectedTabIndex = signal(0);
|
||||
|
||||
// computed state
|
||||
parsedDocContent = computed(() => {
|
||||
// TODO: pull this logic outside of a computed where it can be tested etc.
|
||||
const docContent = this.docContent();
|
||||
|
||||
if (docContent === undefined) {
|
||||
return {
|
||||
header: undefined,
|
||||
members: undefined,
|
||||
tabs: [],
|
||||
};
|
||||
}
|
||||
|
||||
const element = this.document.createElement('div');
|
||||
element.innerHTML = docContent.contents;
|
||||
|
||||
// Get the innerHTML of the header element from received document.
|
||||
const header = element.querySelector(API_REFERENCE_DETAILS_PAGE_HEADER_CLASS_NAME);
|
||||
// Get the innerHTML of the card elements from received document.
|
||||
const members = element.querySelector(API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME);
|
||||
|
||||
// Get the tab elements from received document.
|
||||
// We're expecting that tab element will contain `tab` attribute.
|
||||
const tabs = Array.from(element.querySelectorAll(`[${API_REFERENCE_TAB_ATTRIBUTE}]`)).map(
|
||||
(tab) => ({
|
||||
url: tab.getAttribute(API_REFERENCE_TAB_URL_ATTRIBUTE)!,
|
||||
title: tab.getAttribute(API_REFERENCE_TAB_ATTRIBUTE)!,
|
||||
content: tab.innerHTML,
|
||||
}),
|
||||
);
|
||||
|
||||
element.remove();
|
||||
|
||||
return {
|
||||
header: header?.innerHTML,
|
||||
members: members?.innerHTML,
|
||||
tabs,
|
||||
};
|
||||
});
|
||||
|
||||
tabs = () => this.parsedDocContent().tabs;
|
||||
|
||||
selectedTabIndex = computed(() => {
|
||||
const existingTabIdx = this.tabs().findIndex((tab) => tab.url === this.tab());
|
||||
return Math.max(existingTabIdx, 0);
|
||||
});
|
||||
|
||||
isApiTabActive = computed(() => {
|
||||
const activeTabTitle = this.tabs()[this.selectedTabIndex()]?.title;
|
||||
return activeTabTitle === API_REFERENCE_TAB_API_LABEL || activeTabTitle === 'CLI';
|
||||
});
|
||||
|
||||
constructor() {
|
||||
this.appScroller.disableScrolling = true;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.setPageContent();
|
||||
afterNextRender({
|
||||
write: () => {
|
||||
if (this.isApiTabActive()) {
|
||||
this.scrollHandler.updateMembersMarginTop(API_REFERENCE_TAB_BODY_CLASS_NAME);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.appScroller.disableScrolling = false;
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.setActiveTab();
|
||||
this.listenToTabChange();
|
||||
}
|
||||
|
||||
membersCardsLoaded(): void {
|
||||
this.scrollHandler.setupListeners(API_TAB_CLASS_NAME);
|
||||
}
|
||||
|
||||
// Fetch the content for API Reference page based on the active route.
|
||||
private setPageContent(): void {
|
||||
this.activatedRoute.data
|
||||
.pipe(
|
||||
map((data) => data['docContent']),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
)
|
||||
.subscribe((doc: DocContent | undefined) => {
|
||||
this.setContentForPageSections(doc);
|
||||
afterNextRender(() => this.setActiveTab(), {injector: this.injector});
|
||||
});
|
||||
}
|
||||
|
||||
private listenToTabChange(): void {
|
||||
this.matTabGroup.selectedIndexChange
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe((index) => {
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.activatedRoute,
|
||||
queryParams: {tab: this.tabs()[index].url},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private setContentForPageSections(doc: DocContent | undefined): void {
|
||||
const element = this.document.createElement('div');
|
||||
element.innerHTML = doc?.contents!;
|
||||
|
||||
// Get the innerHTML of the header element from received document.
|
||||
const header = element.querySelector(API_REFERENCE_DETAILS_PAGE_HEADER_CLASS_NAME);
|
||||
if (header) {
|
||||
this.headerInnerHtml.set(header.innerHTML);
|
||||
}
|
||||
|
||||
// Get the innerHTML of the card elements from received document.
|
||||
const members = element.querySelector(API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME);
|
||||
if (members) {
|
||||
this.membersInnerHtml.set(members.innerHTML);
|
||||
}
|
||||
|
||||
// Get the tab elements from received document.
|
||||
// We're expecting that tab element will contain `tab` attribute.
|
||||
const tabs = Array.from(element.querySelectorAll(`[${API_REFERENCE_TAB_ATTRIBUTE}]`));
|
||||
this.tabs.set(
|
||||
tabs.map((tab) => ({
|
||||
url: tab.getAttribute(API_REFERENCE_TAB_URL_ATTRIBUTE)!,
|
||||
title: tab.getAttribute(API_REFERENCE_TAB_ATTRIBUTE)!,
|
||||
content: tab.innerHTML,
|
||||
})),
|
||||
);
|
||||
|
||||
element.remove();
|
||||
}
|
||||
|
||||
private setActiveTab(): void {
|
||||
this.activatedRoute.queryParamMap
|
||||
.pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe((paramsMap) => {
|
||||
const selectedTabUrl = paramsMap.get(API_REFERENCE_TAB_QUERY_PARAM);
|
||||
const tabIndexToSelect = this.tabs().findIndex((tab) => tab.url === selectedTabUrl);
|
||||
this.selectedTabIndex.set(tabIndexToSelect < 0 ? 0 : tabIndexToSelect);
|
||||
|
||||
this.scrollHandler.updateMembersMarginTop(API_REFERENCE_TAB_BODY_CLASS_NAME);
|
||||
|
||||
const isApiTabActive =
|
||||
this.tabs()[this.selectedTabIndex()]?.title === API_REFERENCE_TAB_API_LABEL ||
|
||||
this.tabs()[this.selectedTabIndex()]?.title === 'CLI';
|
||||
this.canDisplayCards.set(isApiTabActive);
|
||||
});
|
||||
tabChange(tabIndex: number) {
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.activatedRoute,
|
||||
queryParams: {tab: this.tabs()[tabIndex].url},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,14 +10,13 @@ import {
|
|||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Injector,
|
||||
afterNextRender,
|
||||
computed,
|
||||
effect,
|
||||
inject,
|
||||
model,
|
||||
signal,
|
||||
viewChild,
|
||||
afterRenderEffect,
|
||||
} from '@angular/core';
|
||||
import ApiItemsSection from '../api-items-section/api-items-section.component';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
|
|
@ -40,69 +39,63 @@ export const ALL_STATUSES_KEY = 'All';
|
|||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export default class ApiReferenceList {
|
||||
// services
|
||||
private readonly apiReferenceManager = inject(ApiReferenceManager);
|
||||
private readonly router = inject(Router);
|
||||
filterInput = viewChild.required(TextField, {read: ElementRef});
|
||||
private readonly injector = inject(Injector);
|
||||
|
||||
private readonly allGroups = this.apiReferenceManager.apiGroups;
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const filterInput = this.filterInput();
|
||||
afterNextRender(
|
||||
{
|
||||
write: () => {
|
||||
// Lord forgive me for I have sinned
|
||||
// Use the CVA to focus when https://github.com/angular/angular/issues/31133 is implemented
|
||||
if (matchMedia('(hover: hover) and (pointer:fine)').matches) {
|
||||
filterInput.nativeElement.querySelector('input').focus();
|
||||
}
|
||||
},
|
||||
},
|
||||
{injector: this.injector},
|
||||
);
|
||||
});
|
||||
|
||||
effect(
|
||||
() => {
|
||||
const params: Params = {
|
||||
'query': this.query() ? this.query() : null,
|
||||
'type': this.type() ? this.type() : null,
|
||||
};
|
||||
|
||||
this.router.navigate([], {
|
||||
queryParams: params,
|
||||
replaceUrl: true,
|
||||
preserveFragment: true,
|
||||
info: {
|
||||
disableScrolling: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
{allowSignalWrites: true},
|
||||
);
|
||||
}
|
||||
|
||||
// inputs
|
||||
query = model<string | undefined>('');
|
||||
includeDeprecated = signal(false);
|
||||
|
||||
type = model<string | undefined>(ALL_STATUSES_KEY);
|
||||
|
||||
featuredGroup = this.apiReferenceManager.featuredGroup;
|
||||
// const state
|
||||
itemTypes = Object.values(ApiItemType);
|
||||
|
||||
// state
|
||||
featuredGroup = this.apiReferenceManager.featuredGroup; // THINK: this is a shortcut - why would people write this?
|
||||
includeDeprecated = signal(false);
|
||||
|
||||
// queries
|
||||
filterInput = viewChild.required(TextField, {read: ElementRef});
|
||||
|
||||
constructor() {
|
||||
afterRenderEffect({
|
||||
write: () => {
|
||||
// Lord forgive me for I have sinned
|
||||
// Use the CVA to focus when https://github.com/angular/angular/issues/31133 is implemented
|
||||
if (matchMedia('(hover: hover) and (pointer:fine)').matches) {
|
||||
this.filterInput().nativeElement.querySelector('input').focus();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
const params: Params = {
|
||||
'query': this.query() ?? null,
|
||||
'type': this.type() ?? null,
|
||||
};
|
||||
|
||||
this.router.navigate([], {
|
||||
queryParams: params,
|
||||
replaceUrl: true,
|
||||
preserveFragment: true,
|
||||
info: {
|
||||
disableScrolling: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
filteredGroups = computed((): ApiItemsGroup[] => {
|
||||
return this.allGroups()
|
||||
const query = this.query()?.toLocaleLowerCase();
|
||||
return this.apiReferenceManager
|
||||
.apiGroups()
|
||||
.map((group) => ({
|
||||
title: group.title,
|
||||
isFeatured: group.isFeatured,
|
||||
id: group.id,
|
||||
items: group.items.filter((apiItem) => {
|
||||
return (
|
||||
(this.query() !== undefined
|
||||
? apiItem.title
|
||||
.toLocaleLowerCase()
|
||||
.includes((this.query() as string).toLocaleLowerCase())
|
||||
: true) &&
|
||||
(query !== undefined ? apiItem.title.toLocaleLowerCase().includes(query) : true) &&
|
||||
(this.includeDeprecated() ? true : apiItem.isDeprecated === this.includeDeprecated()) &&
|
||||
(this.type() === undefined ||
|
||||
this.type() === ALL_STATUSES_KEY ||
|
||||
|
|
@ -112,7 +105,6 @@ export default class ApiReferenceList {
|
|||
}))
|
||||
.filter((group) => group.items.length > 0);
|
||||
});
|
||||
itemTypes = Object.values(ApiItemType);
|
||||
|
||||
filterByItemType(itemType: ApiItemType): void {
|
||||
this.type.update((currentType) => (currentType === itemType ? ALL_STATUSES_KEY : itemType));
|
||||
|
|
|
|||
Loading…
Reference in a new issue