Browse Source

Feature/add filter by data source for asset profiles in admin control panel (#5385)

* Add filter by data source

* Update changelog
pull/5392/head
Thomas Kaul 16 hours ago
committed by GitHub
parent
commit
b5649654b2
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 2
      apps/api/src/app/admin/admin.controller.ts
  3. 16
      apps/api/src/app/admin/admin.service.ts
  4. 69
      apps/client/src/app/components/admin-market-data/admin-market-data.component.ts
  5. 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
### Added ### Added
- Added a filter by data source for the asset profiles in the admin control panel
- Extended the data providers management of the admin control panel by every data provider in use - Extended the data providers management of the admin control panel by every data provider in use
### Changed ### Changed

2
apps/api/src/app/admin/admin.controller.ts

@ -197,6 +197,7 @@ export class AdminController {
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async getMarketData( public async getMarketData(
@Query('assetSubClasses') filterByAssetSubClasses?: string, @Query('assetSubClasses') filterByAssetSubClasses?: string,
@Query('dataSource') filterByDataSource?: string,
@Query('presetId') presetId?: MarketDataPreset, @Query('presetId') presetId?: MarketDataPreset,
@Query('query') filterBySearchQuery?: string, @Query('query') filterBySearchQuery?: string,
@Query('skip') skip?: number, @Query('skip') skip?: number,
@ -206,6 +207,7 @@ export class AdminController {
): Promise<AdminMarketData> { ): Promise<AdminMarketData> {
const filters = this.apiService.buildFiltersFromQueryParams({ const filters = this.apiService.buildFiltersFromQueryParams({
filterByAssetSubClasses, filterByAssetSubClasses,
filterByDataSource,
filterBySearchQuery filterBySearchQuery
}); });

16
apps/api/src/app/admin/admin.service.ts

@ -218,12 +218,12 @@ export class AdminService {
return type === 'SEARCH_QUERY'; return type === 'SEARCH_QUERY';
})?.id; })?.id;
const { ASSET_SUB_CLASS: filtersByAssetSubClass } = groupBy( const {
filters, ASSET_SUB_CLASS: filtersByAssetSubClass,
({ type }) => { DATA_SOURCE: filtersByDataSource
return type; } = groupBy(filters, ({ type }) => {
} return type;
); });
const marketDataItems = await this.prismaService.marketData.groupBy({ const marketDataItems = await this.prismaService.marketData.groupBy({
_count: true, _count: true,
@ -234,6 +234,10 @@ export class AdminService {
where.assetSubClass = AssetSubClass[filtersByAssetSubClass[0].id]; where.assetSubClass = AssetSubClass[filtersByAssetSubClass[0].id];
} }
if (filtersByDataSource) {
where.dataSource = DataSource[filtersByDataSource[0].id];
}
if (searchQuery) { if (searchQuery) {
where.OR = [ where.OR = [
{ id: { mode: 'insensitive', startsWith: searchQuery } }, { id: { mode: 'insensitive', startsWith: searchQuery } },

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

@ -103,39 +103,46 @@ export class GfAdminMarketDataComponent
@ViewChild(MatSort) sort: MatSort; @ViewChild(MatSort) sort: MatSort;
public activeFilters: Filter[] = []; public activeFilters: Filter[] = [];
public allFilters: Filter[] = Object.keys(AssetSubClass) public allFilters: Filter[] = [
.filter((assetSubClass) => { ...Object.keys(AssetSubClass)
return assetSubClass !== 'CASH'; .filter((assetSubClass) => {
}) return assetSubClass !== 'CASH';
.map((assetSubClass) => { })
.map((assetSubClass) => {
return {
id: assetSubClass.toString(),
label: translate(assetSubClass),
type: 'ASSET_SUB_CLASS' as Filter['type']
};
}),
...Object.keys(DataSource).map((dataSource) => {
return { return {
id: assetSubClass.toString(), id: dataSource.toString(),
label: translate(assetSubClass), label: dataSource,
type: 'ASSET_SUB_CLASS' as Filter['type'] type: 'DATA_SOURCE' as Filter['type']
}; };
}) }),
.concat([ {
{ id: 'BENCHMARKS',
id: 'BENCHMARKS', label: $localize`Benchmarks`,
label: $localize`Benchmarks`, type: 'PRESET_ID' as Filter['type']
type: 'PRESET_ID' as Filter['type'] },
}, {
{ id: 'CURRENCIES',
id: 'CURRENCIES', label: $localize`Currencies`,
label: $localize`Currencies`, type: 'PRESET_ID' as Filter['type']
type: 'PRESET_ID' as Filter['type'] },
}, {
{ id: 'ETF_WITHOUT_COUNTRIES',
id: 'ETF_WITHOUT_COUNTRIES', label: $localize`ETFs without Countries`,
label: $localize`ETFs without Countries`, type: 'PRESET_ID' as Filter['type']
type: 'PRESET_ID' as Filter['type'] },
}, {
{ id: 'ETF_WITHOUT_SECTORS',
id: 'ETF_WITHOUT_SECTORS', label: $localize`ETFs without Sectors`,
label: $localize`ETFs without Sectors`, type: 'PRESET_ID' as Filter['type']
type: 'PRESET_ID' as Filter['type'] }
} ];
]);
public benchmarks: Partial<SymbolProfile>[]; public benchmarks: Partial<SymbolProfile>[];
public currentDataSource: DataSource; public currentDataSource: DataSource;
public currentSymbol: string; public currentSymbol: string;

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

@ -12,6 +12,7 @@ const locales = {
DATA_IMPORT_AND_EXPORT_TOOLTIP_BASIC: $localize`Switch to Ghostfolio Premium or Ghostfolio Open Source easily`, DATA_IMPORT_AND_EXPORT_TOOLTIP_BASIC: $localize`Switch to Ghostfolio Premium or Ghostfolio Open Source easily`,
DATA_IMPORT_AND_EXPORT_TOOLTIP_OSS: $localize`Switch to Ghostfolio Premium easily`, DATA_IMPORT_AND_EXPORT_TOOLTIP_OSS: $localize`Switch to Ghostfolio Premium easily`,
DATA_IMPORT_AND_EXPORT_TOOLTIP_PREMIUM: $localize`Switch to Ghostfolio Open Source or Ghostfolio Basic easily`, DATA_IMPORT_AND_EXPORT_TOOLTIP_PREMIUM: $localize`Switch to Ghostfolio Open Source or Ghostfolio Basic easily`,
DATA_SOURCE: $localize`Data Source`,
EMERGENCY_FUND: $localize`Emergency Fund`, EMERGENCY_FUND: $localize`Emergency Fund`,
EXCLUDE_FROM_ANALYSIS: $localize`Exclude from Analysis`, EXCLUDE_FROM_ANALYSIS: $localize`Exclude from Analysis`,
Global: $localize`Global`, Global: $localize`Global`,

Loading…
Cancel
Save