Last active
September 4, 2020 12:26
-
-
Save jweisman/7cb7b298a191206dfa985cd7f9fb5df6 to your computer and use it in GitHub Desktop.
Ex Libris Cloud App Angular Component for use with an API Proxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h1>Using a Proxy to Access Data from Other Institutions</h1> | |
<div class="loading-shade" *ngIf="loading"><mat-spinner diameter="50"></mat-spinner></div> | |
<mat-form-field appearance="fill"> | |
<mat-label>Intitution</mat-label> | |
<mat-select #instcode> | |
<mat-option *ngFor="let inst of instcodes" [value]="inst">{{inst}}</mat-option> | |
</mat-select> | |
</mat-form-field> | |
<button mat-flat-button color="primary" (click)="test(instcode.value)">Test connection</button> | |
<mat-form-field appearance="fill"> | |
<mat-label>Username</mat-label> | |
<input matInput #username> | |
</mat-form-field> | |
<button mat-flat-button color="primary" (click)="proxyGet(instcode.value, username.value)">Retrieve user from the remote institution</button> | |
<section> | |
<mat-card class="example-card"> | |
<mat-card-header> | |
<mat-card-title>API Result</mat-card-title> | |
</mat-card-header> | |
<mat-card-content> | |
<textarea #apiResultArea [value]="apiResult | json"></textarea> | |
</mat-card-content> | |
<mat-card-actions> | |
<button mat-raised-button color="primary" (click)="proxyPut(apiResultArea.value, instcode.value, username.value)" | |
[disabled]="!apiResult || loading">Update in the remote institution</button> | |
</mat-card-actions> | |
</mat-card> | |
</section> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mat-form-field { | |
width: 100%; | |
margin-top: 10px; | |
} | |
section { | |
margin-top: 20px; | |
} | |
textarea { | |
padding: 2px; | |
border-width: 1px; | |
$width: calc(100% - 6px); | |
width: $width; | |
max-width: $width; | |
height: 150px; | |
font-family: monospace; | |
display: block; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, OnInit } from '@angular/core'; | |
import { HttpMethod } from '@exlibris/exl-cloudapp-angular-lib'; | |
import { ToastrService } from 'ngx-toastr'; | |
import { RestClient } from './rest-client'; | |
import { finalize } from 'rxjs/operators'; | |
@Component({ | |
selector: 'app-proxy', | |
templateUrl: './proxy.component.html', | |
styleUrls: ['./proxy.component.scss'] | |
}) | |
export class ProxyComponent implements OnInit { | |
apiResult: any; | |
loading = false; | |
constructor( | |
private toastr: ToastrService, | |
private rest: RestClient, | |
) { } | |
ngOnInit() { } | |
test(instCode: string) { | |
this.loading = true; | |
this.rest.call('/conf/general', instCode) | |
.pipe(finalize(()=>this.loading=false)) | |
.subscribe({ | |
next: config => this.toastr.success(`Successfully connected to "${config.institution.desc}"`), | |
error: e => this.toastr.error('Could not connect to proxy: ' + e.message) | |
}) | |
} | |
proxyGet(instCode: string, userName: string) { | |
this.loading = true; | |
this.rest.call(`/users/${userName}`, instCode) | |
.pipe(finalize(()=>this.loading=false)) | |
.subscribe({ | |
next: results => this.apiResult = results, | |
error: e => this.toastr.error('Could not retrieve data: ' + e.message) | |
}); | |
} | |
proxyPut(requestBody: any, instCode: string, userName: string) { | |
this.loading = true; | |
let req = { | |
url: `/users/${userName}`, | |
method: HttpMethod.PUT, | |
requestBody: requestBody | |
}; | |
this.rest.call(req, instCode) | |
.pipe(finalize(()=>this.loading=false)) | |
.subscribe({ | |
next: () => this.toastr.success('Success'), | |
error: e => this.toastr.error('Could not retrieve data: ' + e.message) | |
}) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; | |
import { Injectable } from '@angular/core'; | |
import { Observable, throwError } from 'rxjs'; | |
import { environment } from '../../environments/environment'; | |
import { CloudAppEventsService, HttpMethod } from '@exlibris/exl-cloudapp-angular-lib'; | |
import { catchError } from 'rxjs/operators'; | |
enum AllowedHeader { | |
ACCEPT = "Accept", | |
CONTENT_TYPE = "Content-Type", | |
FOR_INST_CODE = "X-For-InstCode", | |
} | |
export interface Request { | |
url: string; | |
method?: HttpMethod; | |
headers?: { | |
[header in AllowedHeader]?: string; | |
}; | |
queryParams?: { | |
[param: string]: any; | |
}; | |
requestBody?: any; | |
} | |
export function restClientCreator(http: HttpClient, eventsService: CloudAppEventsService) { | |
return new RestClient(http, eventsService); | |
} | |
const PROXY_URL = environment.proxyUrl; | |
@Injectable() | |
export class RestClient { | |
private _token: string; | |
public constructor(public http: HttpClient, private eventsService: CloudAppEventsService) { | |
this.eventsService.getAuthToken().subscribe(token => this._token = token); | |
} | |
call<T = any>(request: string | Request, instCode: string): Observable<T> { | |
let req: Request = typeof request == 'string' ? { url: request, method: HttpMethod.GET } : request; | |
if (!req.headers) req.headers = {}; | |
let headers = new HttpHeaders({ | |
'content-type': req.headers["Content-Type"] || 'application/json', | |
'accept': req.headers.Accept || 'application/json', | |
'authorization': `Bearer ${this._token}`, | |
'x-for-instcode': instCode | |
}); | |
let params = new HttpParams(req.queryParams); | |
const url = PROXY_URL + req.url; | |
const options = { headers, params }; | |
switch (req.method) { | |
case HttpMethod.GET: | |
return wrapError(this.http.get<T>(url, options)); | |
case HttpMethod.PUT: | |
return wrapError(this.http.put<T>(url, req.requestBody, options)); | |
case HttpMethod.POST: | |
return wrapError(this.http.post<T>(url, req.requestBody, options)); | |
case HttpMethod.DELETE: | |
return wrapError(this.http.delete<T>(url, options)); | |
} | |
} | |
} | |
const wrapError = (obs: Observable<any>): Observable<any> => { | |
return obs.pipe( | |
catchError(err=>{ | |
if (err.error && err.error.errorList) { | |
err.message = err.error.errorList.error[0].errorMessage | |
}; | |
return throwError(err); | |
}) | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this component to your Cloud App and add the rest client to the
app.module.ts
file as follows: