Feature/refactor holding detail dialog to standalone (#3407)
* Refactor holding detail dialog to standalone * Update changelog
This commit is contained in:
parent
812ff5cbdc
commit
e31b4c64cb
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Refactored the holding detail dialog to a standalone component
|
||||||
- Refreshed the cryptocurrencies list
|
- Refreshed the cryptocurrencies list
|
||||||
- Refactored various pages to standalone components
|
- Refactored various pages to standalone components
|
||||||
- Upgraded `body-parser` from version `1.20.1` to `1.20.2`
|
- Upgraded `body-parser` from version `1.20.1` to `1.20.2`
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
|
|
||||||
import { Account, Tag } from '@prisma/client';
|
import { Account, Tag } from '@prisma/client';
|
||||||
|
|
||||||
export interface PortfolioPositionDetail {
|
export interface PortfolioHoldingDetail {
|
||||||
accounts: Account[];
|
accounts: Account[];
|
||||||
averagePrice: number;
|
averagePrice: number;
|
||||||
dataProviderInfo: DataProviderInfo;
|
dataProviderInfo: DataProviderInfo;
|
@ -51,7 +51,7 @@ import { AssetClass, AssetSubClass } from '@prisma/client';
|
|||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
|
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
|
||||||
|
|
||||||
import { PortfolioPositionDetail } from './interfaces/portfolio-position-detail.interface';
|
import { PortfolioHoldingDetail } from './interfaces/portfolio-holding-detail.interface';
|
||||||
import { PortfolioService } from './portfolio.service';
|
import { PortfolioService } from './portfolio.service';
|
||||||
|
|
||||||
@Controller('portfolio')
|
@Controller('portfolio')
|
||||||
@ -569,7 +569,7 @@ export class PortfolioController {
|
|||||||
@Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string,
|
@Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string,
|
||||||
@Param('dataSource') dataSource,
|
@Param('dataSource') dataSource,
|
||||||
@Param('symbol') symbol
|
@Param('symbol') symbol
|
||||||
): Promise<PortfolioPositionDetail> {
|
): Promise<PortfolioHoldingDetail> {
|
||||||
const position = await this.portfolioService.getPosition(
|
const position = await this.portfolioService.getPosition(
|
||||||
dataSource,
|
dataSource,
|
||||||
impersonationId,
|
impersonationId,
|
||||||
|
@ -77,7 +77,7 @@ import {
|
|||||||
PerformanceCalculationType,
|
PerformanceCalculationType,
|
||||||
PortfolioCalculatorFactory
|
PortfolioCalculatorFactory
|
||||||
} from './calculator/portfolio-calculator.factory';
|
} from './calculator/portfolio-calculator.factory';
|
||||||
import { PortfolioPositionDetail } from './interfaces/portfolio-position-detail.interface';
|
import { PortfolioHoldingDetail } from './interfaces/portfolio-holding-detail.interface';
|
||||||
import { RulesService } from './rules.service';
|
import { RulesService } from './rules.service';
|
||||||
|
|
||||||
const asiaPacificMarkets = require('../../assets/countries/asia-pacific-markets.json');
|
const asiaPacificMarkets = require('../../assets/countries/asia-pacific-markets.json');
|
||||||
@ -602,7 +602,7 @@ export class PortfolioService {
|
|||||||
aDataSource: DataSource,
|
aDataSource: DataSource,
|
||||||
aImpersonationId: string,
|
aImpersonationId: string,
|
||||||
aSymbol: string
|
aSymbol: string
|
||||||
): Promise<PortfolioPositionDetail> {
|
): Promise<PortfolioHoldingDetail> {
|
||||||
const userId = await this.getUserId(aImpersonationId, this.request.user.id);
|
const userId = await this.getUserId(aImpersonationId, this.request.user.id);
|
||||||
const user = await this.userService.user({ id: userId });
|
const user = await this.userService.user({ id: userId });
|
||||||
const userCurrency = this.getUserCurrency(user);
|
const userCurrency = this.getUserCurrency(user);
|
||||||
@ -693,7 +693,7 @@ export class PortfolioService {
|
|||||||
transactionCount
|
transactionCount
|
||||||
} = position;
|
} = position;
|
||||||
|
|
||||||
const accounts: PortfolioPositionDetail['accounts'] = uniqBy(
|
const accounts: PortfolioHoldingDetail['accounts'] = uniqBy(
|
||||||
orders.filter(({ Account }) => {
|
orders.filter(({ Account }) => {
|
||||||
return Account;
|
return Account;
|
||||||
}),
|
}),
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { GfHoldingDetailDialogComponent } from '@ghostfolio/client/components/holding-detail-dialog/holding-detail-dialog.component';
|
||||||
|
import { HoldingDetailDialogParams } from '@ghostfolio/client/components/holding-detail-dialog/interfaces/interfaces';
|
||||||
import { getCssVariable } from '@ghostfolio/common/helper';
|
import { getCssVariable } from '@ghostfolio/common/helper';
|
||||||
import { InfoItem, User } from '@ghostfolio/common/interfaces';
|
import { InfoItem, User } from '@ghostfolio/common/interfaces';
|
||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
@ -26,8 +28,6 @@ import { DeviceDetectorService } from 'ngx-device-detector';
|
|||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { filter, takeUntil } from 'rxjs/operators';
|
import { filter, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import { PositionDetailDialogParams } from './components/position-detail-dialog/interfaces/interfaces';
|
|
||||||
import { PositionDetailDialog } from './components/position-detail-dialog/position-detail-dialog.component';
|
|
||||||
import { DataService } from './services/data.service';
|
import { DataService } from './services/data.service';
|
||||||
import { ImpersonationStorageService } from './services/impersonation-storage.service';
|
import { ImpersonationStorageService } from './services/impersonation-storage.service';
|
||||||
import { TokenStorageService } from './services/token-storage.service';
|
import { TokenStorageService } from './services/token-storage.service';
|
||||||
@ -246,9 +246,9 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
.subscribe((user) => {
|
.subscribe((user) => {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
|
||||||
const dialogRef = this.dialog.open(PositionDetailDialog, {
|
const dialogRef = this.dialog.open(GfHoldingDetailDialogComponent, {
|
||||||
autoFocus: false,
|
autoFocus: false,
|
||||||
data: <PositionDetailDialogParams>{
|
data: <HoldingDetailDialogParams>{
|
||||||
dataSource,
|
dataSource,
|
||||||
symbol,
|
symbol,
|
||||||
baseCurrency: this.user?.settings?.baseCurrency,
|
baseCurrency: this.user?.settings?.baseCurrency,
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
|
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
|
||||||
|
import { GfAccountsTableModule } from '@ghostfolio/client/components/accounts-table/accounts-table.module';
|
||||||
|
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
|
||||||
|
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
|
||||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||||
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
||||||
import { DATE_FORMAT, downloadAsFile } from '@ghostfolio/common/helper';
|
import { DATE_FORMAT, downloadAsFile } from '@ghostfolio/common/helper';
|
||||||
@ -8,9 +11,16 @@ import {
|
|||||||
LineChartItem,
|
LineChartItem,
|
||||||
User
|
User
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
|
import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table';
|
||||||
|
import { GfDataProviderCreditsComponent } from '@ghostfolio/ui/data-provider-credits';
|
||||||
import { translate } from '@ghostfolio/ui/i18n';
|
import { translate } from '@ghostfolio/ui/i18n';
|
||||||
|
import { GfLineChartComponent } from '@ghostfolio/ui/line-chart';
|
||||||
|
import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart';
|
||||||
|
import { GfValueComponent } from '@ghostfolio/ui/value';
|
||||||
|
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
import {
|
import {
|
||||||
|
CUSTOM_ELEMENTS_SCHEMA,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
Component,
|
Component,
|
||||||
@ -18,24 +28,50 @@ import {
|
|||||||
OnDestroy,
|
OnDestroy,
|
||||||
OnInit
|
OnInit
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatChipsModule } from '@angular/material/chips';
|
||||||
|
import {
|
||||||
|
MAT_DIALOG_DATA,
|
||||||
|
MatDialogModule,
|
||||||
|
MatDialogRef
|
||||||
|
} from '@angular/material/dialog';
|
||||||
import { SortDirection } from '@angular/material/sort';
|
import { SortDirection } from '@angular/material/sort';
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
import { Account, Tag } from '@prisma/client';
|
import { Account, Tag } from '@prisma/client';
|
||||||
import { format, isSameMonth, isToday, parseISO } from 'date-fns';
|
import { format, isSameMonth, isToday, parseISO } from 'date-fns';
|
||||||
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import { PositionDetailDialogParams } from './interfaces/interfaces';
|
import { HoldingDetailDialogParams } from './interfaces/interfaces';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'd-flex flex-column h-100' },
|
|
||||||
selector: 'gf-position-detail-dialog',
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
templateUrl: 'position-detail-dialog.html',
|
host: { class: 'd-flex flex-column h-100' },
|
||||||
styleUrls: ['./position-detail-dialog.component.scss']
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
GfAccountsTableModule,
|
||||||
|
GfActivitiesTableComponent,
|
||||||
|
GfDataProviderCreditsComponent,
|
||||||
|
GfDialogFooterModule,
|
||||||
|
GfDialogHeaderModule,
|
||||||
|
GfLineChartComponent,
|
||||||
|
GfPortfolioProportionChartComponent,
|
||||||
|
GfValueComponent,
|
||||||
|
MatButtonModule,
|
||||||
|
MatChipsModule,
|
||||||
|
MatDialogModule,
|
||||||
|
MatTabsModule,
|
||||||
|
NgxSkeletonLoaderModule
|
||||||
|
],
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
selector: 'gf-holding-detail-dialog',
|
||||||
|
standalone: true,
|
||||||
|
styleUrls: ['./holding-detail-dialog.component.scss'],
|
||||||
|
templateUrl: 'holding-detail-dialog.html'
|
||||||
})
|
})
|
||||||
export class PositionDetailDialog implements OnDestroy, OnInit {
|
export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
||||||
public accounts: Account[];
|
public accounts: Account[];
|
||||||
public activities: Activity[];
|
public activities: Activity[];
|
||||||
public assetClass: string;
|
public assetClass: string;
|
||||||
@ -80,14 +116,14 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
|
|||||||
public constructor(
|
public constructor(
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private dataService: DataService,
|
private dataService: DataService,
|
||||||
public dialogRef: MatDialogRef<PositionDetailDialog>,
|
public dialogRef: MatDialogRef<GfHoldingDetailDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: PositionDetailDialogParams,
|
@Inject(MAT_DIALOG_DATA) public data: HoldingDetailDialogParams,
|
||||||
private userService: UserService
|
private userService: UserService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchPositionDetail({
|
.fetchHoldingDetail({
|
||||||
dataSource: this.data.dataSource,
|
dataSource: this.data.dataSource,
|
||||||
symbol: this.data.symbol
|
symbol: this.data.symbol
|
||||||
})
|
})
|
@ -2,7 +2,7 @@ import { ColorScheme } from '@ghostfolio/common/types';
|
|||||||
|
|
||||||
import { DataSource } from '@prisma/client';
|
import { DataSource } from '@prisma/client';
|
||||||
|
|
||||||
export interface PositionDetailDialogParams {
|
export interface HoldingDetailDialogParams {
|
||||||
baseCurrency: string;
|
baseCurrency: string;
|
||||||
colorScheme: ColorScheme;
|
colorScheme: ColorScheme;
|
||||||
dataSource: DataSource;
|
dataSource: DataSource;
|
@ -1,40 +0,0 @@
|
|||||||
import { GfAccountsTableModule } from '@ghostfolio/client/components/accounts-table/accounts-table.module';
|
|
||||||
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
|
|
||||||
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
|
|
||||||
import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table';
|
|
||||||
import { GfDataProviderCreditsComponent } from '@ghostfolio/ui/data-provider-credits';
|
|
||||||
import { GfLineChartComponent } from '@ghostfolio/ui/line-chart';
|
|
||||||
import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart';
|
|
||||||
import { GfValueComponent } from '@ghostfolio/ui/value';
|
|
||||||
|
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
|
||||||
import { MatChipsModule } from '@angular/material/chips';
|
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
|
||||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
|
||||||
|
|
||||||
import { PositionDetailDialog } from './position-detail-dialog.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [PositionDetailDialog],
|
|
||||||
imports: [
|
|
||||||
CommonModule,
|
|
||||||
GfAccountsTableModule,
|
|
||||||
GfActivitiesTableComponent,
|
|
||||||
GfDataProviderCreditsComponent,
|
|
||||||
GfDialogFooterModule,
|
|
||||||
GfDialogHeaderModule,
|
|
||||||
GfLineChartComponent,
|
|
||||||
GfPortfolioProportionChartComponent,
|
|
||||||
GfValueComponent,
|
|
||||||
MatButtonModule,
|
|
||||||
MatChipsModule,
|
|
||||||
MatDialogModule,
|
|
||||||
MatTabsModule,
|
|
||||||
NgxSkeletonLoaderModule
|
|
||||||
],
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
|
||||||
})
|
|
||||||
export class GfPositionDetailDialogModule {}
|
|
@ -6,7 +6,7 @@ import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto
|
|||||||
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
|
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
|
||||||
import { Activities } from '@ghostfolio/api/app/order/interfaces/activities.interface';
|
import { Activities } from '@ghostfolio/api/app/order/interfaces/activities.interface';
|
||||||
import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
|
import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
|
||||||
import { PortfolioPositionDetail } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-position-detail.interface';
|
import { PortfolioHoldingDetail } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-holding-detail.interface';
|
||||||
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
|
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
|
||||||
import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface';
|
import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface';
|
||||||
import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interface';
|
import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interface';
|
||||||
@ -325,6 +325,31 @@ export class DataService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fetchHoldingDetail({
|
||||||
|
dataSource,
|
||||||
|
symbol
|
||||||
|
}: {
|
||||||
|
dataSource: DataSource;
|
||||||
|
symbol: string;
|
||||||
|
}) {
|
||||||
|
return this.http
|
||||||
|
.get<PortfolioHoldingDetail>(
|
||||||
|
`/api/v1/portfolio/position/${dataSource}/${symbol}`
|
||||||
|
)
|
||||||
|
.pipe(
|
||||||
|
map((data) => {
|
||||||
|
if (data.orders) {
|
||||||
|
for (const order of data.orders) {
|
||||||
|
order.createdAt = parseISO(<string>(<unknown>order.createdAt));
|
||||||
|
order.date = parseISO(<string>(<unknown>order.date));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public fetchInfo(): InfoItem {
|
public fetchInfo(): InfoItem {
|
||||||
const info = cloneDeep((window as any).info);
|
const info = cloneDeep((window as any).info);
|
||||||
const utmSource = <'ios' | 'trusted-web-activity'>(
|
const utmSource = <'ios' | 'trusted-web-activity'>(
|
||||||
@ -563,31 +588,6 @@ export class DataService {
|
|||||||
return this.http.get<PortfolioReport>('/api/v1/portfolio/report');
|
return this.http.get<PortfolioReport>('/api/v1/portfolio/report');
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchPositionDetail({
|
|
||||||
dataSource,
|
|
||||||
symbol
|
|
||||||
}: {
|
|
||||||
dataSource: DataSource;
|
|
||||||
symbol: string;
|
|
||||||
}) {
|
|
||||||
return this.http
|
|
||||||
.get<PortfolioPositionDetail>(
|
|
||||||
`/api/v1/portfolio/position/${dataSource}/${symbol}`
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
map((data) => {
|
|
||||||
if (data.orders) {
|
|
||||||
for (const order of data.orders) {
|
|
||||||
order.createdAt = parseISO(<string>(<unknown>order.createdAt));
|
|
||||||
order.date = parseISO(<string>(<unknown>order.date));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public loginAnonymous(accessToken: string) {
|
public loginAnonymous(accessToken: string) {
|
||||||
return this.http.post<OAuthResponse>(`/api/v1/auth/anonymous`, {
|
return this.http.post<OAuthResponse>(`/api/v1/auth/anonymous`, {
|
||||||
accessToken
|
accessToken
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component';
|
import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component';
|
||||||
import { GfPositionDetailDialogModule } from '@ghostfolio/client/components/position-detail-dialog/position-detail-dialog.module';
|
import { GfHoldingDetailDialogComponent } from '@ghostfolio/client/components/holding-detail-dialog/holding-detail-dialog.component';
|
||||||
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
|
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
|
||||||
import { getLocale } from '@ghostfolio/common/helper';
|
import { getLocale } from '@ghostfolio/common/helper';
|
||||||
import { PortfolioPosition, UniqueAsset } from '@ghostfolio/common/interfaces';
|
import { PortfolioPosition, UniqueAsset } from '@ghostfolio/common/interfaces';
|
||||||
@ -23,7 +23,7 @@ import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
|
|||||||
import { MatSort, MatSortModule } from '@angular/material/sort';
|
import { MatSort, MatSortModule } from '@angular/material/sort';
|
||||||
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
||||||
import { Router, RouterModule } from '@angular/router';
|
import { Router, RouterModule } from '@angular/router';
|
||||||
import { AssetClass, AssetSubClass } from '@prisma/client';
|
import { AssetSubClass } from '@prisma/client';
|
||||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||||
import { Subject, Subscription } from 'rxjs';
|
import { Subject, Subscription } from 'rxjs';
|
||||||
|
|
||||||
@ -32,8 +32,8 @@ import { Subject, Subscription } from 'rxjs';
|
|||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
GfAssetProfileIconComponent,
|
GfAssetProfileIconComponent,
|
||||||
|
GfHoldingDetailDialogComponent,
|
||||||
GfNoTransactionsInfoComponent,
|
GfNoTransactionsInfoComponent,
|
||||||
GfPositionDetailDialogModule,
|
|
||||||
GfSymbolModule,
|
GfSymbolModule,
|
||||||
GfValueComponent,
|
GfValueComponent,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user