Feature/move asset profile details to dialog (#1185)

* Introduce asset profile dialog

* Update changelog
pull/1186/head
Thomas Kaul 2 years ago committed by GitHub
parent b6f395fd3b
commit 24abbd85e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Improved the language localization for German (`de`)
- Extended and made the columns of the asset profiles sortable in the admin control
- Moved the asset profile details in the admin control panel to a dialog
## 1.181.2 - 21.08.2022

@ -84,7 +84,9 @@ export class AdminService {
return {
dataSource,
marketDataItemCount,
symbol
symbol,
countriesCount: 0,
sectorsCount: 0
};
});
@ -95,6 +97,10 @@ export class AdminService {
_count: {
select: { Order: true }
},
assetClass: true,
assetSubClass: true,
countries: true,
sectors: true,
dataSource: true,
Order: {
orderBy: [{ date: 'asc' }],
@ -106,6 +112,9 @@ export class AdminService {
}
})
).map((symbolProfile) => {
const countriesCount = symbolProfile.countries
? Object.keys(symbolProfile.countries).length
: 0;
const marketDataItemCount =
marketData.find((marketDataItem) => {
return (
@ -113,10 +122,17 @@ export class AdminService {
marketDataItem.symbol === symbolProfile.symbol
);
})?._count ?? 0;
const sectorsCount = symbolProfile.sectors
? Object.keys(symbolProfile.sectors).length
: 0;
return {
countriesCount,
marketDataItemCount,
sectorsCount,
activityCount: symbolProfile._count.Order,
assetClass: symbolProfile.assetClass,
assetSubClass: symbolProfile.assetSubClass,
dataSource: symbolProfile.dataSource,
date: symbolProfile.Order?.[0]?.date,
symbol: symbolProfile.symbol

@ -3,17 +3,26 @@ import {
ChangeDetectorRef,
Component,
OnDestroy,
OnInit
OnInit,
ViewChild
} from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { getDateFormatString } from '@ghostfolio/common/helper';
import { DATE_FORMAT, getDateFormatString } from '@ghostfolio/common/helper';
import { UniqueAsset, User } from '@ghostfolio/common/interfaces';
import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface';
import { DataSource, MarketData } from '@prisma/client';
import { DataSource } from '@prisma/client';
import { format, parseISO } from 'date-fns';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { AssetProfileDialog } from './asset-profile-dialog/asset-profile-dialog.component';
import { AssetProfileDialogParams } from './asset-profile-dialog/interfaces/interfaces';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
@ -22,11 +31,26 @@ import { takeUntil } from 'rxjs/operators';
templateUrl: './admin-market-data.html'
})
export class AdminMarketDataComponent implements OnDestroy, OnInit {
@ViewChild(MatSort) sort: MatSort;
public currentDataSource: DataSource;
public currentSymbol: string;
public dataSource: MatTableDataSource<any> = new MatTableDataSource();
public defaultDateFormat: string;
public deviceType: string;
public displayedColumns = [
'symbol',
'dataSource',
'assetClass',
'assetSubClass',
'date',
'activityCount',
'marketDataItemCount',
'countriesCount',
'sectorsCount',
'actions'
];
public marketData: AdminMarketDataItem[] = [];
public marketDataDetails: MarketData[] = [];
public user: User;
private unsubscribeSubject = new Subject<void>();
@ -35,8 +59,29 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
private adminService: AdminService,
private changeDetectorRef: ChangeDetectorRef,
private dataService: DataService,
private deviceService: DeviceDetectorService,
private dialog: MatDialog,
private route: ActivatedRoute,
private router: Router,
private userService: UserService
) {
this.route.queryParams
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((params) => {
if (
params['assetProfileDialog'] &&
params['dataSource'] &&
params['dateOfFirstActivity'] &&
params['symbol']
) {
this.openAssetProfileDialog({
dataSource: params['dataSource'],
dateOfFirstActivity: params['dateOfFirstActivity'],
symbol: params['symbol']
});
}
});
this.userService.stateChanged
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((state) => {
@ -51,6 +96,8 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
}
public ngOnInit() {
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
this.fetchAdminMarketData();
}
@ -75,28 +122,19 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
.subscribe(() => {});
}
public onMarketDataChanged(withRefresh: boolean = false) {
if (withRefresh) {
this.fetchAdminMarketData();
this.fetchAdminMarketDataBySymbol({
dataSource: this.currentDataSource,
symbol: this.currentSymbol
});
}
}
public setCurrentProfile({ dataSource, symbol }: UniqueAsset) {
this.marketDataDetails = [];
if (this.currentSymbol === symbol) {
this.currentDataSource = undefined;
this.currentSymbol = '';
} else {
this.currentDataSource = dataSource;
this.currentSymbol = symbol;
this.fetchAdminMarketDataBySymbol({ dataSource, symbol });
}
public onOpenAssetProfileDialog({
dataSource,
dateOfFirstActivity,
symbol
}: UniqueAsset & { dateOfFirstActivity: string }) {
this.router.navigate([], {
queryParams: {
dataSource,
symbol,
assetProfileDialog: true,
dateOfFirstActivity: format(parseISO(dateOfFirstActivity), DATE_FORMAT)
}
});
}
public ngOnDestroy() {
@ -109,20 +147,48 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
.fetchAdminMarketData()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ marketData }) => {
this.marketData = marketData;
this.dataSource = new MatTableDataSource(marketData);
this.dataSource.sort = this.sort;
this.changeDetectorRef.markForCheck();
});
}
private fetchAdminMarketDataBySymbol({ dataSource, symbol }: UniqueAsset) {
this.adminService
.fetchAdminMarketDataBySymbol({ dataSource, symbol })
private openAssetProfileDialog({
dataSource,
dateOfFirstActivity,
symbol
}: {
dataSource: DataSource;
dateOfFirstActivity: string;
symbol: string;
}) {
this.userService
.get()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ marketData }) => {
this.marketDataDetails = marketData;
this.changeDetectorRef.markForCheck();
.subscribe((user) => {
this.user = user;
const dialogRef = this.dialog.open(AssetProfileDialog, {
autoFocus: false,
data: <AssetProfileDialogParams>{
dataSource,
dateOfFirstActivity,
symbol,
deviceType: this.deviceType,
locale: this.user?.settings?.locale
},
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
});
dialogRef
.afterClosed()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
this.router.navigate(['.'], { relativeTo: this.route });
});
});
}
}

