refactor: API-Details-Page design, fixed marketplace search and pagination
MODIFY
angular.json
angular.json
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss",
"src/themes/default.scss",
- "node_modules/swagger-ui-dist/swagger-ui.css"
+ "node_modules/swagger-ui-dist/swagger-ui.css",
+ "node_modules/simplebar/dist/simplebar.css"
],
"scripts": [
"node_modules/marked/lib/marked.js",
"node_modules/swagger-ui-dist/swagger-ui-bundle.js",
- "node_modules/swagger-ui-dist/swagger-ui-standalone-preset.js"
+ "node_modules/swagger-ui-dist/swagger-ui-standalone-preset.js",
+ "node_modules/simplebar/dist/simplebar.js"
]
},
"configurations": {

MODIFY
package-lock.json
package-lock.json
"schema-utils": "^2.7.0"
}
},
+ "@juggle/resize-observer": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.3.1.tgz",
+ "integrity": "sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw=="
+ },
"@ngtools/webpack": {
"version": "12.2.2",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.2.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
+ "can-use-dom": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/can-use-dom/-/can-use-dom-0.1.0.tgz",
+ "integrity": "sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo="
+ },
"caniuse-api": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
"core-js": {
"version": "3.16.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.0.tgz",
- "integrity": "sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g==",
- "dev": true
+ "integrity": "sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g=="
},
"core-js-compat": {
"version": "3.16.2",
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
- "dev": true
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
- "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
- "dev": true
+ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
},
"lodash.merge": {
"version": "4.6.2",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
+ "lodash.throttle": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+ "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
+ },
"lodash.truncate": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
+ "simplebar": {
+ "version": "5.3.5",
+ "resolved": "https://registry.npmjs.org/simplebar/-/simplebar-5.3.5.tgz",
+ "integrity": "sha512-mcTlXEiva8pSMdNEzeV3C1KyBHk7Sn2Pe46U1Uwo53dCuQqdJIK0bEJrIPs8W4/RqJquKIsC8Y1h7+aqOl8ccA==",
+ "requires": {
+ "@juggle/resize-observer": "^3.3.1",
+ "can-use-dom": "^0.1.0",
+ "core-js": "^3.0.1",
+ "lodash.debounce": "^4.0.8",
+ "lodash.memoize": "^4.1.2",
+ "lodash.throttle": "^4.1.1"
+ }
+ },
"slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",

MODIFY
package.json
package.json
"keycloak-js": "^15.0.2",
"ngx-markdown": "^12.0.1",
"rxjs": "~6.6.0",
+ "simplebar": "^5.3.5",
"swagger-ui-dist": "^4.0.0-beta.4",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"

MODIFY
src/app/app.module.ts
src/app/app.module.ts
-import { APP_INITIALIZER, NgModule } from '@angular/core';
+import {APP_INITIALIZER, NgModule, SecurityContext} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@@ -115,7 +115,9 @@ function initializeKeycloak(keycloakHelper: KeycloakHelperService) {
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
- MarkdownModule.forRoot(),
+ MarkdownModule.forRoot({
+ sanitize: SecurityContext.NONE
+ }),
FormsModule,
HttpClientModule,
ClipboardModule,

MODIFY
src/app/components/api-card-list/api-card-list.component.html
src/app/components/api-card-list/api-card-list.component.html
-<ng-container *ngIf="ready">
<div *ngIf="listType === 'api'" class="align">
<mat-form-field>
<mat-icon matPrefix color="primary">search</mat-icon>
/>
</mat-form-field>
</div>
-
+<ng-container *ngIf="ready">
<div id="grid">
<app-api-card
*ngFor="let api of apis"
class="api-card"
></app-api-card>
</div>
-
+</ng-container>
<div *ngIf="listType === 'api'" class="align">
<mat-paginator
[length]="totalSize"
>
</mat-paginator>
</div>
-</ng-container>

MODIFY
src/app/components/api-card/api-card.component.scss
src/app/components/api-card/api-card.component.scss
border-radius: 2px;
min-width: 24%;
height: 30%;
+ border: 1px solid rgba(0,0,0,0.1);
}
.api-card-header{

MODIFY
src/app/components/marketplace-api-description/marketplace-api-description.component.html
src/app/components/marketplace-api-description/marketplace-api-description.component.html
<mat-expansion-panel-header>
<mat-panel-title>
Version {{ api.version }} of {{ api.api.name }}
- <strong *ngIf="isLatest">[latest]</strong>
+ <strong *ngIf="isLatest" class="latest">[latest]</strong>
</mat-panel-title>
</mat-expansion-panel-header>
- <mat-card>
- <mat-card-header>
+ <div id="content-header">
+ <span id="icon">
<img
mat-card-avatar
alt="Logo"
src="https://github.com/apiman/apiman/raw/master/manager/ui/war/plugins/api-manager/img/about-logo.png"
/>
- <mat-card-title>{{ api.api.name }}</mat-card-title>
- <mat-card-subtitle>{{ api.api.description }}</mat-card-subtitle>
- </mat-card-header>
- </mat-card>
+ </span>
+ <p id="shortDescription">{{ markdown.substr(0,240) }}</p>
+ </div>
- <mat-grid-list cols="3" rowHeight="1:1">
- <mat-grid-tile colspan="2" class="grid-content">
- <div class="box">
+ <mat-grid-list cols="4" rowHeight="1:1">
+ <mat-grid-tile colspan="3" id="long-description-tile">
+ <div class="box" data-simplebar>
<markdown [data]="markdown"></markdown>
</div>
</mat-grid-tile>
- <mat-grid-tile colspan="1" class="grid-content">
- <mat-divider [vertical]="true"></mat-divider>
- <div class="box">
+ <mat-grid-tile colspan="1">
+ <div class="box" id="key-features">
<h1>Key Features</h1>
<mat-list>
<!--To-Do-->
</div>
</mat-grid-tile>
</mat-grid-list>
- <h2>Plans</h2>
+ <h2 id="plans-header">Plans</h2>
<app-plan-card-list></app-plan-card-list>
</mat-expansion-panel>

MODIFY
src/app/components/marketplace-api-description/marketplace-api-description.component.scss
src/app/components/marketplace-api-description/marketplace-api-description.component.scss
@@ -9,12 +9,59 @@ mat-divider {
margin-right: 2em;
}
+mat-panel-title {
+ font-size: 1.3em;
+
+ .latest {
+ margin-left: 1em;
+ }
+}
+
+#content-header {
+ display: flex;
+ margin-bottom: 1em;
+ width: 75%;
+
+ #icon {
+ margin: 2em 2em 0 2em;
+ }
+
+ #shortDescription {
+ margin-top: 2em;
+ }
+}
+
+mat-grid-list {
+ margin-bottom: 2em;
+}
+
+#long-description-tile {
+ border: 1px solid rgba(0,0,0,0.2);
+ background: rgba(0,0,0,0.02)
+}
+
+.box {
+ padding-left: 1%;
+ padding-right: 1%
+}
+
+#key-features {
+ margin-left: 2em;
+}
+
#docs-button{
margin-top: 4em;
+ width: 50%;
+}
+
+#plans-header {
+ margin: unset;
}
.mat-expansion-panel-header.mat-expanded,
.mat-expansion-panel-header.mat-expanded:hover,
.mat-expansion-panel-header.mat-expanded:focus {
- background: rgba(106, 116, 127, .2);
+ border-bottom: 1px;
+ border-bottom-style: solid;
+ border-bottom-color: rgba(0,0,0,0.12);
}

