|
|
|
|
@ -1,105 +1,109 @@
|
|
|
|
|
<div class="container">
|
|
|
|
|
<div class="d-md-block d-none mb-5 row">
|
|
|
|
|
<div class="mb-5 row">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<h2 class="text-center" i18n>Data Providers</h2>
|
|
|
|
|
<mat-card appearance="outlined">
|
|
|
|
|
<mat-card-content>
|
|
|
|
|
@for (dataProvider of dataProviders; track dataProvider.name) {
|
|
|
|
|
<div class="align-items-center d-flex my-3">
|
|
|
|
|
@if (dataProvider.name === 'Ghostfolio') {
|
|
|
|
|
<div class="w-50">
|
|
|
|
|
<div class="d-flex">
|
|
|
|
|
<gf-asset-profile-icon
|
|
|
|
|
class="mr-1"
|
|
|
|
|
[url]="dataProvider.url"
|
|
|
|
|
<table class="gf-table w-100" mat-table [dataSource]="dataSource">
|
|
|
|
|
<ng-container matColumnDef="name">
|
|
|
|
|
<th *matHeaderCellDef class="px-1 py-2" mat-header-cell>
|
|
|
|
|
<ng-container i18n>Name</ng-container>
|
|
|
|
|
</th>
|
|
|
|
|
<td *matCellDef="let element" class="px-1 py-2" mat-cell>
|
|
|
|
|
<div class="d-flex align-items-center">
|
|
|
|
|
<gf-asset-profile-icon class="mr-1" [url]="element.url" />
|
|
|
|
|
<div>
|
|
|
|
|
@if (isGhostfolioDataProvider(element)) {
|
|
|
|
|
<a
|
|
|
|
|
class="align-items-center d-inline-flex"
|
|
|
|
|
target="_blank"
|
|
|
|
|
[href]="pricingUrl"
|
|
|
|
|
>
|
|
|
|
|
Ghostfolio Premium
|
|
|
|
|
<gf-premium-indicator
|
|
|
|
|
class="d-inline-block ml-1"
|
|
|
|
|
[enableLink]="false"
|
|
|
|
|
/>
|
|
|
|
|
<div>
|
|
|
|
|
<a
|
|
|
|
|
class="align-items-center d-inline-flex"
|
|
|
|
|
target="_blank"
|
|
|
|
|
[href]="pricingUrl"
|
|
|
|
|
@if (isGhostfolioApiKeyValid === false) {
|
|
|
|
|
<span class="badge badge-warning ml-2" i18n
|
|
|
|
|
>Early Access</span
|
|
|
|
|
>
|
|
|
|
|
Ghostfolio Premium
|
|
|
|
|
<gf-premium-indicator
|
|
|
|
|
class="d-inline-block ml-1"
|
|
|
|
|
[enableLink]="false"
|
|
|
|
|
/>
|
|
|
|
|
@if (isGhostfolioApiKeyValid === false) {
|
|
|
|
|
<span class="badge badge-warning ml-2" i18n
|
|
|
|
|
>Early Access</span
|
|
|
|
|
>
|
|
|
|
|
}
|
|
|
|
|
</a>
|
|
|
|
|
@if (isGhostfolioApiKeyValid === true) {
|
|
|
|
|
<div class="line-height-1">
|
|
|
|
|
<small class="text-muted">
|
|
|
|
|
<ng-container i18n>Valid until</ng-container>
|
|
|
|
|
{{
|
|
|
|
|
ghostfolioApiStatus?.subscription?.expiresAt
|
|
|
|
|
| date: defaultDateFormat
|
|
|
|
|
}}</small
|
|
|
|
|
>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="w-50">
|
|
|
|
|
}
|
|
|
|
|
</a>
|
|
|
|
|
@if (isGhostfolioApiKeyValid === true) {
|
|
|
|
|
<div class="align-items-center d-flex flex-wrap">
|
|
|
|
|
<div class="flex-grow-1 mr-3">
|
|
|
|
|
<div class="line-height-1">
|
|
|
|
|
<small class="text-muted">
|
|
|
|
|
<ng-container i18n>Valid until</ng-container>
|
|
|
|
|
{{
|
|
|
|
|
ghostfolioApiStatus?.subscription?.expiresAt
|
|
|
|
|
| date: defaultDateFormat
|
|
|
|
|
}}
|
|
|
|
|
</small>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="line-height-1 mt-1">
|
|
|
|
|
<small class="text-muted">
|
|
|
|
|
{{ ghostfolioApiStatus.dailyRequests }}
|
|
|
|
|
<ng-container i18n>of</ng-container>
|
|
|
|
|
{{ ghostfolioApiStatus.dailyRequestsMax }}
|
|
|
|
|
<ng-container i18n>daily requests</ng-container>
|
|
|
|
|
</div>
|
|
|
|
|
<button
|
|
|
|
|
class="mx-1 no-min-width px-2"
|
|
|
|
|
mat-button
|
|
|
|
|
[matMenuTriggerFor]="ghostfolioApiMenu"
|
|
|
|
|
(click)="$event.stopPropagation()"
|
|
|
|
|
>
|
|
|
|
|
<ion-icon name="ellipsis-horizontal" />
|
|
|
|
|
</button>
|
|
|
|
|
<mat-menu #ghostfolioApiMenu="matMenu" xPosition="before">
|
|
|
|
|
<button
|
|
|
|
|
mat-menu-item
|
|
|
|
|
(click)="onRemoveGhostfolioApiKey()"
|
|
|
|
|
>
|
|
|
|
|
<span class="align-items-center d-flex">
|
|
|
|
|
<ion-icon class="mr-2" name="trash-outline" />
|
|
|
|
|
<span i18n>Remove API key</span>
|
|
|
|
|
</span>
|
|
|
|
|
</button>
|
|
|
|
|
</mat-menu>
|
|
|
|
|
</small>
|
|
|
|
|
</div>
|
|
|
|
|
} @else if (isGhostfolioApiKeyValid === false) {
|
|
|
|
|
<button
|
|
|
|
|
color="accent"
|
|
|
|
|
mat-flat-button
|
|
|
|
|
(click)="onSetGhostfolioApiKey()"
|
|
|
|
|
>
|
|
|
|
|
<ion-icon class="mr-1" name="key-outline" />
|
|
|
|
|
<span i18n>Set API key</span>
|
|
|
|
|
</button>
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
} @else {
|
|
|
|
|
<div class="w-50">
|
|
|
|
|
<div class="d-flex">
|
|
|
|
|
<gf-asset-profile-icon
|
|
|
|
|
class="mr-1"
|
|
|
|
|
[url]="dataProvider.url"
|
|
|
|
|
/>
|
|
|
|
|
{{ dataProvider.name }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="w-50"></div>
|
|
|
|
|
}
|
|
|
|
|
} @else {
|
|
|
|
|
{{ element.name }}
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
</mat-card-content>
|
|
|
|
|
</mat-card>
|
|
|
|
|
</td>
|
|
|
|
|
</ng-container>
|
|
|
|
|
|
|
|
|
|
<ng-container matColumnDef="actions">
|
|
|
|
|
<th *matHeaderCellDef class="px-1 py-2" mat-header-cell></th>
|
|
|
|
|
|
|
|
|
|
<td *matCellDef="let element" class="px-1 py-2 text-right" mat-cell>
|
|
|
|
|
@if (isGhostfolioDataProvider(element)) {
|
|
|
|
|
@if (isGhostfolioApiKeyValid === true) {
|
|
|
|
|
<button
|
|
|
|
|
class="mx-1 no-min-width px-2"
|
|
|
|
|
mat-button
|
|
|
|
|
[matMenuTriggerFor]="ghostfolioApiMenu"
|
|
|
|
|
(click)="$event.stopPropagation()"
|
|
|
|
|
>
|
|
|
|
|
<ion-icon name="ellipsis-horizontal" />
|
|
|
|
|
</button>
|
|
|
|
|
<mat-menu #ghostfolioApiMenu="matMenu" xPosition="before">
|
|
|
|
|
<button mat-menu-item (click)="onRemoveGhostfolioApiKey()">
|
|
|
|
|
<span class="align-items-center d-flex">
|
|
|
|
|
<ion-icon class="mr-2" name="trash-outline" />
|
|
|
|
|
<span i18n>Remove API key</span>
|
|
|
|
|
</span>
|
|
|
|
|
</button>
|
|
|
|
|
</mat-menu>
|
|
|
|
|
} @else if (isGhostfolioApiKeyValid === false) {
|
|
|
|
|
<button
|
|
|
|
|
color="accent"
|
|
|
|
|
mat-flat-button
|
|
|
|
|
(click)="onSetGhostfolioApiKey()"
|
|
|
|
|
>
|
|
|
|
|
<ion-icon class="mr-1" name="key-outline" />
|
|
|
|
|
<span i18n>Set API key</span>
|
|
|
|
|
</button>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</td>
|
|
|
|
|
</ng-container>
|
|
|
|
|
|
|
|
|
|
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
|
|
|
|
|
<tr *matRowDef="let row; columns: displayedColumns" mat-row></tr>
|
|
|
|
|
</table>
|
|
|
|
|
@if (isLoading) {
|
|
|
|
|
<ngx-skeleton-loader
|
|
|
|
|
animation="pulse"
|
|
|
|
|
class="px-4 py-3"
|
|
|
|
|
[theme]="{
|
|
|
|
|
height: '1.5rem',
|
|
|
|
|
width: '100%'
|
|
|
|
|
}"
|
|
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="mb-5 row">
|
|
|
|
|
|