mirror of https://github.com/ghostfolio/ghostfolio
Browse Source
* Upgrade ai * @openrouter/ai-sdk-provider to version 2.9.0 * ai to version 6.0.174 * Add AI service health check and improve layout * Update changelogpull/6787/head^2
committed by
GitHub
12 changed files with 335 additions and 239 deletions
@ -1,77 +1,173 @@ |
|||||
<div class="container"> |
<div class="container"> |
||||
<div class="mb-3"> |
<div class="mb-5 row"> |
||||
<h2 class="text-center">Status</h2> |
<div class="col"> |
||||
<div>{{ status$ | async | json }}</div> |
<mat-card appearance="outlined" class="mb-3"> |
||||
</div> |
<mat-card-header> |
||||
<div class="mb-3"> |
<mat-card-title>AI Service Health</mat-card-title> |
||||
<h2 class="text-center">Asset Profile</h2> |
</mat-card-header> |
||||
<div>{{ assetProfile$ | async | json }}</div> |
<mat-card-content> |
||||
</div> |
@let aiServiceHealth = aiServiceHealth$ | async; |
||||
<div> |
@if (isFetchFailure(aiServiceHealth)) { |
||||
<h2 class="text-center">Lookup</h2> |
🔴 {{ aiServiceHealth.fetchError }} |
||||
@if (lookupItems$) { |
} @else if (aiServiceHealth) { |
||||
@let symbols = lookupItems$ | async; |
🟢 {{ aiServiceHealth.status }} |
||||
<ul> |
} @else { |
||||
@for (item of symbols; track item.symbol) { |
<ngx-skeleton-loader |
||||
<li>{{ item.name }} ({{ item.symbol }})</li> |
animation="pulse" |
||||
} |
[theme]="{ height: '1.5rem', width: '100%' }" |
||||
</ul> |
/> |
||||
} |
} |
||||
</div> |
</mat-card-content> |
||||
<div> |
</mat-card> |
||||
<h2 class="text-center">Lookup (ISIN)</h2> |
<mat-card appearance="outlined" class="mb-3"> |
||||
@if (isinLookupItems$) { |
<mat-card-header> |
||||
@let symbols = isinLookupItems$ | async; |
<mat-card-title>Status</mat-card-title> |
||||
<ul> |
</mat-card-header> |
||||
@for (item of symbols; track item.symbol) { |
<mat-card-content> |
||||
<li>{{ item.name }} ({{ item.symbol }})</li> |
@let status = status$ | async; |
||||
} |
@if (isFetchFailure(status)) { |
||||
</ul> |
🔴 {{ status.fetchError }} |
||||
} |
} @else if (status) { |
||||
</div> |
<pre><code>{{ status | json }}</code></pre> |
||||
<div> |
} @else { |
||||
<h2 class="text-center">Quotes</h2> |
<ngx-skeleton-loader |
||||
@if (quotes$) { |
animation="pulse" |
||||
@let quotes = quotes$ | async; |
[theme]="{ height: '1.5rem', width: '100%' }" |
||||
<ul> |
/> |
||||
@for (quote of quotes | keyvalue; track quote) { |
} |
||||
<li> |
</mat-card-content> |
||||
{{ quote.key }}: {{ quote.value.marketPrice }} |
</mat-card> |
||||
{{ quote.value.currency }} |
<mat-card appearance="outlined" class="mb-3"> |
||||
</li> |
<mat-card-header> |
||||
} |
<mat-card-title>Asset Profile</mat-card-title> |
||||
</ul> |
</mat-card-header> |
||||
} |
<mat-card-content> |
||||
</div> |
@let assetProfile = assetProfile$ | async; |
||||
<div> |
@if (isFetchFailure(assetProfile)) { |
||||
<h2 class="text-center">Historical</h2> |
🔴 {{ assetProfile.fetchError }} |
||||
@if (historicalData$) { |
} @else if (assetProfile) { |
||||
@let historicalData = historicalData$ | async; |
<pre><code>{{ assetProfile | json }}</code></pre> |
||||
<ul> |
} @else { |
||||
@for ( |
<ngx-skeleton-loader |
||||
historicalDataItem of historicalData | keyvalue; |
animation="pulse" |
||||
track historicalDataItem |
[theme]="{ height: '1.5rem', width: '100%' }" |
||||
) { |
/> |
||||
<li> |
} |
||||
{{ historicalDataItem.key }}: |
</mat-card-content> |
||||
{{ historicalDataItem.value.marketPrice }} |
</mat-card> |
||||
</li> |
<mat-card appearance="outlined" class="mb-3"> |
||||
} |
<mat-card-header> |
||||
</ul> |
<mat-card-title>Lookup</mat-card-title> |
||||
} |
</mat-card-header> |
||||
</div> |
<mat-card-content> |
||||
<div> |
@let symbols = lookupItems$ | async; |
||||
<h2 class="text-center">Dividends</h2> |
@if (isFetchFailure(symbols)) { |
||||
@if (dividends$) { |
🔴 {{ symbols.fetchError }} |
||||
@let dividends = dividends$ | async; |
} @else if (symbols) { |
||||
<ul> |
<ul> |
||||
@for (dividend of dividends | keyvalue; track dividend) { |
@for (item of symbols; track item.symbol) { |
||||
<li> |
<li>{{ item.name }} ({{ item.symbol }})</li> |
||||
{{ dividend.key }}: |
} |
||||
{{ dividend.value.marketPrice }} |
</ul> |
||||
</li> |
} @else { |
||||
} |
<ngx-skeleton-loader |
||||
</ul> |
animation="pulse" |
||||
} |
[theme]="{ height: '1.5rem', width: '100%' }" |
||||
|
/> |
||||
|
} |
||||
|
</mat-card-content> |
||||
|
</mat-card> |
||||
|
<mat-card appearance="outlined" class="mb-3"> |
||||
|
<mat-card-header> |
||||
|
<mat-card-title>Lookup (ISIN)</mat-card-title> |
||||
|
</mat-card-header> |
||||
|
<mat-card-content> |
||||
|
@let isinSymbols = isinLookupItems$ | async; |
||||
|
@if (isFetchFailure(isinSymbols)) { |
||||
|
🔴 {{ isinSymbols.fetchError }} |
||||
|
} @else if (isinSymbols) { |
||||
|
<ul> |
||||
|
@for (item of isinSymbols; track item.symbol) { |
||||
|
<li>{{ item.name }} ({{ item.symbol }})</li> |
||||
|
} |
||||
|
</ul> |
||||
|
} @else { |
||||
|
<ngx-skeleton-loader |
||||
|
animation="pulse" |
||||
|
[theme]="{ height: '1.5rem', width: '100%' }" |
||||
|
/> |
||||
|
} |
||||
|
</mat-card-content> |
||||
|
</mat-card> |
||||
|
<mat-card appearance="outlined" class="mb-3"> |
||||
|
<mat-card-header> |
||||
|
<mat-card-title>Quotes</mat-card-title> |
||||
|
</mat-card-header> |
||||
|
<mat-card-content> |
||||
|
@let quotes = quotes$ | async; |
||||
|
@if (isFetchFailure(quotes)) { |
||||
|
🔴 {{ quotes.fetchError }} |
||||
|
} @else if (quotes) { |
||||
|
<ul> |
||||
|
@for (quote of quotes | keyvalue; track quote) { |
||||
|
<li> |
||||
|
{{ quote.key }}: {{ quote.value.marketPrice }} |
||||
|
{{ quote.value.currency }} |
||||
|
</li> |
||||
|
} |
||||
|
</ul> |
||||
|
} @else { |
||||
|
<ngx-skeleton-loader |
||||
|
animation="pulse" |
||||
|
[theme]="{ height: '1.5rem', width: '100%' }" |
||||
|
/> |
||||
|
} |
||||
|
</mat-card-content> |
||||
|
</mat-card> |
||||
|
<mat-card appearance="outlined" class="mb-3"> |
||||
|
<mat-card-header> |
||||
|
<mat-card-title>Historical</mat-card-title> |
||||
|
</mat-card-header> |
||||
|
<mat-card-content> |
||||
|
@let historicalData = historicalData$ | async; |
||||
|
@if (isFetchFailure(historicalData)) { |
||||
|
🔴 {{ historicalData.fetchError }} |
||||
|
} @else if (historicalData) { |
||||
|
<ul> |
||||
|
@for (item of historicalData | keyvalue; track item) { |
||||
|
<li>{{ item.key }}: {{ item.value.marketPrice }}</li> |
||||
|
} |
||||
|
</ul> |
||||
|
} @else { |
||||
|
<ngx-skeleton-loader |
||||
|
animation="pulse" |
||||
|
[theme]="{ height: '1.5rem', width: '100%' }" |
||||
|
/> |
||||
|
} |
||||
|
</mat-card-content> |
||||
|
</mat-card> |
||||
|
<mat-card appearance="outlined" class="mb-3"> |
||||
|
<mat-card-header> |
||||
|
<mat-card-title>Dividends</mat-card-title> |
||||
|
</mat-card-header> |
||||
|
<mat-card-content> |
||||
|
@let dividends = dividends$ | async; |
||||
|
@if (isFetchFailure(dividends)) { |
||||
|
🔴 {{ dividends.fetchError }} |
||||
|
} @else if (dividends) { |
||||
|
<ul> |
||||
|
@for (dividend of dividends | keyvalue; track dividend) { |
||||
|
<li>{{ dividend.key }}: {{ dividend.value.marketPrice }}</li> |
||||
|
} |
||||
|
</ul> |
||||
|
} @else { |
||||
|
<ngx-skeleton-loader |
||||
|
animation="pulse" |
||||
|
[theme]="{ height: '1.5rem', width: '100%' }" |
||||
|
/> |
||||
|
} |
||||
|
</mat-card-content> |
||||
|
</mat-card> |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|||||
@ -0,0 +1,5 @@ |
|||||
|
export interface FetchFailure { |
||||
|
fetchError: string; |
||||
|
} |
||||
|
|
||||
|
export type FetchResult<T> = T | FetchFailure; |
||||
@ -0,0 +1,3 @@ |
|||||
|
export interface AiServiceHealthResponse { |
||||
|
status: string; |
||||
|
} |
||||
Loading…
Reference in new issue