Skip to content

Commit 4898468

Browse files
committed
merge master
2 parents bf0a149 + 9fe6440 commit 4898468

File tree

72 files changed

+1430
-8774
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1430
-8774
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ jobs:
2525
steps:
2626
- name: Checkout code
2727
uses: actions/checkout@v3
28-
28+
- name: Setup Node.js 18
29+
uses: actions/setup-node@v3
30+
with:
31+
node-version: 18
2932
- name: Install
3033
run: npm install
3134

package-lock.json

Lines changed: 95 additions & 7643 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "apim-developer-portal",
3-
"version": "2.23.0",
3+
"version": "2.24.0",
44
"description": "API management developer portal",
55
"author": "Microsoft",
66
"license": "MIT",
@@ -78,12 +78,11 @@
7878
"@braintree/sanitize-url": "6.0.2",
7979
"@microsoft/applicationinsights-web": "^2.8.11",
8080
"@monaco-editor/loader": "^1.3.2",
81-
"@paperbits/azure": "0.1.580",
82-
"@paperbits/common": "0.1.580",
83-
"@paperbits/core": "0.1.580",
84-
"@paperbits/forms": "0.1.580",
85-
"@paperbits/prosemirror": "0.1.580",
86-
"@paperbits/styles": "0.1.580",
81+
"@paperbits/azure": "0.1.587",
82+
"@paperbits/common": "0.1.587",
83+
"@paperbits/core": "0.1.587",
84+
"@paperbits/forms": "0.1.587",
85+
"@paperbits/styles": "0.1.587",
8786
"@webcomponents/custom-elements": "1.5.1",
8887
"@webcomponents/shadydom": "^1.10.0",
8988
"client-oauth2": "4.3.3",

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

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,105 @@
11
<div class="form-group">
22
<div class="input-group" tabindex="0" aria-label="APIs">
3-
<div class="form-control text-truncate dropdown-input" data-toggle="dropdown" role="button">
3+
<div class="form-control text-truncate" data-toggle="dropdown" role="button">
44
<span data-bind="text: selection"></span>
55
<!-- ko if: selectedApi() -->
66
<!-- ko if: selectedApi().type === 'soap' -->
7-
<span class="badge api-type-badge">SOAP</span>
7+
<span class="badge badge-soap">SOAP</span>
88
<!-- /ko -->
99
<!-- ko if: selectedApi().type === 'websocket' -->
10-
<span class="badge api-type-badge">WebSocket</span>
10+
<span class="badge badge-soap">WebSocket</span>
1111
<!-- /ko -->
1212
<!-- ko if: selectedApi().type === 'graphql' -->
13-
<span class="badge api-type-badge">GraphQL</span>
13+
<span class="badge badge-soap">GraphQL</span>
1414
<!-- /ko -->
1515
<!-- /ko -->
1616
</div>
17-
<button class="dropdown-input-button" data-toggle="dropdown" aria-label="Expand APIs list">
17+
<button class="input-group-addon no-border" data-toggle="dropdown" aria-label="Expand APIs list">
1818
<i class="icon-emb icon-emb-chevron-down"></i>
1919
</button>
20-
<div class="dropdown dropdown-container">
21-
<input type="search" class="form-control form-control-light search-input" aria-label="Search" placeholder="Search APIs"
20+
<div class="dropdown">
21+
<input type="search" class="form-control form-control-light" aria-label="Search" placeholder="Search APIs"
2222
data-bind="textInput: pattern" autofocus />
2323

2424
<!-- <tag-input params="{ scope: 'apis', onChange: onTagsChange }"></tag-input> -->
2525

26+
<div>
27+
<label>Group by tag
28+
<div class="switch">
29+
<input type="checkbox" data-bind="checked: $component.groupByTag">
30+
<span class="slider round"></span>
31+
</div>
32+
</label>
33+
</div>
34+
2635
<!-- ko if: working -->
2736
<spinner class="block" role="presentation"></spinner>
2837
<!-- /ko -->
2938

