Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
0b2252755c | |||
239bd09cbd | |||
cd76f89902 | |||
7425ba94f1 | |||
b9522307c4 |
17
CHANGELOG.md
17
CHANGELOG.md
@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 1.74.0 - 11.11.2021
|
||||
|
||||
### Changed
|
||||
|
||||
- Adapted the decimal places for cryptocurrencies in the position detail dialog
|
||||
- Moved the _Fear & Greed Index_ (market mood) to a new tab on the home page
|
||||
|
||||
## 1.73.0 - 10.11.2021
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved the info messages to add the first transaction
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the skeleton loader of the portfolio holdings
|
||||
|
||||
## 1.72.0 - 08.11.2021
|
||||
|
||||
### Changed
|
||||
|
@ -1,4 +1,8 @@
|
||||
import { AssetClass, AssetSubClass } from '@prisma/client';
|
||||
|
||||
export interface PortfolioPositionDetail {
|
||||
assetClass?: AssetClass;
|
||||
assetSubClass?: AssetSubClass;
|
||||
averagePrice: number;
|
||||
currency: string;
|
||||
firstBuyDate: string;
|
||||
|
@ -1,5 +1,3 @@
|
||||
// TODO ///////////
|
||||
|
||||
import { AccountService } from '@ghostfolio/api/app/account/account.service';
|
||||
import { CashDetails } from '@ghostfolio/api/app/account/interfaces/cash-details.interface';
|
||||
import { OrderService } from '@ghostfolio/api/app/order/order.service';
|
||||
@ -299,6 +297,8 @@ export class PortfolioService {
|
||||
};
|
||||
}
|
||||
|
||||
const assetClass = orders[0].SymbolProfile?.assetClass;
|
||||
const assetSubClass = orders[0].SymbolProfile?.assetSubClass;
|
||||
const positionCurrency = orders[0].currency;
|
||||
const name = orders[0].SymbolProfile?.name ?? '';
|
||||
|
||||
@ -412,6 +412,8 @@ export class PortfolioService {
|
||||
}
|
||||
|
||||
return {
|
||||
assetClass,
|
||||
assetSubClass,
|
||||
currency,
|
||||
firstBuyDate,
|
||||
grossPerformance,
|
||||
@ -467,6 +469,8 @@ export class PortfolioService {
|
||||
}
|
||||
|
||||
return {
|
||||
assetClass,
|
||||
assetSubClass,
|
||||
marketPrice,
|
||||
maxPrice,
|
||||
minPrice,
|
||||
|
@ -2,6 +2,5 @@ import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.i
|
||||
|
||||
export interface PositionDetailDialogParams {
|
||||
deviceType: string;
|
||||
fearAndGreedIndex: number;
|
||||
historicalDataItems: LineChartItem[];
|
||||
}
|
||||
|
@ -22,13 +22,11 @@ import { PositionDetailDialogParams } from './interfaces/interfaces';
|
||||
})
|
||||
export class PerformanceChartDialog {
|
||||
public benchmarkDataItems: LineChartItem[];
|
||||
public benchmarkLabel = 'S&P 500';
|
||||
public benchmarkSymbol = 'VOO';
|
||||
public currency: string;
|
||||
public firstBuyDate: string;
|
||||
public marketPrice: number;
|
||||
public historicalDataItems: LineChartItem[];
|
||||
public title: string;
|
||||
|
||||
private unsubscribeSubject = new Subject<void>();
|
||||
|
||||
@ -83,8 +81,6 @@ export class PerformanceChartDialog {
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
});
|
||||
|
||||
this.title = `Performance vs. ${this.benchmarkLabel}`;
|
||||
}
|
||||
|
||||
public onClose(): void {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<gf-dialog-header
|
||||
mat-dialog-title
|
||||
title="Performance"
|
||||
[deviceType]="data.deviceType"
|
||||
[title]="title"
|
||||
(closeButtonClicked)="onClose()"
|
||||
></gf-dialog-header>
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
class="mb-4"
|
||||
symbol="Performance"
|
||||
[benchmarkDataItems]="benchmarkDataItems"
|
||||
[benchmarkLabel]="benchmarkLabel"
|
||||
[historicalDataItems]="historicalDataItems"
|
||||
[showGradient]="true"
|
||||
[showLegend]="true"
|
||||
@ -19,13 +18,6 @@
|
||||
[showYAxis]="false"
|
||||
></gf-line-chart>
|
||||
</div>
|
||||
|
||||
<div *ngIf="data.fearAndGreedIndex" class="container p-0">
|
||||
<gf-fear-and-greed-index
|
||||
class="d-flex flex-column justify-content-center"
|
||||
[fearAndGreedIndex]="data.fearAndGreedIndex"
|
||||
></gf-fear-and-greed-index>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<gf-dialog-footer
|
||||
|
@ -8,7 +8,6 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||
|
||||
import { GfDialogFooterModule } from '../dialog-footer/dialog-footer.module';
|
||||
import { GfDialogHeaderModule } from '../dialog-header/dialog-header.module';
|
||||
import { GfFearAndGreedIndexModule } from '../fear-and-greed-index/fear-and-greed-index.module';
|
||||
import { PerformanceChartDialog } from './performance-chart-dialog.component';
|
||||
|
||||
@NgModule({
|
||||
@ -18,7 +17,6 @@ import { PerformanceChartDialog } from './performance-chart-dialog.component';
|
||||
CommonModule,
|
||||
GfDialogFooterModule,
|
||||
GfDialogHeaderModule,
|
||||
GfFearAndGreedIndexModule,
|
||||
GfLineChartModule,
|
||||
GfValueModule,
|
||||
MatButtonModule,
|
||||
|
@ -9,6 +9,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { DATE_FORMAT } from '@ghostfolio/common/helper';
|
||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||
import { AssetSubClass } from '@prisma/client';
|
||||
import { format, isSameMonth, isToday, parseISO } from 'date-fns';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
@ -23,6 +24,7 @@ import { PositionDetailDialogParams } from './interfaces/interfaces';
|
||||
styleUrls: ['./position-detail-dialog.component.scss']
|
||||
})
|
||||
export class PositionDetailDialog implements OnDestroy {
|
||||
public assetSubClass: AssetSubClass;
|
||||
public averagePrice: number;
|
||||
public benchmarkDataItems: LineChartItem[];
|
||||
public currency: string;
|
||||
@ -38,6 +40,7 @@ export class PositionDetailDialog implements OnDestroy {
|
||||
public netPerformance: number;
|
||||
public netPerformancePercent: number;
|
||||
public quantity: number;
|
||||
public quantityPrecision = 2;
|
||||
public symbol: string;
|
||||
public transactionCount: number;
|
||||
|
||||
@ -54,6 +57,7 @@ export class PositionDetailDialog implements OnDestroy {
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe(
|
||||
({
|
||||
assetSubClass,
|
||||
averagePrice,
|
||||
currency,
|
||||
firstBuyDate,
|
||||
@ -71,6 +75,7 @@ export class PositionDetailDialog implements OnDestroy {
|
||||
symbol,
|
||||
transactionCount
|
||||
}) => {
|
||||
this.assetSubClass = assetSubClass;
|
||||
this.averagePrice = averagePrice;
|
||||
this.benchmarkDataItems = [];
|
||||
this.currency = currency;
|
||||
@ -146,6 +151,18 @@ export class PositionDetailDialog implements OnDestroy {
|
||||
this.benchmarkDataItems[0].value = this.averagePrice;
|
||||
}
|
||||
|
||||
if (Number.isInteger(this.quantity)) {
|
||||
this.quantityPrecision = 0;
|
||||
} else if (assetSubClass === 'CRYPTOCURRENCY') {
|
||||
if (this.quantity < 1) {
|
||||
this.quantityPrecision = 7;
|
||||
} else if (this.quantity < 1000) {
|
||||
this.quantityPrecision = 5;
|
||||
} else if (this.quantity > 10000000) {
|
||||
this.quantityPrecision = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
}
|
||||
);
|
||||
|
@ -82,7 +82,7 @@
|
||||
label="Quantity"
|
||||
size="medium"
|
||||
[locale]="data.locale"
|
||||
[precision]="2"
|
||||
[precision]="quantityPrecision"
|
||||
[value]="quantity"
|
||||
></gf-value>
|
||||
</div>
|
||||
|
@ -103,7 +103,9 @@
|
||||
></ngx-skeleton-loader>
|
||||
|
||||
<div *ngIf="dataSource.data.length === 0 && !isLoading" class="p-3 text-center">
|
||||
<gf-no-transactions-info-indicator></gf-no-transactions-info-indicator>
|
||||
<gf-no-transactions-info-indicator
|
||||
[hasBorder]="false"
|
||||
></gf-no-transactions-info-indicator>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
@ -24,7 +24,9 @@
|
||||
></gf-position>
|
||||
</ng-container>
|
||||
<div *ngIf="!hasPositions" class="p-3 text-center">
|
||||
<gf-no-transactions-info-indicator></gf-no-transactions-info-indicator>
|
||||
<gf-no-transactions-info-indicator
|
||||
[hasBorder]="false"
|
||||
></gf-no-transactions-info-indicator>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
@ -2,7 +2,9 @@
|
||||
<div class="row no-gutters">
|
||||
<div class="col">
|
||||
<mat-card *ngIf="rules === null" class="my-2 text-center">
|
||||
<gf-no-transactions-info-indicator></gf-no-transactions-info-indicator>
|
||||
<gf-no-transactions-info-indicator
|
||||
[hasBorder]="false"
|
||||
></gf-no-transactions-info-indicator>
|
||||
</mat-card>
|
||||
|
||||
<gf-rule *ngIf="rules === undefined" [isLoading]="true"></gf-rule>
|
||||
|
@ -270,3 +270,9 @@
|
||||
width: '100%'
|
||||
}"
|
||||
></ngx-skeleton-loader>
|
||||
|
||||
<div *ngIf="dataSource.data.length === 0 && !isLoading" class="p-3 text-center">
|
||||
<gf-no-transactions-info-indicator
|
||||
[hasBorder]="false"
|
||||
></gf-no-transactions-info-indicator>
|
||||
</div>
|
||||
|
@ -10,6 +10,7 @@ import { MatSortModule } from '@angular/material/sort';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
|
||||
import { GfNoTransactionsInfoModule } from '@ghostfolio/ui/no-transactions-info';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||
|
||||
@ -22,6 +23,7 @@ import { TransactionsTableComponent } from './transactions-table.component';
|
||||
exports: [TransactionsTableComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GfNoTransactionsInfoModule,
|
||||
GfPositionDetailDialogModule,
|
||||
GfSymbolIconModule,
|
||||
GfSymbolModule,
|
||||
|
@ -7,10 +7,7 @@ import {
|
||||
OnInit,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatTabChangeEvent } from '@angular/material/tabs';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { PerformanceChartDialog } from '@ghostfolio/client/components/performance-chart-dialog/performance-chart-dialog.component';
|
||||
import { ToggleOption } from '@ghostfolio/client/components/toggle/interfaces/toggle-option.type';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
|
||||
@ -61,7 +58,6 @@ export class HomePageComponent implements OnDestroy, OnInit {
|
||||
public hasImpersonationId: boolean;
|
||||
public hasPermissionToAccessFearAndGreedIndex: boolean;
|
||||
public hasPermissionToCreateOrder: boolean;
|
||||
public hasPositions: boolean;
|
||||
public historicalDataItems: LineChartItem[];
|
||||
public isLoadingPerformance = true;
|
||||
public isLoadingSummary = true;
|
||||
@ -80,21 +76,10 @@ export class HomePageComponent implements OnDestroy, OnInit {
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
private dataService: DataService,
|
||||
private deviceService: DeviceDetectorService,
|
||||
private dialog: MatDialog,
|
||||
private impersonationStorageService: ImpersonationStorageService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private settingsStorageService: SettingsStorageService,
|
||||
private userService: UserService
|
||||
) {
|
||||
this.routeQueryParams = this.route.queryParams
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe((params) => {
|
||||
if (params['performanceChartDialog']) {
|
||||
this.openDialog();
|
||||
}
|
||||
});
|
||||
|
||||
this.userService.stateChanged
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe((state) => {
|
||||
@ -173,25 +158,6 @@ export class HomePageComponent implements OnDestroy, OnInit {
|
||||
this.unsubscribeSubject.complete();
|
||||
}
|
||||
|
||||
private openDialog(): void {
|
||||
const dialogRef = this.dialog.open(PerformanceChartDialog, {
|
||||
autoFocus: false,
|
||||
data: {
|
||||
deviceType: this.deviceType,
|
||||
fearAndGreedIndex: this.fearAndGreedIndex,
|
||||
historicalDataItems: this.historicalDataItems
|
||||
},
|
||||
width: '50rem'
|
||||
});
|
||||
|
||||
dialogRef
|
||||
.afterClosed()
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe(() => {
|
||||
this.router.navigate(['.'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
|
||||
private update() {
|
||||
if (this.currentTabIndex === 0) {
|
||||
this.isLoadingPerformance = true;
|
||||
@ -225,7 +191,6 @@ export class HomePageComponent implements OnDestroy, OnInit {
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe((response) => {
|
||||
this.positions = response.positions;
|
||||
this.hasPositions = this.positions?.length > 0;
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
});
|
||||
|
@ -23,12 +23,7 @@
|
||||
"
|
||||
>
|
||||
<div class="row w-100">
|
||||
<a
|
||||
*ngIf="historicalDataItems?.length !== 0"
|
||||
class="chart-container col"
|
||||
[routerLink]="[]"
|
||||
[queryParams]="{performanceChartDialog: true}"
|
||||
>
|
||||
<div class="chart-container col">
|
||||
<gf-line-chart
|
||||
class="mr-3"
|
||||
symbol="Performance"
|
||||
@ -38,19 +33,19 @@
|
||||
[showXAxis]="false"
|
||||
[showYAxis]="false"
|
||||
></gf-line-chart>
|
||||
</a>
|
||||
<div
|
||||
*ngIf="historicalDataItems?.length === 0"
|
||||
class="
|
||||
align-items-center
|
||||
chart-container
|
||||
d-flex
|
||||
justify-content-center
|
||||
w-100
|
||||
"
|
||||
>
|
||||
<div class="d-flex justify-content-center">
|
||||
<gf-no-transactions-info-indicator></gf-no-transactions-info-indicator>
|
||||
<div
|
||||
*ngIf="historicalDataItems?.length === 0"
|
||||
class="
|
||||
align-items-center
|
||||
chart-container
|
||||
d-flex
|
||||
justify-content-center
|
||||
w-100
|
||||
"
|
||||
>
|
||||
<div class="d-flex justify-content-center">
|
||||
<gf-no-transactions-info-indicator></gf-no-transactions-info-indicator>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -92,33 +87,25 @@
|
||||
(change)="onChangeDateRange($event.value)"
|
||||
></gf-toggle>
|
||||
</div>
|
||||
<ng-container *ngIf="hasPositions === true">
|
||||
<mat-card class="p-0">
|
||||
<mat-card-content>
|
||||
<gf-positions
|
||||
[baseCurrency]="user?.settings?.baseCurrency"
|
||||
[deviceType]="deviceType"
|
||||
[locale]="user?.settings?.locale"
|
||||
[positions]="positions"
|
||||
[range]="dateRange"
|
||||
></gf-positions>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div *ngIf="hasPermissionToCreateOrder" class="text-center">
|
||||
<a
|
||||
class="mt-3"
|
||||
i18n
|
||||
mat-button
|
||||
[routerLink]="['/portfolio', 'transactions']"
|
||||
>Manage Transactions...</a
|
||||
>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div
|
||||
*ngIf="hasPositions === false"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<gf-no-transactions-info-indicator></gf-no-transactions-info-indicator>
|
||||
<mat-card class="p-0">
|
||||
<mat-card-content>
|
||||
<gf-positions
|
||||
[baseCurrency]="user?.settings?.baseCurrency"
|
||||
[deviceType]="deviceType"
|
||||
[locale]="user?.settings?.locale"
|
||||
[positions]="positions"
|
||||
[range]="dateRange"
|
||||
></gf-positions>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div *ngIf="hasPermissionToCreateOrder" class="text-center">
|
||||
<a
|
||||
class="mt-3"
|
||||
i18n
|
||||
mat-button
|
||||
[routerLink]="['/portfolio', 'transactions']"
|
||||
>Manage Transactions...</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -148,4 +135,33 @@
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab *ngIf="hasPermissionToAccessFearAndGreedIndex">
|
||||
<ng-template mat-tab-label>
|
||||
<ion-icon name="newspaper-outline" size="large"></ion-icon>
|
||||
</ng-template>
|
||||
<div
|
||||
class="
|
||||
align-items-center
|
||||
container
|
||||
d-flex
|
||||
flex-grow-1
|
||||
h-100
|
||||
justify-content-center
|
||||
w-100
|
||||
"
|
||||
>
|
||||
<div class="row w-100">
|
||||
<div class="col-xs-12 col-md-8 offset-md-2">
|
||||
<mat-card class="h-100">
|
||||
<mat-card-content>
|
||||
<gf-fear-and-greed-index
|
||||
class="d-flex justify-content-center"
|
||||
[fearAndGreedIndex]="fearAndGreedIndex"
|
||||
></gf-fear-and-greed-index>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
@ -4,6 +4,7 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfFearAndGreedIndexModule } from '@ghostfolio/client/components/fear-and-greed-index/fear-and-greed-index.module';
|
||||
import { GfPerformanceChartDialogModule } from '@ghostfolio/client/components/performance-chart-dialog/performance-chart-dialog.module';
|
||||
import { GfPortfolioPerformanceModule } from '@ghostfolio/client/components/portfolio-performance/portfolio-performance.module';
|
||||
import { GfPortfolioSummaryModule } from '@ghostfolio/client/components/portfolio-summary/portfolio-summary.module';
|
||||
@ -20,6 +21,7 @@ import { HomePageComponent } from './home-page.component';
|
||||
exports: [],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GfFearAndGreedIndexModule,
|
||||
GfLineChartModule,
|
||||
GfNoTransactionsInfoModule,
|
||||
GfPerformanceChartDialogModule,
|
||||
|
@ -38,7 +38,6 @@ export class ZenPageComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||
public deviceType: string;
|
||||
public hasImpersonationId: boolean;
|
||||
public hasPermissionToCreateOrder: boolean;
|
||||
public hasPositions: boolean;
|
||||
public historicalDataItems: LineChartItem[];
|
||||
public isLoadingPerformance = true;
|
||||
public performance: PortfolioPerformance;
|
||||
@ -140,7 +139,6 @@ export class ZenPageComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe((response) => {
|
||||
this.positions = response.positions;
|
||||
this.hasPositions = this.positions?.length > 0;
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
});
|
||||
|
@ -65,35 +65,25 @@
|
||||
<h3 class="d-flex justify-content-center mb-3" i18n>Holdings</h3>
|
||||
<div class="row">
|
||||
<div class="align-items-center col">
|
||||
<ng-container *ngIf="hasPositions === true">
|
||||
<mat-card class="p-0">
|
||||
<mat-card-content>
|
||||
<gf-positions
|
||||
[baseCurrency]="user?.settings?.baseCurrency"
|
||||
[deviceType]="deviceType"
|
||||
[locale]="user?.settings?.locale"
|
||||
[positions]="positions"
|
||||
[range]="dateRange"
|
||||
></gf-positions>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div *ngIf="hasPermissionToCreateOrder" class="text-center">
|
||||
<a
|
||||
class="mt-3"
|
||||
i18n
|
||||
mat-button
|
||||
[routerLink]="['/portfolio', 'transactions']"
|
||||
>Manage Transactions...</a
|
||||
>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div
|
||||
*ngIf="hasPositions === false"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<div>
|
||||
<gf-no-transactions-info-indicator></gf-no-transactions-info-indicator>
|
||||
</div>
|
||||
<mat-card class="p-0">
|
||||
<mat-card-content>
|
||||
<gf-positions
|
||||
[baseCurrency]="user?.settings?.baseCurrency"
|
||||
[deviceType]="deviceType"
|
||||
[locale]="user?.settings?.locale"
|
||||
[positions]="positions"
|
||||
[range]="dateRange"
|
||||
></gf-positions>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div *ngIf="hasPermissionToCreateOrder" class="text-center">
|
||||
<a
|
||||
class="mt-3"
|
||||
i18n
|
||||
mat-button
|
||||
[routerLink]="['/portfolio', 'transactions']"
|
||||
>Manage Transactions...</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,6 +6,7 @@
|
||||
class="align-items-center justify-content-center"
|
||||
color="primary"
|
||||
[routerLink]="['/portfolio', 'transactions']"
|
||||
[queryParams]="{ createDialog: true }"
|
||||
mat-button
|
||||
>
|
||||
<span i18n>Time to add your first transaction.</span>
|
||||
|
@ -1,8 +1,11 @@
|
||||
:host {
|
||||
border: 1px solid rgba(var(--dark-dividers));
|
||||
border-radius: 0.25rem;
|
||||
display: block;
|
||||
|
||||
&.has-border {
|
||||
border: 1px solid rgba(var(--dark-dividers));
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
gf-logo {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
@ -1,4 +1,9 @@
|
||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
HostBinding,
|
||||
Input
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'gf-no-transactions-info-indicator',
|
||||
@ -6,8 +11,8 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
templateUrl: './no-transactions-info.component.html',
|
||||
styleUrls: ['./no-transactions-info.component.scss']
|
||||
})
|
||||
export class NoTransactionsInfoComponent implements OnInit {
|
||||
public constructor() {}
|
||||
export class NoTransactionsInfoComponent {
|
||||
@HostBinding('class.has-border') @Input() hasBorder = true;
|
||||
|
||||
public ngOnInit() {}
|
||||
public constructor() {}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ghostfolio",
|
||||
"version": "1.72.0",
|
||||
"version": "1.74.0",
|
||||
"homepage": "https://ghostfol.io",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
Reference in New Issue
Block a user