MODIFY
src/app/components/plan-card-list/plan-card-list.component.html
src/app/components/plan-card-list/plan-card-list.component.html
+<div id="plan-grid">
<app-plan-card *ngFor="let plan of plans" [plan]="plan"></app-plan-card>
+</div>

MODIFY
src/app/components/plan-card-list/plan-card-list.component.scss
src/app/components/plan-card-list/plan-card-list.component.scss
+#plan-grid {
+ margin-right: 2%;
+ display: grid;
+ justify-content: space-between;
+ align-items: flex-start;
+ grid-template-columns: repeat(auto-fit, 420px);
+ grid-column-gap: 16px;
+ grid-row-gap: 32px;
+}
+
+@media screen and (max-width: 1745px) {
+ #grid {
+ grid-template-columns: repeat(auto-fit, 370px);
+ }
+}
+
+@media screen and (max-width: 1495px) {
+ #grid {
+ grid-template-columns: repeat(auto-fit, 350px);
+ }
+}

MODIFY
src/app/components/plan-card/plan-card.component.html
src/app/components/plan-card/plan-card.component.html
<mat-card class="plan-card">
- <mat-card-header>
- <mat-card-title>{{ plan.title }}</mat-card-title>
- <mat-card-subtitle>{{ plan.subtitle }}</mat-card-subtitle>
+ <mat-card-header class="card-header">
+ <mat-card-title class="card-header-content">{{ plan.title }}</mat-card-title>
+ <mat-card-subtitle class="card-header-content">{{ plan.subtitle }}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<mat-list>
</ng-container>
</mat-list>
</mat-card-content>
- <mat-card-actions>
- <button mat-raised-button [routerLink]="['/api-signup', orgId, apiId]">
+ <mat-card-actions id="plan-card-actions">
+ <button id="sign-up-button" mat-raised-button color="primary" [routerLink]="['/api-signup', orgId, apiId]">
SIGN UP
</button>
</mat-card-actions>

MODIFY
src/app/components/plan-card/plan-card.component.scss
src/app/components/plan-card/plan-card.component.scss
@@ -2,6 +2,11 @@ mat-card {
margin-top: 30px;
}
+mat-card-actions {
+ text-align: center;
+ margin-bottom: unset;
+}
+
::ng-deep .mat-grid-tile-content{
align-items: flex-start !important;
}
@@ -15,5 +20,18 @@ p {
}
.plan-card{
- width: 25vw;
+ width: 100%;
+ border: 1px solid rgba(0,0,0,0.1);
+}
+
+.card-header {
+ justify-content: center
+}
+
+.card-header-content {
+ text-align: center;
+}
+
+#sign-up-button {
+ width: 50%;
}

MODIFY
src/app/services/plan/plan.service.ts
src/app/services/plan/plan.service.ts
@@ -22,7 +22,37 @@ export class PlanService {
},
{
title: 'Quota',
- configuration: '500 MB per Day',
+ configuration: '500 MB per day',
+ },
+ ],
+ },
+ {
+ id: '2',
+ title: 'Small Business',
+ subtitle: 'For small business just getting started',
+ policies: [
+ {
+ title: 'Rate Limiting',
+ configuration: '5000 Requests per day',
+ },
+ {
+ title: 'Quota',
+ configuration: '2 GB per day',
+ },
+ ],
+ },
+ {
+ id: '3',
+ title: 'Corporate Plan',
+ subtitle: 'For heavy usage business partners',
+ policies: [
+ {
+ title: 'Rate Limiting',
+ configuration: '1000 Requests per minute',
+ },
+ {
+ title: 'Quota',
+ configuration: '10 GB per hour',
},
],
},

refactor: API-Details-Page design, fixed marketplace search and pagination