Skip to content

Commit f5d4e1d

Browse files
authored
Added pagination component. (#1578)
1 parent 107b541 commit f5d4e1d

30 files changed

+358
-937
lines changed

src/apim.runtime.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import { TenantService } from "./services/tenantService";
7373
import { UsersService } from "./services/usersService";
7474
import { ApimSettingsProvider } from "./configuration/apimSettingsProvider";
7575
import { AccessTokenRefrsher } from "./authentication/accessTokenRefresher";
76+
import { Pagination } from "./components/pagination/pagination";
7677

7778
export class ApimRuntimeModule implements IInjectorModule {
7879
public register(injector: IInjector): void {
@@ -137,6 +138,7 @@ export class ApimRuntimeModule implements IInjectorModule {
137138
injector.bindSingleton("viewStack", ViewStack);
138139
injector.bindSingleton("sessionManager", DefaultSessionManager);
139140
injector.bind("tagInput", TagInput);
140-
injector.bindToCollection("autostart", AccessTokenRefrsher)
141+
injector.bindToCollection("autostart", AccessTokenRefrsher);
142+
injector.bind("pagination", Pagination);
141143
}
142144
}

src/components/apis/api-products/ko/runtime/api-products-tiles.html

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,11 @@ <h3>
3838
</div>
3939
<!-- /ko -->
4040

41+
<!-- ko ifnot: working -->
42+
<!-- ko if: totalPages() > 1 -->
4143
<div class="cards-footer">
42-
<!-- ko if: hasPager -->
43-
<ul class="pagination" role="navigation" aria-label="Pagination">
44-
<!-- ko if: hasPrevPage -->
45-
<li class="page-item">
46-
<a href="#" class="page-link" role="button" aria-label="Previous page"
47-
data-bind="click: prevPage, enable: hasPrevPage">
48-
<i class="icon-emb icon-emb-chevron-left"></i>
49-
</a>
50-
</li>
51-
<!-- /ko -->
52-
<li class="page-item">
53-
<span class="page-link" data-bind="text: page"></span>
54-
</li>
55-
<!-- ko if: hasNextPage -->
56-
<li class="page-item">
57-
<a href="#" class="page-link" role="button" aria-label="Next page"
58-
data-bind="click: nextPage, enable: hasNextPage">
59-
<i class="icon-emb icon-emb-chevron-right"></i>
60-
</a>
61-
</li>
62-
<!-- /ko -->
63-
</ul>
64-
<!-- /ko -->
44+
<pagination params="{ pageNumber: pageNumber, totalPages: totalPages }"></pagination>
6545
</div>
46+
<!-- /ko -->
47+
<!-- /ko -->
6648
</div>

src/components/apis/api-products/ko/runtime/api-products-tiles.ts

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@ export class ApiProductsTiles {
2020
public readonly selectedApiName: ko.Observable<string>;
2121
public readonly working: ko.Observable<boolean>;
2222
public readonly pattern: ko.Observable<string>;
23-
public readonly page: ko.Observable<number>;
24-
public readonly hasPager: ko.Computed<boolean>;
25-
public readonly hasPrevPage: ko.Observable<boolean>;
26-
public readonly hasNextPage: ko.Observable<boolean>;
23+
public readonly pageNumber: ko.Observable<number>;
24+
public readonly totalPages: ko.Observable<number>;
25+
2726
private lastPattern: string;
2827

2928
constructor(
@@ -36,10 +35,8 @@ export class ApiProductsTiles {
3635
this.selectedApiName = ko.observable();
3736
this.working = ko.observable();
3837
this.pattern = ko.observable();
39-
this.page = ko.observable(1);
40-
this.hasPrevPage = ko.observable();
41-
this.hasNextPage = ko.observable();
42-
this.hasPager = ko.computed(() => this.hasPrevPage() || this.hasNextPage());
38+
this.pageNumber = ko.observable(1);
39+
this.totalPages = ko.observable(0);
4340
}
4441

4542
@Param()
@@ -48,16 +45,19 @@ export class ApiProductsTiles {
4845
@OnMounted()
4946
public async initialize(): Promise<void> {
5047
const apiName = this.routeHelper.getApiName();
48+
5149
if (apiName) {
5250
this.selectedApiName(apiName);
53-
await this.loadData();
51+
await this.loadPageOfProducts();
5452
}
5553

5654
this.router.addRouteChangeListener(this.onRouteChange);
5755

5856
this.pattern
5957
.extend({ rateLimit: { timeout: Constants.defaultInputDelayMs, method: "notifyWhenChangesStop" } })
6058
.subscribe(this.searchProducts);
59+
60+
this.pageNumber.subscribe(this.loadPageOfProducts);
6161
}
6262

6363
private async onRouteChange(): Promise<void> {
@@ -68,23 +68,22 @@ export class ApiProductsTiles {
6868
}
6969

7070
this.selectedApiName(apiName);
71-
await this.loadData();
71+
await this.loadPageOfProducts();
7272
}
7373

7474
/**
7575
* Initiates searching products.
7676
*/
7777
public async searchProducts(): Promise<void> {
78-
this.page(1);
79-
await this.loadData();
78+
this.pageNumber(1);
79+
await this.loadPageOfProducts();
8080
}
8181

8282
/**
8383
* Loads page of products.
8484
*/
85-
public async loadData(): Promise<void> {
86-
87-
const pageNumber = this.page() - 1;
85+
public async loadPageOfProducts(): Promise<void> {
86+
const pageNumber = this.pageNumber() - 1;
8887

8988
const query: SearchQuery = {
9089
pattern: this.pattern(),
@@ -95,11 +94,10 @@ export class ApiProductsTiles {
9594
try {
9695
this.working(true);
9796
const apiName = this.selectedApiName();
98-
const itemsPage = await this.apiService.getApiProductsPage(apiName, query);
97+
const pageOfProducts = await this.apiService.getApiProductsPage(apiName, query);
9998
this.lastPattern = this.pattern();
100-
this.hasPrevPage(pageNumber > 0);
101-
this.hasNextPage(!!itemsPage.nextLink);
102-
this.products(itemsPage.value);
99+
this.products(pageOfProducts.value);
100+
this.totalPages(Math.ceil(pageOfProducts.count / Constants.defaultPageSize));
103101
}
104102
catch (error) {
105103
throw new Error(`Unable to load API products. Error: ${error.message}`);
@@ -113,16 +111,6 @@ export class ApiProductsTiles {
113111
return this.routeHelper.getProductReferenceUrl(product.name, this.detailsPageUrl());
114112
}
115113

116-
public prevPage(): void {
117-
this.page(this.page() - 1);
118-
this.loadData();
119-
}
120-
121-
public nextPage(): void {
122-
this.page(this.page() + 1);
123-
this.loadData();
124-
}
125-
126114
@OnDestroyed()
127115
public dispose(): void {
128116
this.router.removeRouteChangeListener(this.searchProducts);

src/components/apis/api-products/ko/runtime/api-products.html

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,30 +46,10 @@
4646

4747
<!-- /ko -->
4848

49-
<!-- ko if: hasPager -->
5049
<!-- ko ifnot: working -->
50+
<!-- ko if: $component.totalPages() > 1 -->
5151
<div class="table-footer">
52-
<ul class="pagination justify-content-center" role="navigation" aria-label="Pagination">
53-
<!-- ko if: hasPrevPage -->
54-
<li>
55-
<a href="#" class="page-link" role="button" aria-label="Previous page"
56-
data-bind="click: prevPage, enable: hasPrevPage">
57-
<i class="icon-emb icon-emb-chevron-left"></i>
58-
</a>
59-
</li>
60-
<!-- /ko -->
61-
<li>
62-
<span class="page-link" data-bind="text: page"></span>
63-
</li>
64-
<!-- ko if: hasNextPage -->
65-
<li>
66-
<a href="#" class="page-link" role="button" aria-label="Next page"
67-
data-bind="click: nextPage, enable: hasNextPage">
68-
<i class="icon-emb icon-emb-chevron-right"></i>
69-
</a>
70-
</li>
71-
<!-- /ko -->
72-
</ul>
52+
<pagination params="{ pageNumber: $component.pageNumber, totalPages: $component.totalPages }"></pagination>
7353
</div>
7454
<!-- /ko -->
7555
<!-- /ko -->

src/components/apis/api-products/ko/runtime/api-products.ts

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ export class ApiProducts {
2020
public readonly selectedApiName: ko.Observable<string>;
2121
public readonly working: ko.Observable<boolean>;
2222
public readonly pattern: ko.Observable<string>;
23-
public readonly page: ko.Observable<number>;
24-
public readonly hasPager: ko.Computed<boolean>;
25-
public readonly hasPrevPage: ko.Observable<boolean>;
26-
public readonly hasNextPage: ko.Observable<boolean>;
23+
public readonly pageNumber: ko.Observable<number>;
24+
public readonly totalPages: ko.Observable<number>;
2725
private lastPattern: string;
2826

2927
constructor(
@@ -36,10 +34,8 @@ export class ApiProducts {
3634
this.selectedApiName = ko.observable();
3735
this.working = ko.observable();
3836
this.pattern = ko.observable();
39-
this.page = ko.observable(1);
40-
this.hasPrevPage = ko.observable();
41-
this.hasNextPage = ko.observable();
42-
this.hasPager = ko.computed(() => this.hasPrevPage() || this.hasNextPage());
37+
this.pageNumber = ko.observable(1);
38+
this.totalPages = ko.observable(0);
4339
}
4440

4541
@Param()
@@ -48,16 +44,19 @@ export class ApiProducts {
4844
@OnMounted()
4945
public async initialize(): Promise<void> {
5046
const apiName = this.routeHelper.getApiName();
47+
5148
if (apiName) {
5249
this.selectedApiName(apiName);
53-
await this.loadData();
50+
await this.loadPageOfProducts();
5451
}
5552

5653
this.router.addRouteChangeListener(this.onRouteChange);
5754

5855
this.pattern
5956
.extend({ rateLimit: { timeout: Constants.defaultInputDelayMs, method: "notifyWhenChangesStop" } })
6057
.subscribe(this.searchProducts);
58+
59+
this.pageNumber.subscribe(this.loadPageOfProducts);
6160
}
6261

6362
private async onRouteChange(): Promise<void> {
@@ -68,23 +67,22 @@ export class ApiProducts {
6867
}
6968

7069
this.selectedApiName(apiName);
71-
await this.loadData();
70+
await this.loadPageOfProducts();
7271
}
7372

7473
/**
7574
* Initiates searching products.
7675
*/
7776
public async searchProducts(): Promise<void> {
78-
this.page(1);
79-
await this.loadData();
77+
this.pageNumber(1);
78+
await this.loadPageOfProducts();
8079
}
8180

8281
/**
8382
* Loads page of products.
8483
*/
85-
public async loadData(): Promise<void> {
86-
87-
const pageNumber = this.page() - 1;
84+
public async loadPageOfProducts(): Promise<void> {
85+
const pageNumber = this.pageNumber() - 1;
8886

8987
const query: SearchQuery = {
9088
pattern: this.pattern(),
@@ -95,11 +93,10 @@ export class ApiProducts {
9593
try {
9694
this.working(true);
9795
const apiName = this.selectedApiName();
98-
const itemsPage = await this.apiService.getApiProductsPage(apiName, query);
96+
const pageOfProducts = await this.apiService.getApiProductsPage(apiName, query);
9997
this.lastPattern = this.pattern();
100-
this.hasPrevPage(pageNumber > 0);
101-
this.hasNextPage(!!itemsPage.nextLink);
102-
this.products(itemsPage.value);
98+
this.products(pageOfProducts.value);
99+
this.totalPages(Math.ceil(pageOfProducts.count / Constants.defaultPageSize));
103100
}
104101
catch (error) {
105102
throw new Error(`Unable to load API products. Error: ${error.message}`);
@@ -113,16 +110,6 @@ export class ApiProducts {
113110
return this.routeHelper.getProductReferenceUrl(product.name, this.detailsPageUrl());
114111
}
115112

116-
public prevPage(): void {
117-
this.page(this.page() - 1);
118-
this.loadData();
119-
}
120-
121-
public nextPage(): void {
122-
this.page(this.page() + 1);
123-
this.loadData();
124-
}
125-
126113
@OnDestroyed()
127114
public dispose(): void {
128115
this.router.removeRouteChangeListener(this.searchProducts);

src/components/apis/list-of-apis/ko/runtime/api-list-dropdown.html

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
<div class="dropdown-container collapsible">
2-
<div class="form-control" tabindex="0" role="button" data-toggle="dropdown" aria-label="APIs" >
2+
<div class="form-control" tabindex="0" role="button" data-toggle="dropdown" aria-label="APIs">
33
<div class="input-group">
44
<div class="input">
55
<span data-bind="text: selection"></span>
66
<!-- ko if: selectedApi() -->
7-
<!-- ko if: selectedApi().type === 'soap' -->
8-
<span class="badge badge-soap">SOAP</span>
9-
<!-- /ko -->
10-
<!-- ko if: selectedApi().type === 'websocket' -->
11-
<span class="badge badge-soap">WebSocket</span>
12-
<!-- /ko -->
13-
<!-- ko if: selectedApi().type === 'graphql' -->
14-
<span class="badge badge-soap">GraphQL</span>
15-
<!-- /ko -->
7+
<!-- ko if: selectedApi().type === 'soap' -->
8+
<span class="badge badge-soap">SOAP</span>
9+
<!-- /ko -->
10+
<!-- ko if: selectedApi().type === 'websocket' -->
11+
<span class="badge badge-soap">WebSocket</span>
12+
<!-- /ko -->
13+
<!-- ko if: selectedApi().type === 'graphql' -->
14+
<span class="badge badge-soap">GraphQL</span>
15+
<!-- /ko -->
1616
<!-- /ko -->
1717
</div>
1818
<div class="input-group-append">
@@ -72,28 +72,10 @@
7272
<div class="list-item-empty">No APIs found</div>
7373
<!-- /ko -->
7474

75-
<!-- ko if: hasPager -->
76-
<ul class="pagination justify-content-center" role="navigation" aria-label="Pagination">
77-
<!-- ko if: hasPrevPage -->
78-
<li class="page-item">
79-
<a href="#" class="page-link" role="button" aria-label="Previous page"
80-
data-bind="click: prevPage, enable: hasPrevPage">
81-
<i class="icon-emb icon-emb-chevron-left"></i>
82-
</a>
83-
</li>
84-
<!-- /ko -->
85-
<li class="page-item">
86-
<span class="page-link" data-bind="text: page"></span>
87-
</li>
88-
<!-- ko if: hasNextPage -->
89-
<li class="page-item">
90-
<a href="#" class="page-link" role="button" aria-label="Next page"
91-
data-bind="click: nextPage, enable: hasNextPage">
92-
<i class="icon-emb icon-emb-chevron-right"></i>
93-
</a>
94-
</li>
95-
<!-- /ko -->
96-
</ul>
75+
<!-- ko ifnot: working -->
76+
<!-- ko if: $component.totalPages() > 1 -->
77+
<pagination params="{ pageNumber: $component.pageNumber, totalPages: $component.totalPages }"></pagination>
78+
<!-- /ko -->
9779
<!-- /ko -->
9880

9981
<!-- /ko -->

0 commit comments

Comments
 (0)