apim-developer-portal1
Version:
API management developer portal
245 lines (198 loc) • 8.08 kB
text/typescript
import * as ko from "knockout";
import * as Constants from "../../../../../constants";
import template from "./operation-list.html";
import { Router } from "@paperbits/common/routing";
import { Component, RuntimeComponent, OnMounted, OnDestroyed, Param } from "@paperbits/common/ko/decorators";
import { ApiService } from "../../../../../services/apiService";
import { Operation } from "../../../../../models/operation";
import { SearchQuery } from "../../../../../contracts/searchQuery";
import { TagGroup } from "../../../../../models/tagGroup";
import { RouteHelper } from "../../../../../routing/routeHelper";
import { Tag } from "../../../../../models/tag";
import { Utils } from "../../../../../utils";
export class OperationList {
private searchRequest: SearchQuery;
public readonly selectedApiName: ko.Observable<string>;
public readonly selectedOperationName: ko.Observable<string>;
public readonly operations: ko.ObservableArray<Operation>;
public readonly working: ko.Observable<boolean>;
public readonly groupByTag: ko.Observable<boolean>;
public readonly operationGroups: ko.ObservableArray<TagGroup<Operation>>;
public readonly pattern: ko.Observable<string>;
public readonly tags: ko.Observable<Tag[]>;
public readonly pageNumber: ko.Observable<number>;
public readonly hasPrevPage: ko.Observable<boolean>;
public readonly hasNextPage: ko.Observable<boolean>;
public readonly hasPager: ko.Computed<boolean>;
public readonly tagScope: 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.operations = ko.observableArray();
this.operationGroups = ko.observableArray();
this.selectedApiName = ko.observable();
this.selectedOperationName = ko.observable().extend(<any>{ acceptChange: this.allowSelection });
this.working = ko.observable(false);
this.groupByTag = ko.observable(false);
this.defaultGroupByTagToEnabled = ko.observable(false);
this.pattern = ko.observable();
this.tags = ko.observable([]);
this.pageNumber = ko.observable(1);
this.hasNextPage = ko.observable();
this.hasPrevPage = ko.observable();
this.hasPager = ko.computed(() => this.hasPrevPage() || this.hasNextPage());
this.tagScope = ko.computed(() =>
this.selectedApiName()
? `apis/${this.selectedApiName()}`
: "");
}
public allowSelection: ko.Observable<boolean>;
public defaultGroupByTagToEnabled: ko.Observable<boolean>;
public detailsPageUrl: ko.Observable<string>;
public async initialize(): Promise<void> {
const apiName = this.routeHelper.getApiName();
const operationName = this.routeHelper.getOperationName();
this.selectedApiName(apiName);
this.selectedOperationName(operationName);
this.groupByTag(this.defaultGroupByTagToEnabled());
if (this.selectedApiName()) {
await this.loadOperations();
}
this.pattern
.extend({ rateLimit: { timeout: Constants.defaultInputDelayMs, method: "notifyWhenChangesStop" } })
.subscribe(this.resetSearch);
this.tags
.subscribe(this.resetSearch);
this.groupByTag
.subscribe(this.loadOperations);
this.router.addRouteChangeListener(this.onRouteChange);
}
private async onRouteChange(): Promise<void> {
const apiName = this.routeHelper.getApiName();
const operationName = this.routeHelper.getOperationName();
if (apiName !== this.selectedApiName()) {
this.selectedApiName(apiName);
this.selectedOperationName(null);
await this.resetSearch();
return;
}
if (operationName !== this.selectedOperationName()) {
this.selectedOperationName(operationName);
}
}
public async loadOperations(): Promise<void> {
if (this.groupByTag()) {
this.operationGroups([]);
this.searchRequest = { pattern: this.pattern(), tags: this.tags(), grouping: "tag" };
}
else {
this.operations([]);
this.searchRequest = { pattern: this.pattern(), tags: this.tags(), grouping: "none" };
}
try {
this.working(true);
if (this.groupByTag()) {
await this.loadOfOperationsByTag();
}
else {
await this.loadPageOfOperations();
}
if (this.allowSelection() && !this.selectedOperationName()) {
this.selectFirstOperation();
}
}
catch (error) {
throw new Error(`Unable to load operations: Error: ${error.message}`);
}
finally {
this.working(false);
}
}
private async loadOfOperationsByTag(): Promise<void> {
this.searchRequest.skip = (this.pageNumber() - 1) * Constants.defaultPageSize;
const pageOfOperationsByTag = await this.apiService.getOperationsByTags(this.selectedApiName(), this.searchRequest);
const operationGroups = pageOfOperationsByTag.value;
this.operationGroups(operationGroups);
this.hasPrevPage(this.pageNumber() > 1);
this.hasNextPage(!!pageOfOperationsByTag.nextLink);
}
private async loadPageOfOperations(): Promise<void> {
const apiName = this.selectedApiName();
if (!apiName) {
return;
}
this.searchRequest.skip = (this.pageNumber() - 1) * Constants.defaultPageSize;
const pageOfOperations = await this.apiService.getOperations(`apis/${apiName}`, this.searchRequest);
this.operations(pageOfOperations.value);
this.hasPrevPage(this.pageNumber() > 1);
this.hasNextPage(!!pageOfOperations.nextLink);
}
private selectFirstOperation(): void {
let operationName;
if (this.groupByTag()) {
const groups = this.operationGroups();
if (groups.length < 1 || groups[0].items.length < 1) {
return;
}
operationName = groups[0].items[0].name;
}
else {
const operations = this.operations();
if (operations.length < 1) {
return;
}
operationName = operations[0].name;
}
this.selectedOperationName(operationName);
const operationUrl = this.routeHelper.getOperationReferenceUrl(this.selectedApiName(), operationName, this.detailsPageUrl());
this.router.navigateTo(operationUrl);
}
public getReferenceUrl(operation: Operation): string {
const apiName = this.routeHelper.getApiName();
return this.routeHelper.getOperationReferenceUrl(apiName, operation.name, this.detailsPageUrl());
}
public async resetSearch(): Promise<void> {
this.pageNumber(1);
this.loadOperations();
}
public prevPage(): void {
this.pageNumber(this.pageNumber() - 1);
if (this.groupByTag()) {
this.loadOfOperationsByTag();
}
else {
this.loadPageOfOperations();
}
}
public nextPage(): void {
this.pageNumber(this.pageNumber() + 1);
if (this.groupByTag()) {
this.loadOfOperationsByTag();
}
else {
this.loadPageOfOperations();
}
}
public async onTagsChange(tags: Tag[]): Promise<void> {
this.tags(tags);
}
public dispose(): void {
this.router.removeRouteChangeListener(this.onRouteChange);
}
}