@ -1,76 +1,137 @@
<div class="container">
<div class="row">
<div class="col">
<table class="gf-table w-100">
<thead>
<tr class="mat-header-row">
<th class="mat-header-cell px-1 py-2" i18n>Symbol</th>
<th class="mat-header-cell px-1 py-2" i18n>Data Source</th>
<th class="mat-header-cell px-1 py-2" i18n>First Activity</th>
<th class="mat-header-cell px-1 py-2" i18n>Activity Count</th>
<th class="mat-header-cell px-1 py-2" i18n>Historical Data</th>
<th class="mat-header-cell px-1 py-2"></th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let item of marketData; let i = index">
<tr
class="cursor-pointer mat-row"
(click)="setCurrentProfile({ dataSource: item.dataSource, symbol: item.symbol })"
<table
class="gf-table w-100"
matSort
matSortActive="symbol"
matSortDirection="asc"
mat-table
[dataSource]="dataSource"
>
<ng-container matColumnDef="symbol">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Symbol</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
{{ element.symbol }}
</td>
</ng-container>
<ng-container matColumnDef="dataSource">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Data Source</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
{{ element.dataSource }}
</td>
</ng-container>
<ng-container matColumnDef="assetClass">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Asset Class</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
{{ element.assetClass }}
</td>
</ng-container>
<ng-container matColumnDef="assetSubClass">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Asset Sub Class</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
{{ element.assetSubClass }}
</td>
</ng-container>
<ng-container matColumnDef="date">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>First Activity</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
{{ (element.date | date: defaultDateFormat) ?? '' }}
</td>
</ng-container>
<ng-container matColumnDef="activityCount">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Activity Count</ng-container>
</th>
<td *matCellDef="let element" class="px-1 text-right" mat-cell>
{{ element.activityCount }}
</td>
</ng-container>
<ng-container matColumnDef="marketDataItemCount">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Historical Data</ng-container>
</th>
<td *matCellDef="let element" class="px-1 text-right" mat-cell>
{{ element.marketDataItemCount }}
</td>
</ng-container>
<ng-container matColumnDef="countriesCount">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Countries Count</ng-container>
</th>
<td *matCellDef="let element" class="px-1 text-right" mat-cell>
{{ element.countriesCount }}
</td>
</ng-container>
<ng-container matColumnDef="sectorsCount">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Sectors Count</ng-container>
</th>
<td *matCellDef="let element" class="px-1 text-right" mat-cell>
{{ element.sectorsCount }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th *matHeaderCellDef class="px-1 text-center" mat-header-cell></th>
<td *matCellDef="let element" class="px-1 text-center" mat-cell>
<button
class="mx-1 no-min-width px-2"
mat-button
[matMenuTriggerFor]="accountMenu"
(click)="$event.stopPropagation()"
>
<td class="mat-cell px-1 py-2">{{ item.symbol }}</td>
<td class="mat-cell px-1 py-2">{{ item.dataSource }}</td>
<td class="mat-cell px-1 py-2">
{{ (item.date | date: defaultDateFormat) ?? '' }}
</td>
<td class="mat-cell px-1 py-2">{{ item.activityCount }}</td>
<td class="mat-cell px-1 py-2">{{ item.marketDataItemCount }}</td>
<td class="mat-cell px-1 py-2">
<button
class="mx-1 no-min-width px-2"
mat-button
[matMenuTriggerFor]="accountMenu"
(click)="$event.stopPropagation()"
>
<ion-icon name="ellipsis-vertical"></ion-icon>
</button>
<mat-menu #accountMenu="matMenu" xPosition="before">
<button
mat-menu-item
(click)="onGatherSymbol({dataSource: item.dataSource, symbol: item.symbol})"
>
<ng-container i18n>Gather Data</ng-container>
</button>
<button
mat-menu-item
(click)="onGatherProfileDataBySymbol({dataSource: item.dataSource, symbol: item.symbol})"
>
<ng-container i18n>Gather Profile Data</ng-container>
</button>
<button
mat-menu-item
[disabled]="item.activityCount !== 0"
(click)="onDeleteProfileData({dataSource: item.dataSource, symbol: item.symbol})"
>
<ng-container i18n>Delete</ng-container>
</button>
</mat-menu>
</td>
</tr>
<tr *ngIf="currentSymbol === item.symbol" class="mat-row">
<td class="p-1" colspan="6">
<gf-admin-market-data-detail
[dataSource]="item.dataSource"
[dateOfFirstActivity]="item.date"
[locale]="user?.settings?.locale"
[marketData]="marketDataDetails"
[symbol]="item.symbol"
(marketDataChanged)="onMarketDataChanged($event)"
></gf-admin-market-data-detail>
</td>
</tr>
</ng-container>
</tbody>
<ion-icon name="ellipsis-vertical"></ion-icon>
</button>
<mat-menu #accountMenu="matMenu" xPosition="before">
<button
mat-menu-item
(click)="onGatherSymbol({dataSource: element.dataSource, symbol: element.symbol})"
>
<ng-container i18n>Gather Data</ng-container>
</button>
<button
mat-menu-item
(click)="onGatherProfileDataBySymbol({dataSource: element.dataSource, symbol: element.symbol})"
>
<ng-container i18n>Gather Profile Data</ng-container>
</button>
<button
mat-menu-item
[disabled]="element.activityCount !== 0"
(click)="onDeleteProfileData({dataSource: element.dataSource, symbol: element.symbol})"
>
<ng-container i18n>Delete</ng-container>
</button>
</mat-menu>
</td>
</ng-container>
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
<tr
*matRowDef="let row; columns: displayedColumns"
class="cursor-pointer"
mat-row
(click)="onOpenAssetProfileDialog({ dateOfFirstActivity: row.date, dataSource: row.dataSource, symbol: row.symbol })"
></tr>
</table>
</div>
</div>

@ -2,17 +2,21 @@ import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { GfAdminMarketDataDetailModule } from '@ghostfolio/client/components/admin-market-data-detail/admin-market-data-detail.module';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { AdminMarketDataComponent } from './admin-market-data.component';
import { GfAssetProfileDialogModule } from './asset-profile-dialog/assset-profile-dialog.module';
@NgModule({
declarations: [AdminMarketDataComponent],
imports: [
CommonModule,
GfAdminMarketDataDetailModule,
GfAssetProfileDialogModule,
MatButtonModule,
MatMenuModule
MatMenuModule,
MatSortModule,
MatTableModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})

@ -0,0 +1,7 @@
:host {
display: block;
.mat-dialog-content {
max-height: unset;
}
}

@ -0,0 +1,73 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Inject,
OnDestroy,
OnInit
} from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AdminService } from '@ghostfolio/client/services/admin.service';
import { UniqueAsset } from '@ghostfolio/common/interfaces';
import { MarketData } from '@prisma/client';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { AssetProfileDialogParams } from './interfaces/interfaces';
@Component({
host: { class: 'd-flex flex-column h-100' },
selector: 'gf-asset-profile-dialog',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: 'asset-profile-dialog.html',
styleUrls: ['./asset-profile-dialog.component.scss']
})
export class AssetProfileDialog implements OnDestroy, OnInit {
public marketDataDetails: MarketData[] = [];
private unsubscribeSubject = new Subject<void>();
public constructor(
private adminService: AdminService,
private changeDetectorRef: ChangeDetectorRef,
public dialogRef: MatDialogRef<AssetProfileDialog>,
@Inject(MAT_DIALOG_DATA) public data: AssetProfileDialogParams
) {}
public ngOnInit(): void {
this.initialize();
}
public onClose(): void {
this.dialogRef.close();
}
public onMarketDataChanged(withRefresh: boolean = false) {
if (withRefresh) {
this.initialize();
}
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private fetchAdminMarketDataBySymbol({ dataSource, symbol }: UniqueAsset) {
this.adminService
.fetchAdminMarketDataBySymbol({ dataSource, symbol })
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ marketData }) => {
this.marketDataDetails = marketData;
this.changeDetectorRef.markForCheck();
});
}
private initialize() {
this.fetchAdminMarketDataBySymbol({
dataSource: this.data.dataSource,
symbol: this.data.symbol
});
}
}

