apim-developer-portal4
Version:
API management developer portal
173 lines (143 loc) • 5.27 kB
text/typescript
import * as ko from "knockout";
import * as Constants from "../../../../../constants";
import template from "./api-list-dropdown.html";
import { Component, RuntimeComponent, OnMounted, Param, OnDestroyed } from "@paperbits/common/ko/decorators";
import { Router } from "@paperbits/common/routing";
import { RouteHelper } from "../../../../../routing/routeHelper";
import { Api } from "../../../../../models/api";
import { ApiService } from "../../../../../services/apiService";
import { TagGroup } from "../../../../../models/tagGroup";
import { SearchQuery } from "../../../../../contracts/searchQuery";
import { Utils } from "../../../../../utils";
import { Tag } from "../../../../../models/tag";
export class ApiListDropdown {
public readonly apiGroups: ko.ObservableArray<TagGroup<Api>>;
public readonly selectedApi: ko.Observable<Api>;
public readonly selectedApiName: ko.Observable<string>;
public readonly working: ko.Observable<boolean>;
public readonly pattern: ko.Observable<string>;
public readonly tags: ko.Observable<Tag[]>;
public readonly page: ko.Observable<number>;
public readonly hasPager: ko.Computed<boolean>;
public readonly hasPrevPage: ko.Observable<boolean>;
public readonly hasNextPage: ko.Observable<boolean>;
public readonly selection: ko.Computed<string>;
constructor(
private readonly apiService: ApiService,
private readonly router: Router,
private readonly routeHelper: RouteHelper
) {
this.detailsPageUrl = ko.observable();
this.allowSelection = ko.observable(false);
this.working = ko.observable();
this.selectedApi = ko.observable();
this.selectedApiName = ko.observable();
this.pattern = ko.observable();
this.tags = ko.observable([]);
this.page = ko.observable(1);
this.hasPrevPage = ko.observable();
this.hasNextPage = ko.observable();
this.hasPager = ko.computed(() => this.hasPrevPage() || this.hasNextPage());
this.apiGroups = ko.observableArray();
this.selection = ko.computed(() => {
const api = ko.unwrap(this.selectedApi);
return api ? api.versionedDisplayName : "Select API";
});
}
public allowSelection: ko.Observable<boolean>;
public detailsPageUrl: ko.Observable<string>;
public async initialize(): Promise<void> {
await this.resetSearch();
await this.checkSelection();
this.pattern
.extend({ rateLimit: { timeout: Constants.defaultInputDelayMs, method: "notifyWhenChangesStop" } })
.subscribe(this.resetSearch);
this.tags
.subscribe(this.resetSearch);
this.router.addRouteChangeListener(this.onRouteChange);
}
/**
* Initiates searching APIs.
*/
public async resetSearch(): Promise<void> {
this.page(1);
this.loadPageOfApis();
}
private async onRouteChange(): Promise<void> {
const apiName = this.routeHelper.getApiName();
if (apiName === this.selectedApiName()) {
return;
}
await this.checkSelection();
}
/**
* Loads page of APIs.
*/
public async loadPageOfApis(): Promise<void> {
try {
this.working(true);
const pageNumber = this.page() - 1;
const query: SearchQuery = {
pattern: this.pattern(),
tags: this.tags(),
skip: pageNumber * Constants.defaultPageSize,
take: Constants.defaultPageSize
};
const pageOfTagResources = await this.apiService.getApisByTags(query);
const apiGroups = pageOfTagResources.value;
this.apiGroups(apiGroups);
const nextLink = pageOfTagResources.nextLink;
this.hasPrevPage(pageNumber > 0);
this.hasNextPage(!!nextLink);
}
catch (error) {
throw new Error(`Unable to load APIs. ${error.message}`);
}
finally {
this.working(false);
}
}
private async checkSelection(): Promise<void> {
if (!this.allowSelection()) {
return;
}
const apiName = this.routeHelper.getApiName();
if (!apiName) {
return;
}
const api = await this.apiService.getApi(`apis/${apiName}`);
if (!api) {
return;
}
this.selectedApi(api);
this.selectedApiName(apiName);
}
public prevPage(): void {
this.page(this.page() - 1);
this.loadPageOfApis();
}
public nextPage(): void {
this.page(this.page() + 1);
this.loadPageOfApis();
}
public getReferenceUrl(api: Api): string {
return this.routeHelper.getApiReferenceUrl(api.name, this.detailsPageUrl());
}
public async onTagsChange(tags: Tag[]): Promise<void> {
this.tags(tags);
}
public dispose(): void {
this.router.removeRouteChangeListener(this.onRouteChange);
}
}