Browse Source

Task/improve data source filter in market data table (#8327)

* Improve data source filter

* Update changelog
pull/7865/merge
Thomas Kaul 5 hours ago
committed by GitHub
parent
commit
67a64074b4
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 52
      apps/client/src/app/components/admin-market-data/admin-market-data.component.ts
  3. 1
      libs/ui/src/lib/i18n.ts

1
CHANGELOG.md

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Improved the data source filter in the historical market data table of the admin control panel to only list the data providers in use
- Restricted the health check endpoint of the AI service (`GET api/v1/health/ai`) to administrators - Restricted the health check endpoint of the AI service (`GET api/v1/health/ai`) to administrators
- Increased the timeout in the health check endpoint of the AI service to 30 seconds - Increased the timeout in the health check endpoint of the AI service to 30 seconds
- Deprecated the `api/v1/access` endpoints in favor of the `api/v1/accesses` endpoints - Deprecated the `api/v1/access` endpoints in favor of the `api/v1/accesses` endpoints

52
apps/client/src/app/components/admin-market-data/admin-market-data.component.ts

@ -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.`,

1
libs/ui/src/lib/i18n.ts

@ -27,6 +27,7 @@ const locales = {
HIGHER_RISK: $localize`Higher Risk`, HIGHER_RISK: $localize`Higher Risk`,
IMPORT_ACTIVITY_ERROR_IS_DUPLICATE: $localize`This activity already exists.`, IMPORT_ACTIVITY_ERROR_IS_DUPLICATE: $localize`This activity already exists.`,
LOWER_RISK: $localize`Lower Risk`, LOWER_RISK: $localize`Lower Risk`,
MANUAL: $localize`Manual`,
MONTH: $localize`Month`, MONTH: $localize`Month`,
MONTHS: $localize`Months`, MONTHS: $localize`Months`,
OTHER: $localize`Other`, OTHER: $localize`Other`,

Loading…
Cancel
Save