Merge pull request #94 from fastenhealth/elasticsearch-pagination

This commit is contained in:
Jason Kulatunga 2023-03-12 14:42:04 -07:00 committed by GitHub
commit 2c7e23a22f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2853 changed files with 36071 additions and 100 deletions

View File

@ -47,11 +47,10 @@ make backend-test
# Start Development Environment
To run Fasten from source, you'll need to create 3 separate processes:
To run Fasten from source, you'll need to create 2 separate processes:
- Angular Frontend
- Go Backend
- CouchDB Database
First we'll create a development config file (`config.dev.yaml`)

View File

@ -1,16 +1,17 @@
version: "3.9"
services:
couchdb:
fasten:
# NOTE: only developers need to build Fasten from source
# For production, use the pre-built image from GitHub Packages
# ghcr.io/fastenhealth/fasten-onprem:main
build:
context: .
dockerfile: Dockerfile
# environment:
# - COUCHDB_USER=admin
# - COUCHDB_PASSWORD=password
args:
- FASTEN_ENV=prod
# - FASTEN_ENV=sandbox
ports:
- "9090:8080"
- "5984:5984"
volumes:
- ./.couchdb/data:/opt/couchdb/data
- ./.couchdb/config:/opt/couchdb/etc/local.d
- ./db:/opt/fasten/db
# - ./config.example.yaml:/opt/fasten/config/config.yaml

View File

@ -36,7 +36,6 @@
"bootstrap": "^4.4.1",
"chart.js": "2.9.4",
"fhirpath": "^3.3.0",
"fuse.js": "^6.6.2",
"humanize-duration": "^3.27.3",
"idb": "^7.1.0",
"jose": "^4.10.4",
@ -44,6 +43,7 @@
"ng2-charts": "^2.3.0",
"ngx-dropzone": "^3.1.0",
"ngx-highlightjs": "^7.0.1",
"ngx-infinite-scroll": "^14.0.0",
"ngx-moment": "^6.0.2",
"rxjs": "~6.5.4",
"tslib": "^2.0.0",

View File