3039
<!-- ko ifnot: working -->
40+
<!-- ko if: groupByTag -->
3141
<!-- ko foreach: { data: apiGroups, as: 'group' } -->
32-
<div class="tag-group">
33-
<span class="tag-card" role="group" data-bind="text: group.tag"></span>
42+
<div>
43+
<button class="tag-group tag-group-collapsible no-border"
44+
data-bind="class: $component.groupTagsExpanded().has(group.tag) ? '' : 'active', click: () => $component.groupTagCollapseToggle(group.tag)">
45+
<span class="tag-item" role="rowgroup" data-bind="text: group.tag"></span>
46+
<i class="icon-emb icon-emb-chevron-down"></i>
47+
</button>
48+
<!-- ko if: $component.groupTagsExpanded().has(group.tag) -->
49+
<div class="menu menu-vertical" role="list">
50+
<!-- ko foreach: { data: group.items, as: 'item' } -->
51+
<a href="#" role="listitem" class="nav-link text-truncate" data-dismiss
52+
data-bind="attr: { href: $component.getReferenceUrl(item) }, css: { 'nav-link-active': $component.selectedApiName() === item.name }">
53+
<span data-bind="text: item.displayName"></span>
54+
<!-- ko if: item.type === 'soap' -->
55+
<span class="badge badge-soap">SOAP</span>
56+
<!-- /ko -->
57+
<!-- ko if: item.type === 'websocket' -->
58+
<span class="badge badge-soap">WebSocket</span>
59+
<!-- /ko -->
60+
<!-- ko if: item.type === 'graphql' -->
61+
<span class="badge badge-soap">GraphQL</span>
62+
<!-- /ko -->
63+
<!-- ko if: item.apiVersion -->
64+
- <span data-bind="text: item.apiVersion"></span>
65+
<!-- /ko -->
66+
</a>
67+
<!-- /ko -->
68+
</div>
69+
<!-- /ko -->
3470
</div>
71+
<!-- /ko -->
72+
73+
<!-- ko if: apiGroups().length === 0 -->
74+
<div class="list-item-empty">No APIs found</div>
75+
<!-- /ko -->
76+
<!-- /ko -->
77+
78+
<!-- ko ifnot: groupByTag -->
79+
<!-- ko foreach: { data: apis, as: 'item' } -->
3580
<div class="menu menu-vertical" role="list">
36-
<!-- ko foreach: { data: group.items, as: 'item' } -->
3781
<a href="#" role="listitem" class="nav-link text-truncate" data-dismiss
3882
data-bind="attr: { href: $component.getReferenceUrl(item) }, css: { 'nav-link-active': $component.selectedApiName() === item.name }">
39-
<span class="widget-text" data-bind="text: item.displayName"></span>
83+
<span data-bind="text: item.displayName"></span>
4084
<!-- ko if: item.type === 'soap' -->
41-
<span class="badge api-type-badge">SOAP</span>
85+
<span class="badge badge-soap">SOAP</span>
4286
<!-- /ko -->
4387
<!-- ko if: item.type === 'websocket' -->
44-
<span class="badge api-type-badge">WebSocket</span>
88+
<span class="badge badge-soap">WebSocket</span>
4589
<!-- /ko -->
4690
<!-- ko if: item.type === 'graphql' -->
47-
<span class="badge api-type-badge">GraphQL</span>
91+
<span class="badge badge-soap">GraphQL</span>
4892
<!-- /ko -->
4993
<!-- ko if: item.apiVersion -->
50-
- <span class="widget-text" data-bind="text: item.apiVersion"></span>
94+
- <span data-bind="text: item.apiVersion"></span>
5195
<!-- /ko -->
5296
</a>
53-
<!-- /ko -->
5497
</div>
5598
<!-- /ko -->
5699

57-
<!-- ko if: apiGroups().length === 0 -->
58-
<div class="widget-text list-item-empty">No APIs found</div>
100+
<!-- ko if: apis().length === 0 -->
101+
<div class="list-item-empty">No APIs found</div>
102+
<!-- /ko -->
59103
<!-- /ko -->
60104

61105
<!-- ko ifnot: working -->

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

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { Tag } from "../../../../../models/tag";
1919
template: template
2020
})
2121
export class ApiListDropdown {
22+
public readonly apis: ko.ObservableArray<Api>;
2223
public readonly apiGroups: ko.ObservableArray<TagGroup<Api>>;
2324
public readonly selectedApi: ko.Observable<Api>;
2425
public readonly selectedApiName: ko.Observable<string>;
@@ -28,14 +29,20 @@ export class ApiListDropdown {
2829
public readonly pageNumber: ko.Observable<number>;
2930
public readonly totalPages: ko.Observable<number>;
3031
public readonly selection: ko.Computed<string>;
32+
public readonly groupByTag: ko.Observable<boolean>;
33+
public readonly groupTagsExpanded: ko.Observable<Set<string>>;
3134

3235
constructor(
3336
private readonly apiService: ApiService,
3437
private readonly router: Router,
3538
private readonly routeHelper: RouteHelper
3639
) {
40+
this.apis = ko.observableArray([]);
3741
this.detailsPageUrl = ko.observable();
3842
this.allowSelection = ko.observable(false);
43+
this.defaultGroupByTagToEnabled = ko.observable(false);
44+
this.groupByTag = ko.observable(false);
45+
this.groupTagsExpanded = ko.observable(new Set<string>());
3946
this.working = ko.observable();
4047
this.selectedApi = ko.observable();
4148
this.selectedApiName = ko.observable();
@@ -56,8 +63,14 @@ export class ApiListDropdown {
5663
@Param()
5764
public detailsPageUrl: ko.Observable<string>;
5865

66+
@Param()
67+
public defaultGroupByTagToEnabled: ko.Observable<boolean>;
68+
69+
5970
@OnMounted()
6071
public async initialize(): Promise<void> {
72+
this.groupByTag(this.defaultGroupByTagToEnabled());
73+
6174
await this.resetSearch();
6275
await this.checkSelection();
6376

@@ -68,6 +81,9 @@ export class ApiListDropdown {
6881
this.tags
6982
.subscribe(this.resetSearch);
7083

84+
this.groupByTag
85+
.subscribe(this.resetSearch);
86+
7187
this.router.addRouteChangeListener(this.onRouteChange);
7288
this.pageNumber.subscribe(this.loadPageOfApis);
7389
}
@@ -94,26 +110,39 @@ export class ApiListDropdown {
94110
* Loads page of APIs.
95111
*/
96112
public async loadPageOfApis(): Promise<void> {
113+
const pageNumber = this.pageNumber() - 1;
114+
115+
const query: SearchQuery = {
116+
pattern: this.pattern(),
117+
tags: this.tags(),
118+
skip: pageNumber * Constants.defaultPageSize,
119+
take: Constants.defaultPageSize
120+
};
121+
97122
try {
98123
this.working(true);
99124

100-
const pageNumber = this.pageNumber() - 1;
125+
let totalItems: number;
126+
127+
if (this.groupByTag()) {
128+
const pageOfTagResources = await this.apiService.getApisByTags(query);
129+
const apiGroups = pageOfTagResources.value;
101130

102-
const query: SearchQuery = {
103-
pattern: this.pattern(),
104-
tags: this.tags(),
105-
skip: pageNumber * Constants.defaultPageSize,
106-
take: Constants.defaultPageSize
107-
};
131+
this.apiGroups(apiGroups);
132+
totalItems = pageOfTagResources.count;
133+
}
134+
else {
135+
const pageOfApis = await this.apiService.getApis(query);
136+
const apis = pageOfApis ? pageOfApis.value : [];
108137

109-
const pageOfTagResources = await this.apiService.getApisByTags(query);
110-
const apiGroups = pageOfTagResources.value;
111-
this.apiGroups(apiGroups);
138+
this.apis(apis);
139+
totalItems = pageOfApis.count;
140+
}
112141

113-
this.totalPages(Math.ceil(pageOfTagResources.count / Constants.defaultPageSize));
142+
this.totalPages(Math.ceil(totalItems / Constants.defaultPageSize));
114143
}
115144
catch (error) {
116-
throw new Error(`Unable to load APIs. ${error.message}`);
145+
throw new Error(`Unable to load APIs. Error: ${error.message}`);
117146
}
118147
finally {
119148
this.working(false);
@@ -149,6 +178,12 @@ export class ApiListDropdown {
149178
this.tags(tags);
150179
}
151180

181+
public groupTagCollapseToggle(tag: string): void {
182+
const newSet = this.groupTagsExpanded();
183+
newSet.has(tag) ? newSet.delete(tag) : newSet.add(tag);
184+
this.groupTagsExpanded(newSet);
185+
}
186+
152187
@OnDestroyed()
153188
public dispose(): void {
154189
this.router.removeRouteChangeListener(this.onRouteChange);

src/components/custom-widget/listenForSecretsRequests.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export class ListenForSecretsRequests {
2323

2424
const managementApiUrl = await settingsProvider.getSetting<string>(SettingNames.managementApiUrl);
2525
const secrets: Secrets = {
26+
["parentLocation" as any]: JSON.parse(JSON.stringify(window.location)), // override typescript until new version of the package is released TODO fix
2627
managementApiUrl: Utils.ensureUrlArmified(managementApiUrl),
2728
apiVersion: managementApiVersion
2829
};

src/components/operations/operation-details/ko/runtime/authorization.html

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,44 @@
11
<!-- ko if: $component.authorizationServer() || $component.subscriptionKeyRequired() -->
22
<details open class="details-styled">
3-
<summary aria-label="Authorization">
4-
<h3 class="pt-0 console-title">
3+
<summary aria-label="Authorization">
4+
<h3 class="pt-0">
55
Authorization
6-
<i class="icon-emb icon-emb-chevron-down collapse-button"></i>
6+
<i class="icon-emb icon-emb-chevron-down"></i>
77
</h3>
88
</summary>
99

1010
<!-- ko if: $component.authorizationServer -->
1111
<div class="row flex flex-row">
1212
<div class="col-4">
13-
<label for="authServer" class="text-monospace form-label console-text"
14-
data-bind="text: $component.authorizationServer().displayName"></label>
13+
<label for="authServer" class="text-monospace form-label"
14+
data-bind="text: $component.authorizationServer().displayName"></label>
1515
</div>
1616
<div class="col-7">
1717
<div class="form-group">
18-
<select id="authServer" class="form-control input"
19-
data-bind="options: $component.authorizationServer().grantTypes, value: $component.selectedGrantType, optionsCaption: 'No auth'">
18+
<select id="authServer" class="form-control"
19+
data-bind="options: $component.authorizationServer().grantTypes, value: $component.selectedGrantType, optionsCaption: 'No auth'">
2020
</select>
2121
</div>
2222
</div>
2323
</div>
2424
<!-- ko if: $component.selectedGrantType() === 'password' && !$component.authenticated() -->
2525
<div class="row flex flex-row">
2626
<div class="col-4">
27-
<label for="username" class="text-monospace form-label console-text">Username</label>
27+
<label for="username" class="text-monospace form-label">Username</label>
2828
</div>
2929
<div class="col-7">
3030
<div class="form-group">
31-
<input type="text" id="username" class="form-control input" data-bind="textInput: $component.username" />
31+
<input type="text" id="username" class="form-control" data-bind="textInput: $component.username" />
3232
</div>
3333
</div>
3434
</div>
3535
<div class="row flex flex-row">
3636
<div class="col-4">
37-
<label for="password" class="text-monospace form-label console-text">Password</label>
37+
<label for="password" class="text-monospace form-label">Password</label>
3838
</div>
3939
<div class="col-7">
4040
<div class="form-group">
41-
<input type="password" id="password" class="form-control input" data-bind="textInput: $component.password" />
41+
<input type="password" id="password" class="form-control" data-bind="textInput: $component.password" />
4242
<span class="invalid-feedback" data-bind="text: $component.authorizationError"></span>
4343
</div>
4444
</div>
@@ -49,7 +49,7 @@ <h3 class="pt-0 console-title">
4949
<div class="col-7">
5050
<div class="form-group">
5151
<button class="button button-primary"
52-
data-bind="click: $component.authenticateOAuthWithPassword">Authorize</button>
52+
data-bind="click: $component.authenticateOAuthWithPassword">Authorize</button>
5353
</div>
5454
</div>
5555
</div>
@@ -61,14 +61,14 @@ <h3 class="pt-0 console-title">
6161
<!-- ko if: $component.subscriptionKeyRequired -->
6262
<div class="row flex flex-row">
6363
<div class="col-4">
64-
<label for="subscriptionKey " class="text-monospace form-label console-text">
64+
<label for="subscriptionKey" class="text-monospace form-label">
6565
Subscription key
6666
</label>
6767
</div>
6868
<div class="col-7">
6969
<div class="form-group">
7070
<!-- ko if: $component.products() && $component.products().length > 0 -->
71-
<select id="subscriptionKey" class="form-control input" data-bind="value: $component.selectedSubscriptionKey">
71+
<select id="subscriptionKey" class="form-control" data-bind="value: $component.selectedSubscriptionKey">
7272
<!-- ko foreach: { data: $component.products, as: 'product' } -->
7373
<optgroup data-bind="attr: { label: product.name }">
7474
<!-- ko foreach: { data: product.subscriptionKeys, as: 'subscriptionKey' } -->
@@ -79,8 +79,15 @@ <h3 class="pt-0 console-title">
7979
</select>
8080
<!-- /ko -->
8181
<!-- ko if: !$component.products() || $component.products().length === 0 -->
82-
<input id="subscriptionKey" type="text" class="form-control input" placeholder="subscription key"
83-
data-bind="textInput: $component.selectedSubscriptionKey" />
82+
<div class="input-group">
83+
<input id="subscriptionKey" class="form-control" placeholder="subscription key"
84+
data-bind="textInput: $component.selectedSubscriptionKey, attr: { type: subscriptionKeyRevealed() ? 'text' : 'password' }"
85+
aria-required="true" />
86+
<button data-bind="click: toggleSubscriptionKey" class="input-group-addon">
87+
<i
88+
data-bind="class: subscriptionKeyRevealed() ? 'icon-emb icon-emb-eye-fill' :'icon-emb icon-emb-eye'"></i>
89+
</button>
90+
</div>
8491
<!-- /ko -->
8592
</div>
8693
</div>

0 commit comments

Comments
 (0)