|
|
@ -11,7 +11,7 @@ import { |
|
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; |
|
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; |
|
|
import { internalRoutes } from '@ghostfolio/common/routes/routes'; |
|
|
import { internalRoutes } from '@ghostfolio/common/routes/routes'; |
|
|
import type { SymbolProfile } from '@ghostfolio/prisma/browser'; |
|
|
import type { SymbolProfile } from '@ghostfolio/prisma/browser'; |
|
|
import { AssetSubClass, DataSource } from '@ghostfolio/prisma/enums'; |
|
|
import { AssetSubClass } from '@ghostfolio/prisma/enums'; |
|
|
import { GfActivitiesFilterComponent } from '@ghostfolio/ui/activities-filter'; |
|
|
import { GfActivitiesFilterComponent } from '@ghostfolio/ui/activities-filter'; |
|
|
import { GfFabComponent } from '@ghostfolio/ui/fab'; |
|
|
import { GfFabComponent } from '@ghostfolio/ui/fab'; |
|
|
import { translate } from '@ghostfolio/ui/i18n'; |
|
|
import { translate } from '@ghostfolio/ui/i18n'; |
|
|
@ -61,6 +61,7 @@ import { |
|
|
ellipsisVertical, |
|
|
ellipsisVertical, |
|
|
trashOutline |
|
|
trashOutline |
|
|
} from 'ionicons/icons'; |
|
|
} from 'ionicons/icons'; |
|
|
|
|
|
import { isEqual } from 'lodash-es'; |
|
|
import ms from 'ms'; |
|
|
import ms from 'ms'; |
|
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; |
|
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; |
|
|
import { Subject } from 'rxjs'; |
|
|
import { Subject } from 'rxjs'; |
|
|
@ -95,7 +96,7 @@ import { AdminMarketDataService } from './admin-market-data.service'; |
|
|
export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
protected readonly adminMarketDataService = inject(AdminMarketDataService); |
|
|
protected readonly adminMarketDataService = inject(AdminMarketDataService); |
|
|
|
|
|
|
|
|
protected readonly allFilters: Filter[] = [ |
|
|
protected allFilters: Filter[] = [ |
|
|
...Object.keys(AssetSubClass) |
|
|
...Object.keys(AssetSubClass) |
|
|
.filter((assetSubClass) => { |
|
|
.filter((assetSubClass) => { |
|
|
return assetSubClass !== 'CASH'; |
|
|
return assetSubClass !== 'CASH'; |
|
|
@ -107,13 +108,6 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
type: 'ASSET_SUB_CLASS' as Filter['type'] |
|
|
type: 'ASSET_SUB_CLASS' as Filter['type'] |
|
|
}; |
|
|
}; |
|
|
}), |
|
|
}), |
|
|
...Object.keys(DataSource).map((dataSource) => { |
|
|
|
|
|
return { |
|
|
|
|
|
id: dataSource.toString(), |
|
|
|
|
|
label: dataSource, |
|
|
|
|
|
type: 'DATA_SOURCE' as Filter['type'] |
|
|
|
|
|
}; |
|
|
|
|
|
}), |
|
|
|
|
|
{ |
|
|
{ |
|
|
id: 'BENCHMARKS', |
|
|
id: 'BENCHMARKS', |
|
|
label: $localize`Benchmarks`, |
|
|
label: $localize`Benchmarks`, |
|
|
@ -202,6 +196,7 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
this.adminMarketDataService.refresh$ |
|
|
this.adminMarketDataService.refresh$ |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.subscribe(() => { |
|
|
.subscribe(() => { |
|
|
|
|
|
this.loadDataSourceFilters(); |
|
|
this.reloadData(); |
|
|
this.reloadData(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
@ -214,7 +209,10 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
this.filters$ |
|
|
this.filters$ |
|
|
.pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe( |
|
|
|
|
|
distinctUntilChanged<Filter[]>(isEqual), |
|
|
|
|
|
takeUntilDestroyed(this.destroyRef) |
|
|
|
|
|
) |
|
|
.subscribe((filters) => { |
|
|
.subscribe((filters) => { |
|
|
this.activeFilters = filters; |
|
|
this.activeFilters = filters; |
|
|
|
|
|
|
|
|
@ -250,6 +248,8 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
const { benchmarks } = this.dataService.fetchInfo(); |
|
|
const { benchmarks } = this.dataService.fetchInfo(); |
|
|
|
|
|
|
|
|
this.benchmarks = benchmarks; |
|
|
this.benchmarks = benchmarks; |
|
|
|
|
|
|
|
|
|
|
|
this.loadDataSourceFilters(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
protected onChangePage(page: PageEvent) { |
|
|
protected onChangePage(page: PageEvent) { |
|
|
@ -268,6 +268,7 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
.deleteAssetProfile({ dataSource, symbol }) |
|
|
.deleteAssetProfile({ dataSource, symbol }) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.subscribe(() => { |
|
|
.subscribe(() => { |
|
|
|
|
|
this.loadDataSourceFilters(); |
|
|
this.reloadData(); |
|
|
this.reloadData(); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
@ -281,6 +282,7 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
) |
|
|
) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.subscribe(() => { |
|
|
.subscribe(() => { |
|
|
|
|
|
this.loadDataSourceFilters(); |
|
|
this.reloadData(); |
|
|
this.reloadData(); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
@ -382,6 +384,36 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private loadDataSourceFilters() { |
|
|
|
|
|
this.adminService |
|
|
|
|
|
.fetchAdminData() |
|
|
|
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
|
|
|
.subscribe(({ dataProviders }) => { |
|
|
|
|
|
this.allFilters = [ |
|
|
|
|
|
...this.allFilters.filter(({ type }) => { |
|
|
|
|
|
return type !== 'DATA_SOURCE'; |
|
|
|
|
|
}), |
|
|
|
|
|
...dataProviders.flatMap( |
|
|
|
|
|
({ assetProfileCount, dataSource, name }) => { |
|
|
|
|
|
if (assetProfileCount === 0 || !dataSource) { |
|
|
|
|
|
return []; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return [ |
|
|
|
|
|
{ |
|
|
|
|
|
id: dataSource, |
|
|
|
|
|
label: name ?? translate(dataSource), |
|
|
|
|
|
type: 'DATA_SOURCE' as Filter['type'] |
|
|
|
|
|
} |
|
|
|
|
|
]; |
|
|
|
|
|
} |
|
|
|
|
|
) |
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
this.changeDetectorRef.markForCheck(); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private notifyDataGatheringHasBeenStarted() { |
|
|
private notifyDataGatheringHasBeenStarted() { |
|
|
this.snackBar.open( |
|
|
this.snackBar.open( |
|
|
'✅ ' + $localize`Data gathering has been started.`, |
|
|
'✅ ' + $localize`Data gathering has been started.`, |
|
|
|