@ -30,7 +30,7 @@ import { MedicalHistoryComponent } from './pages/medical-history/medical-history
import { ReportLabsComponent } from './pages/report-labs/report-labs.component';
import {PipesModule} from './pipes/pipes.module';
import { ResourceCreatorComponent } from './pages/resource-creator/resource-creator.component';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
@NgModule({
declarations: [
@ -62,6 +62,7 @@ import { ResourceCreatorComponent } from './pages/resource-creator/resource-crea
HighlightModule,
MomentModule,
PipesModule,
InfiniteScrollModule
],
providers: [
{

View File

@ -1,4 +1,6 @@
export class MetadataSource {
platform_type: string
brand_logo?: string
source_type: string
display: string
category: string[]

View File

@ -1,4 +1,7 @@
export class LighthouseSourceMetadata {
import {MetadataSource} from '../fasten/metadata-source';
export class LighthouseSourceMetadata extends MetadataSource {
authorization_endpoint: string
token_endpoint: string
introspection_endpoint: string

View File

@ -0,0 +1,21 @@
import {MetadataSource} from '../fasten/metadata-source';
export class LighthouseSourceSearch {
_scroll_id: string;
took: number;
timed_out: boolean;
hits: {
total: {
value: number;
relation: string;
};
max_score: number;
hits: {
_index: string;
_type: string;
_id: string;
_score: number;
_source: MetadataSource;
}[];
};
}

View File

@ -43,6 +43,7 @@ export class DashboardComponent implements OnInit {
this.metadataSource = metadataSource
this.metadataSource["manual"] = {
"source_type": "manual",
"platform_type": "manual",
"display": "Manual",
"category": ["Manual"],
"hidden": false,

View File

@ -32,7 +32,7 @@
<div (click)="openModal(contentModalRef, sourceInfo)" class="card-body">
<div class="h-100 d-flex align-items-center">
<img [src]="'assets/sources/'+sourceInfo?.metadata['source_type']+'.png'" [alt]="sourceInfo?.metadata.display" class="img-fluid">
<img [src]="'assets/sources/'+(sourceInfo.metadata.brand_logo ? sourceInfo.metadata.brand_logo : sourceInfo.metadata.source_type+'.png')" [alt]="sourceInfo?.metadata.display" class="img-fluid">
</div>
<div *ngIf="status[sourceInfo.metadata?.source_type]" class="progress">
<div [style.width]="status[sourceInfo?.metadata?.source_type] == 'authorize' ? '33%' : '66%'" class="bg-indigo progress-bar progress-bar-striped progress-bar-animated" role="progressbar"></div>
@ -71,34 +71,38 @@
<!-- Search -->
<div class="row row-sm sticky-top pt-2" style="position:sticky;">
<div class="col-lg-4">
<div class="col-lg-8">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="search-prefix">Search</span>
</div>
<input (keyup)="searchTermChanged($event)" type="text" class="form-control" placeholder="Search Term">
<input (keyup)="searchTermUpdate.next($event.target.value)" type="text" class="form-control" placeholder="Search Term">
<div class="input-group-append">
<span class="input-group-text">{{this.availableSourceList.length}} of {{this.totalAvailableSourceList}} results</span>
</div>
</div><!-- input-group -->
</div><!-- col -->
<!-- <div class="col-lg-4">-->
<!-- <div class="d-flex text-center">-->
<!-- <small>{{this.availableSourceList.length}} of {{this.totalAvailableSourceList}} sources</small>-->
<!-- </div>-->
<!-- </div>-->
</div>
<div *ngIf="!loading else isLoadingTemplate" class="row row-sm">
<div *ngIf="!loading else isLoadingTemplate" class="row row-sm"
infiniteScroll
[infiniteScrollDistance]="2"
[infiniteScrollThrottle]="50"
(scrolled)="onScroll()"
>
<div *ngFor="let sourceData of availableSourceList" (click)="connectHandler($event, sourceData.metadata.source_type)" class="col-sm-3 mg-b-20 px-3">
<div class="card h-100 d-flex align-items-center justify-content-center mt-3 mt-3 rounded-0 cursor-pointer" [ngClass]="{'card-disable': sourceData.metadata.hidden}">
<div class="card-body d-flex align-items-center">
<img style="max-height: 130px;" [src]="'assets/sources/'+sourceData.metadata.source_type+'.png'" [alt]="metadataSources[sourceData.metadata.source_type].display" class="img-fluid">
<img style="max-height: 130px;" [src]="'assets/sources/'+(sourceData.metadata.brand_logo ? sourceData.metadata.brand_logo : sourceData.metadata.source_type+'.png')" [alt]="sourceData.metadata.display" class="img-fluid">
<div *ngIf="status[sourceData.metadata.source_type]" class="progress">
<div [style.width]="status[sourceData.metadata.source_type] == 'authorize' ? '33%' : '66%'" class="bg-indigo progress-bar progress-bar-striped progress-bar-animated" role="progressbar"></div>
</div>
</div>
<div class="card-footer text-center p-1" style="width:100%">
<small class="tx-gray-700">
{{metadataSources[sourceData.metadata.source_type].display}}
{{sourceData.metadata.display}}
</small>
</div>
</div>

View File

@ -10,8 +10,9 @@ import {Location} from '@angular/common';
import {ToastService} from '../../services/toast.service';
import {ToastNotification, ToastType} from '../../models/fasten/toast';
import {environment} from '../../../environments/environment';
import {forkJoin} from 'rxjs';
import Fuse from 'fuse.js'
import {BehaviorSubject, forkJoin, Subject} from 'rxjs';
import {LighthouseSourceSearch} from '../../models/lighthouse/lighthouse-source-search';
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
// If you dont import this angular will import the wrong "Location"
export const sourceConnectWindowTimeout = 24*5000 //wait 2 minutes (5 * 24 = 120)
@ -32,8 +33,6 @@ export class MedicalSourcesComponent implements OnInit {
environment_name = environment.environment_name
status: { [name: string]: string } = {}
metadataSources: {[name:string]: MetadataSource} = {}
connectedSourceList: SourceListItem[] = [] //source's are populated for this list
availableSourceList: SourceListItem[] = []
totalAvailableSourceList: number = 0
@ -42,8 +41,10 @@ export class MedicalSourcesComponent implements OnInit {
closeResult = '';
modalSelectedSourceListItem:SourceListItem = null;
searchIndex = null
searchTerm: string = ""
scrollId: string = ""
scrollComplete: boolean = false
searchTermUpdate = new BehaviorSubject<string>("");
showHidden: boolean = false
constructor(
private lighthouseApi: LighthouseService,
@ -57,29 +58,20 @@ export class MedicalSourcesComponent implements OnInit {
ngOnInit(): void {
this.loading = true
forkJoin([this.lighthouseApi.getLighthouseSourceMetadataMap(false), this.fastenApi.getSources()]).subscribe(results => {
forkJoin([this.lighthouseApi.findLighthouseSources("", "", this.showHidden), this.fastenApi.getSources()]).subscribe(results => {
this.loading = false
//handle connected sources sources
const connectedSources = results[1] as Source[]
forkJoin(connectedSources.map((source) => this.lighthouseApi.getLighthouseSource(source.source_type))).subscribe((connectedMetadata) => {
for(const ndx in connectedSources){
this.connectedSourceList.push({source: connectedSources[ndx], metadata: connectedMetadata[ndx]})
}
})
//handle source metadata map response
this.metadataSources = results[0] as {[name:string]: MetadataSource}
//handle sources
const sourceList = results[1] as Source[]
for (const sourceType in this.metadataSources) {
let isConnected = false
for(const connectedSource of sourceList){
if(connectedSource.source_type == sourceType){
this.connectedSourceList.push({source: connectedSource, metadata: this.metadataSources[sourceType]})
isConnected = true
break
}
}
if(!isConnected){
//this source has not been found in the connected list, lets add it to the available list.
this.availableSourceList.push({metadata: this.metadataSources[sourceType]})
}
}
this.populateAvailableSourceList(results[0] as LighthouseSourceSearch)
//check if we've just started connecting a "source_type"
@ -97,55 +89,59 @@ export class MedicalSourcesComponent implements OnInit {
this.callback(callbackSourceType).then(console.log)
}
this.totalAvailableSourceList = this.availableSourceList.length
//setup Search
const options = {
// isCaseSensitive: false,
// includeScore: false,
// shouldSort: true,
// includeMatches: false,
findAllMatches: true,
// minMatchCharLength: 1,
// location: 0,
// threshold: 0.6,
// distance: 100,
// useExtendedSearch: false,
// ignoreLocation: false,
// ignoreFieldNorm: false,
// fieldNormWeight: 1,
keys: [
"metadata.display",
"metadata.category",
"metadata.source_type"
]
};
this.searchIndex = new Fuse(this.availableSourceList, options);
}, err => {
this.loading = false
})
//register a callback for when the search term changes
this.searchTermUpdate
.pipe(
debounceTime(200),
distinctUntilChanged(),
)
.subscribe(value => {
console.log("search term changed:", value)
//reset available sources
this.availableSourceList = []
this.scrollId = ""
this.scrollComplete = false
this.totalAvailableSourceList = 0
this.lighthouseApi.findLighthouseSources(value, this.scrollId, this.showHidden)
.subscribe((results) => {
this.populateAvailableSourceList(results)
})
});
}
public searchTermChanged($event):void {
this.searchTerm = $event.target.value
console.log("search term changed:", )
private populateAvailableSourceList(results: LighthouseSourceSearch): void {
this.totalAvailableSourceList = results.hits.total.value
if(results.hits.hits.length == 0){
this.scrollComplete = true
console.log("scroll complete")
return
}
this.scrollId = results._scroll_id
this.availableSourceList = this.availableSourceList.concat(results.hits.hits.map((result) => {
return {metadata: result._source}
}).filter((item) => {
return !this.connectedSourceList.find((connectedItem) => connectedItem.metadata.source_type == item.metadata.source_type)
}))
}
let searchResults
if(this.searchTerm){
searchResults = this.searchIndex.search(this.searchTerm).map((result) => {
return result.item
public onScroll(): void {
if(this.scrollComplete){
return
}
this.lighthouseApi.findLighthouseSources(this.searchTermUpdate.getValue(), this.scrollId, this.showHidden)
.subscribe((results) => {
this.populateAvailableSourceList(results)
})
}
else {
//emtpy search term, show all (original) values.
searchResults = this.searchIndex.getIndex().docs
}
this.availableSourceList = searchResults
console.log(this.availableSourceList)
}
/**
@ -222,7 +218,14 @@ export class MedicalSourcesComponent implements OnInit {
console.log("NO PATIENT ID present, decoding jwt to extract patient")
//const introspectionResp = await Oauth.introspectionRequest(as, client, payload.access_token)
//console.log(introspectionResp)
payload.patient = this.jwtDecode(payload.id_token)["profile"].replace(/^(Patient\/)/,'')
let decodedIdToken = this.jwtDecode(payload.id_token)
//nextGen uses fhirUser instead of profile.
payload.patient = decodedIdToken["profile"] || decodedIdToken["fhirUser"]
if(payload.patient){
payload.patient = payload.patient.replace(/^(Patient\/)/,'')
}
}

View File

@ -9,6 +9,7 @@ import * as Oauth from '@panva/oauth4webapi';
import {SourceState} from '../models/fasten/source-state';
import {MetadataSource} from '../models/fasten/metadata-source';
import {uuidV4} from '../../lib/utils/uuid';
import {LighthouseSourceSearch} from '../models/lighthouse/lighthouse-source-search';
@Injectable({
providedIn: 'root'
@ -18,6 +19,27 @@ export class LighthouseService {
constructor(private _httpClient: HttpClient) {
}
public findLighthouseSources(searchTerm: string, scrollId= "", showHidden = false): Observable<LighthouseSourceSearch> {
const endpointUrl = new URL(`${environment.lighthouse_api_endpoint_base}/list/search`);
if(showHidden){
endpointUrl.searchParams.set('show_hidden', 'true');
}
if(scrollId){
endpointUrl.searchParams.set('scroll_id', scrollId);
}
if(searchTerm){
endpointUrl.searchParams.set('query', searchTerm);
}
return this._httpClient.get<ResponseWrapper>(endpointUrl.toString())
.pipe(
map((response: ResponseWrapper) => {
console.log("Metadata RESPONSE", response)
return response.data as LighthouseSourceSearch
})
);
}
public getLighthouseSourceMetadataMap(showHidden = false): Observable<{[name: string]: MetadataSource}> {
const endpointUrl = new URL(`${environment.lighthouse_api_endpoint_base}/list`);
if(showHidden){

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="408px" height="104px" viewBox="0 0 408 104" enable-background="new 0 0 408 104" xml:space="preserve">
<g>
<defs>
<rect id="SVGID_1_" x="4" y="4" width="400" height="96"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" overflow="visible"/>
</clipPath>
<g clip-path="url(#SVGID_2_)">
<rect x="-3.115" y="-9.004" fill="#005ea6" width="430.518" height="109.004"/>
<rect x="-1.113" y="82.424" fill="#FFFFFF" width="430.518" height="4.291"/>
<rect x="-3.115" y="86.715" fill="#C41623" width="430.518" height="50.596"/>
</g>
</g>
<path fill="#FFFFFF" d="M404,4v96H4V4H404 M408,0h-4H4H0v4v96v4h4h400h4v-4V4V0L408,0z"/>
<g>
<path fill="#FFFFFF" d="M76.748,65.242c0-1.219,0-42.146,0-42.146h-13.23c0,0,0,39.166,0,40.318
c0,6.277-5.355,10.016-12.926,10.016c-8.645,0-13.391-3.738-13.391-10.094c0-1.148,0-40.24,0-40.24H23.975c0,0,0,40.006,0,41.381
c0,14.164,11.242,19.82,26.309,19.82c10.399,0,18.778-2.844,23.152-8.595v7.829h11.801V71.223h-9.428
C76.419,69.417,76.748,67.427,76.748,65.242z"/>
<path fill="#FFFFFF" d="M139.99,66.094c0-10.334-6.27-15.307-18.285-17.604c-1.379-0.23-5.359-1.074-8.41-1.684
c-9.871-1.988-13.469-3.746-13.469-8.184c0-3.445,1.992-5.66,12.012-5.66c7.648,0,10.938,1.758,12.543,5.125
c0.461,0.922,0.844,2.293,0.844,2.98h13.617c0-1.535-0.609-3.82-1.379-5.812c-3.055-7.648-10.172-12.926-25.32-12.926
c-17.746,0-26.004,6.879-26.004,17.137c0,10.023,7.262,15.453,19.047,17.67c2.676,0.531,7.113,1.379,8.875,1.688
c9.781,1.836,12.312,3.59,12.312,8.566c0,3.98-3.211,6.496-12.398,6.496c-8.027,0-12.004-1.523-13.688-5.043
c-0.461-0.914-0.844-2.75-0.844-3.824H85.826c0,1.219,0.23,4.207,0.852,6.191c2.438,7.652,9.016,13.16,27.297,13.16
c11.484,0,19.128-3.223,23.008-8.555v7.715h11.797V71.223h-9.529C139.729,69.62,139.99,67.912,139.99,66.094z"/>
<polygon fill="#FFFFFF" points="191.463,62.031 168.209,23.096 152.834,23.096 152.834,83.531 165.455,83.531 165.455,42.6
189.783,83.531 204.084,83.531 204.084,23.096 191.463,23.096 "/>
<path fill="#FFFFFF" d="M233.311,37.896c-9.73,0-17.43,3.645-21.727,9.887c-2.508,3.566-3.891,8.102-3.891,13.209
c0,5.598,1.215,10.055,3.41,13.539c4.293,6.812,12.312,9.727,22.207,9.727c7.211,0,12.648-1.539,16.543-4.047
c4.453-2.848,7.047-6.895,8.094-11.191h-12.727c-0.238,0.977-1.375,2.43-3.719,3.484c-1.871,0.812-4.543,1.461-8.191,1.461
c-4.863,0-8.504-1.293-10.379-3.32c-1.535-1.703-2.43-3.238-2.43-5.277h37.773c0.727-6.719-0.488-13.127-3.812-17.99
C250.498,41.619,243.521,37.896,233.311,37.896z M220.42,56.863c0-1.303,1.219-3.971,2.758-5.35
c2.191-1.945,5.598-3.168,10.211-3.168c4.867,0,7.945,1.547,9.816,3.41c1.617,1.703,2.172,3.805,2.172,5.107H220.42z"/>
<path fill="#FFFFFF" d="M325.107,38.951l-10.449,33.146l-10.055-33.146h-14.422l-9.805,33.146l-10.699-33.146h-13.535l15.953,44.58
h15.414c0,0,8.758-25.613,8.836-27.158c0.082-0.488,0.559-3.129,0.559-3.129s0.492,2.641,0.578,3.211
c0.156,1.463,8.918,27.076,8.918,27.076h15.316l16.129-44.58H325.107z"/>
<path fill="#FFFFFF" d="M368.623,56.455c-1.535-0.242-7.777-1.141-10.371-1.535c-6.32-0.977-7.707-1.703-7.707-3.648
c0-2.102,2.113-3.246,9.25-3.246c6.156,0,8.504,1.062,9.398,2.273c0.398,0.566,0.57,1.941,0.57,2.426h12.562
c0-0.891-0.246-3.637-0.812-5.348c-2.266-6.398-9.977-9.559-22.207-9.559c-14.352,0-21.477,5.188-21.477,13.121
c0,8.521,4.699,12.814,14.508,14.189c2.672,0.406,8.023,1.219,9.719,1.461c6.566,0.973,9.246,1.535,9.246,4.055
c0,2.59-2.27,3.887-9.645,3.887c-7.055,0-10.457-0.566-11.27-2.672c-0.324-0.895-0.402-1.703-0.402-2.273H337.1
c0,1.461,0.078,2.68,0.48,4.461c1.867,7.297,8.996,10.289,24.078,10.289c15.398,0,22.367-4.699,22.367-13.938
C384.025,62.051,379.318,58.078,368.623,56.455z"/>
<path fill="#FFFFFF" d="M215.045,35.334c1.156,0,2.406-0.195,3.344-0.586c0.172,0.152,0.367,0.32,0.57,0.465h4.621
c-0.879-0.699-1.797-1.406-2.605-2.004c0.973-0.926,1.59-2.242,1.648-3.766h-3.406c-0.035,0.695-0.258,1.34-0.656,1.844
c-0.699-0.574-1.398-1.199-1.945-1.645c1.211-0.75,2.391-1.82,2.43-3.359c0-0.082,0.016-0.418,0-0.527
c-0.086-1.473-1.434-2.812-3.746-2.812c-2.531,0-3.996,1.414-4.062,2.906c0,0.195,0,0.477,0,0.617
c0.02,0.734,0.289,1.566,0.996,2.566c-1.438,0.676-2.75,1.535-2.781,2.918c0,0.156-0.012,0.438,0,0.629
C209.557,34.807,212.158,35.334,215.045,35.334z M214.447,26.338c0.051-0.43,0.277-0.797,0.816-0.797
c0.559,0,0.75,0.352,0.77,0.754c0,0.043,0,0.172,0,0.246c-0.039,0.473-0.473,0.875-1.094,1.242
c-0.301-0.395-0.473-0.781-0.492-1.117C214.432,26.564,214.432,26.436,214.447,26.338z M214.006,31.068
c0.512,0.516,1.234,1.078,1.93,1.676c-0.301,0.078-0.719,0.121-1.062,0.121c-1.266,0-1.809-0.223-1.809-0.809
C213.064,31.713,213.451,31.381,214.006,31.068z"/>
<path fill="#FFFFFF" d="M234.068,35.213c0,0,1.859-6.984,1.879-7.391c0.047,0.391,1.863,7.391,1.863,7.391h4.062l3.406-12.145
h-3.605c0,0-1.824,7.5-1.824,7.883c0-0.383-1.844-7.883-1.844-7.883h-3.82c0,0-1.797,7.5-1.797,7.883
c0-0.383-1.855-7.883-1.855-7.883h-3.973l3.477,12.145H234.068z"/>
<path fill="#FFFFFF" d="M251.893,35.396c4.445,0,6.473-2.098,6.473-6.363c0-4.059-1.891-6.184-6.473-6.184
c-4.492,0-6.48,2.355-6.48,6.23C245.412,33.229,247.436,35.396,251.893,35.396z M251.893,25.721c2.059,0,2.719,0.992,2.719,3.398
c0,2.707-0.992,3.43-2.699,3.43c-1.777,0-2.707-0.855-2.707-3.43C249.205,26.678,249.912,25.721,251.893,25.721z"/>
<path fill="#FFFFFF" d="M263.678,31.104h2.512l2.133,4.109h4.172l-2.84-4.863c0.562-0.125,1.109-0.504,1.492-1.152
c0.324-0.539,0.535-1.312,0.535-2.289c0-1.137-0.227-1.953-0.699-2.566c-0.613-0.809-1.664-1.273-3.281-1.273h-7.688v12.145h3.664
V31.104z M263.713,25.928h3.133c0.539,0,0.895,0.117,1.074,0.508c0.105,0.18,0.133,0.508,0.133,0.781
c0,0.242-0.047,0.566-0.141,0.781c-0.137,0.301-0.527,0.406-0.984,0.406h-3.215V25.928z"/>
<polygon fill="#FFFFFF" points="283.842,32.209 278.01,32.209 278.01,23.068 274.252,23.068 274.252,35.213 283.842,35.213 "/>
<path fill="#FFFFFF" d="M296.709,33.451c0.672-1.008,0.855-1.957,0.855-4.547c0-2.211-0.145-3.223-0.891-4.254
c-0.75-1.043-2.117-1.582-4.312-1.582h-6.664v12.145h6.844C294.725,35.213,295.979,34.572,296.709,33.451z M289.393,32.346v-6.438
h2.344c0.918,0,1.363,0.137,1.836,0.656c0.297,0.344,0.383,1.469,0.383,2.34c0,0.988-0.035,2.363-0.352,2.75
c-0.418,0.492-0.918,0.691-1.867,0.691H289.393z"/>
<path fill="#FFFFFF" d="M307.408,31.104h2.508l2.145,4.109h4.164l-2.844-4.863c0.559-0.125,1.117-0.504,1.496-1.152
c0.32-0.539,0.535-1.312,0.535-2.289c0-1.137-0.227-1.953-0.699-2.566c-0.613-0.809-1.664-1.273-3.281-1.273h-7.684v12.145h3.66
V31.104z M307.443,25.928h3.125c0.535,0,0.902,0.117,1.09,0.508c0.094,0.18,0.117,0.508,0.117,0.781
c0,0.242-0.039,0.566-0.133,0.781c-0.137,0.301-0.539,0.406-0.992,0.406h-3.207V25.928z"/>
<polygon fill="#FFFFFF" points="328.525,32.381 321.791,32.381 321.791,30.576 328.213,30.576 328.213,27.689 321.791,27.689
321.791,25.928 328.459,25.928 328.459,23.068 318.135,23.068 318.135,35.213 328.525,35.213 "/>
<path fill="#FFFFFF" d="M334.65,31.412c0,0,3.285,0.027,3.742,0.02c1.492-0.031,2.656-0.418,3.355-1.234
c0.605-0.645,0.898-1.598,0.898-2.945c0-1.508-0.383-2.555-1.094-3.168c-0.664-0.691-1.707-1.016-3.172-1.016h-7.473v12.145h3.742
V31.412z M334.604,25.893h2.965c0.613,0,0.965,0.188,1.172,0.574c0.113,0.164,0.164,0.477,0.164,0.855
c0,0.355-0.031,0.582-0.152,0.801c-0.176,0.336-0.523,0.57-1.23,0.57c-0.02,0-2.918,0-2.918,0V25.893z"/>
<path fill="#FFFFFF" d="M350.436,35.396c4.438,0,6.469-2.098,6.469-6.363c0-4.059-1.895-6.184-6.469-6.184
c-4.5,0-6.488,2.355-6.488,6.23C343.947,33.229,345.971,35.396,350.436,35.396z M350.436,25.721c2.059,0,2.711,0.992,2.711,3.398
c0,2.707-0.992,3.43-2.707,3.43c-1.773,0-2.695-0.855-2.695-3.43C347.744,26.678,348.443,25.721,350.436,25.721z"/>
<path fill="#FFFFFF" d="M362.256,31.104h2.512l2.141,4.109h4.16l-2.836-4.863c0.57-0.125,1.113-0.504,1.504-1.152
c0.312-0.539,0.531-1.312,0.531-2.289c0-1.137-0.238-1.953-0.703-2.566c-0.617-0.809-1.68-1.273-3.289-1.273h-7.684v12.145h3.664
V31.104z M362.287,25.928h3.133c0.531,0,0.898,0.117,1.082,0.508c0.094,0.18,0.121,0.508,0.121,0.781
c0,0.242-0.043,0.566-0.133,0.781c-0.133,0.301-0.539,0.406-0.996,0.406h-3.207V25.928z"/>
<polygon fill="#FFFFFF" points="375.213,35.213 378.998,35.213 378.998,25.99 382.881,25.99 382.881,23.068 371.361,23.068
371.361,25.99 375.213,25.99 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="130" height="42" viewBox="0 0 130 42"><defs><style>.cls-1{fill:#00a651;}.cls-2{fill:#00aeef;}.cls-3{fill:#16becf;}.cls-4{fill:#3dba93;}.cls-5{fill:#0eb46e;}</style></defs><title>AHNlogo_SVG_fixedsize</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="AHN_Logo_RGB" data-name="AHN Logo RGB"><g id="Group_21960" data-name="Group 21960"><g id="Group_13369" data-name="Group 13369"><path id="Path_6217" data-name="Path 6217" class="cls-1" d="M61.59,13c.3,1.18.59,2.37.89,3.25l2,6.31-5.84.2,2-6.31a34,34,0,0,0,1-3.45M58,6.31,48.54,35.79h6.52l2.48-8.09h8.3l2.57,8.09h6.72L65.45,6.31Z"/></g><path id="Path_6218" data-name="Path 6218" class="cls-1" d="M95.1,17.65h-11V6.31H77.8V35.79h6.33V23.27h11V35.79h6.23V6.31H95.1Z"/><g id="Group_13370" data-name="Group 13370"><path id="Path_6219" data-name="Path 6219" class="cls-1" d="M124,6.31V16.76c0,3.35.1,6.31.3,9.07a53.49,53.49,0,0,0-3.75-7L113,6.41h-6.72V35.89h5.84V25.14c0-3.75,0-6.8-.1-9.76,1.08,2.27,2.47,4.83,4.15,7.69l7.61,12.72H130V6.31Z"/><path id="Path_6220" data-name="Path 6220" class="cls-2" d="M16.51,34.41A66.83,66.83,0,0,1,21.85,42a65.58,65.58,0,0,1,5.34-7.59,57.26,57.26,0,0,0-5.34-7.59,78.46,78.46,0,0,0-5.34,7.59"/><path id="Path_6221" data-name="Path 6221" class="cls-3" d="M22.74,25.93a46.51,46.51,0,0,1,5.34,7.49,57.17,57.17,0,0,1,6.52-6.31,55.56,55.56,0,0,0-5.24-7.49,50,50,0,0,0-6.62,6.31m-1.68,0a51.18,51.18,0,0,0-5.34,7.49,57.26,57.26,0,0,0-6.53-6.31,56.2,56.2,0,0,1,5.24-7.49,50.09,50.09,0,0,1,6.63,6.31"/><path id="Path_6222" data-name="Path 6222" class="cls-1" d="M30.05,5.32A43.05,43.05,0,0,0,22,0a36.06,36.06,0,0,0-8.11,5.32A69.05,69.05,0,0,1,22,10.75a46.4,46.4,0,0,1,8.1-5.43"/><path id="Path_6223" data-name="Path 6223" class="cls-4" d="M21.85,12.22a59,59,0,0,0-6.72,6.41,59.88,59.88,0,0,1,6.72,6.31,50.82,50.82,0,0,1,6.72-6.31,52.21,52.21,0,0,0-6.72-6.41M5.44,13.6A68.71,68.71,0,0,0,0,21.2a49.78,49.78,0,0,1,8.11,5,52.4,52.4,0,0,1,5.24-7.49Q9.53,16,5.44,13.6m25,5.23a83.51,83.51,0,0,1,7.91-5.13,69.92,69.92,0,0,1,5.44,7.59,50.1,50.1,0,0,0-8.11,5,53.22,53.22,0,0,0-5.24-7.49"/><path id="Path_6224" data-name="Path 6224" class="cls-5" d="M20.86,11.44a71.27,71.27,0,0,0-8.11-5.33,66.86,66.86,0,0,0-6.42,6.51,70.17,70.17,0,0,1,7.91,5.22,50.07,50.07,0,0,1,6.62-6.4m2.08,0A70.27,70.27,0,0,1,31,6.11a67,67,0,0,1,6.43,6.51,68.41,68.41,0,0,0-7.91,5.22,51.33,51.33,0,0,0-6.62-6.4"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Some files were not shown because too many files have changed in this diff Show More