@ -0,0 +1,24 @@
<gf-dialog-header
mat-dialog-title
position="center"
[deviceType]="data.deviceType"
[title]="data.symbol"
(closeButtonClicked)="onClose()"
></gf-dialog-header>
<div class="flex-grow-1" mat-dialog-content>
<gf-admin-market-data-detail
[dataSource]="data.dataSource"
[dateOfFirstActivity]="data.dateOfFirstActivity"
[locale]="data.locale"
[marketData]="marketDataDetails"
[symbol]="data.symbol"
(marketDataChanged)="onMarketDataChanged($event)"
></gf-admin-market-data-detail>
</div>
<gf-dialog-footer
mat-dialog-actions
[deviceType]="data.deviceType"
(closeButtonClicked)="onClose()"
></gf-dialog-footer>

@ -0,0 +1,23 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
import { GfAdminMarketDataDetailModule } from '../../admin-market-data-detail/admin-market-data-detail.module';
import { AssetProfileDialog } from './asset-profile-dialog.component';
@NgModule({
declarations: [AssetProfileDialog],
imports: [
CommonModule,
GfAdminMarketDataDetailModule,
GfDialogFooterModule,
GfDialogHeaderModule,
MatButtonModule,
MatDialogModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class GfAssetProfileDialogModule {}

@ -0,0 +1,9 @@
import { DataSource } from '@prisma/client';
export interface AssetProfileDialogParams {
dateOfFirstActivity: string;
dataSource: DataSource;
deviceType: string;
locale: string;
symbol: string;
}

@ -47,7 +47,7 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit {
private settingsStorageService: SettingsStorageService,
private userService: UserService
) {
route.queryParams
this.route.queryParams
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((params) => {
if (

@ -21,6 +21,8 @@ import { takeUntil } from 'rxjs/operators';
export class HomeMarketComponent implements OnDestroy, OnInit {
public benchmarks: Benchmark[];
public fearAndGreedIndex: number;
public fearLabel = $localize`Fear`;
public greedLabel = $localize`Greed`;
public hasPermissionToAccessFearAndGreedIndex: boolean;
public historicalData: HistoricalDataItem[];
public info: InfoItem;

@ -9,13 +9,13 @@
class="mb-3"
symbol="Fear & Greed Index"
yMax="100"
yMaxLabel="Greed"
yMin="0"
yMinLabel="Fear"
[historicalDataItems]="historicalData"
[locale]="user?.settings?.locale"
[showXAxis]="true"
[showYAxis]="true"
[yMaxLabel]="greedLabel"
[yMinLabel]="fearLabel"
></gf-line-chart>
<gf-fear-and-greed-index
class="d-flex justify-content-center"

@ -186,7 +186,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">122</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
@ -222,7 +222,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">7</context>
<context context-type="linenumber">14</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/positions-table/positions-table.component.html</context>
@ -242,7 +242,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">8</context>
<context context-type="linenumber">23</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.html</context>
@ -406,7 +406,7 @@
<target state="translated">Erste Aktivität</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">9</context>
<context context-type="linenumber">50</context>
</context-group>
</trans-unit>
<trans-unit id="ced0954194f098201837bb03b32441e4991b5193" datatype="html">
@ -414,7 +414,7 @@
<target state="translated">Anzahl Aktivitäten</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">10</context>
<context context-type="linenumber">59</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
@ -426,7 +426,7 @@
<target state="translated">Historische Daten</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">11</context>
<context context-type="linenumber">68</context>
</context-group>
</trans-unit>
<trans-unit id="f835caf68bff562ddd23556a651e834d5af3380b" datatype="html">
@ -434,7 +434,7 @@
<target state="translated">Daten einholen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">42</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="912825160188860007" datatype="html">
@ -514,7 +514,7 @@
<target state="translated">Profildaten einholen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">115</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
@ -1988,6 +1988,10 @@
<trans-unit id="584c9433705e9bfdd2e7a9f0192690f453d36196" datatype="html">
<source>Asset Class</source>
<target state="translated">Anlageklasse</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">32</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">145</context>
@ -2380,6 +2384,10 @@
<trans-unit id="27fe3d097c64eaec7ff564358f80fb7ba795f484" datatype="html">
<source>Asset Sub Class</source>
<target state="translated">Anlageunterklasse</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">41</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">154</context>
@ -2561,6 +2569,38 @@
<context context-type="linenumber">296</context>
</context-group>
</trans-unit>
<trans-unit id="aad5320acd7453f912bc8714e72c2fa71e8ab18e" datatype="html">
<source>Countries Count</source>
<target state="translated">Anzahl Länder</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">77</context>
</context-group>
</trans-unit>
<trans-unit id="8511b16abcf065252b350d64e337ba2447db3ffb" datatype="html">
<source>Sectors Count</source>
<target state="translated">Anzahl Sektoren</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="5486880308148746399" datatype="html">
<source>Fear</source>
<target state="translated">Angst</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/home-market/home-market.component.ts</context>
<context context-type="linenumber">24</context>
</context-group>
</trans-unit>
<trans-unit id="6844699413925472826" datatype="html">
<source>Greed</source>
<target state="translated">Gier</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/home-market/home-market.component.ts</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

@ -174,7 +174,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">122</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
@ -207,7 +207,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">7</context>
<context context-type="linenumber">14</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/positions-table/positions-table.component.html</context>
@ -226,7 +226,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">8</context>
<context context-type="linenumber">23</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.html</context>
@ -375,14 +375,14 @@
<source>First Activity</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">9</context>
<context context-type="linenumber">50</context>
</context-group>
</trans-unit>
<trans-unit id="ced0954194f098201837bb03b32441e4991b5193" datatype="html">
<source>Activity Count</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">10</context>
<context context-type="linenumber">59</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
@ -393,14 +393,14 @@
<source>Historical Data</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">11</context>
<context context-type="linenumber">68</context>
</context-group>
</trans-unit>
<trans-unit id="f835caf68bff562ddd23556a651e834d5af3380b" datatype="html">
<source>Gather Data</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">42</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="912825160188860007" datatype="html">
@ -470,7 +470,7 @@
<source>Gather Profile Data</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">115</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
@ -1781,6 +1781,10 @@
</trans-unit>
<trans-unit id="584c9433705e9bfdd2e7a9f0192690f453d36196" datatype="html">
<source>Asset Class</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">32</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">145</context>
@ -2108,6 +2112,10 @@
</trans-unit>
<trans-unit id="27fe3d097c64eaec7ff564358f80fb7ba795f484" datatype="html">
<source>Asset Sub Class</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">41</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">154</context>
@ -2287,6 +2295,34 @@
<context context-type="linenumber">29</context>
</context-group>
</trans-unit>
<trans-unit id="8511b16abcf065252b350d64e337ba2447db3ffb" datatype="html">
<source>Sectors Count</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="aad5320acd7453f912bc8714e72c2fa71e8ab18e" datatype="html">
<source>Countries Count</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">77</context>
</context-group>
</trans-unit>
<trans-unit id="5486880308148746399" datatype="html">
<source>Fear</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/home-market/home-market.component.ts</context>
<context context-type="linenumber">24</context>
</context-group>
</trans-unit>
<trans-unit id="6844699413925472826" datatype="html">
<source>Greed</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/home-market/home-market.component.ts</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

@ -1,12 +1,16 @@
import { DataSource } from '@prisma/client';
import { AssetClass, AssetSubClass, DataSource } from '@prisma/client';
export interface AdminMarketData {
marketData: AdminMarketDataItem[];
}
export interface AdminMarketDataItem {
assetClass?: AssetClass;
assetSubClass?: AssetSubClass;
countriesCount: number;
dataSource: DataSource;
date?: Date;
marketDataItemCount?: number;
marketDataItemCount: number;
sectorsCount: number;
symbol: string;
}

Loading…
Cancel
Save