mirror of https://github.com/ghostfolio/ghostfolio
62 changed files with 5102 additions and 3143 deletions
@ -1,23 +0,0 @@ |
|||
import { PortfolioItem, Position } from '@ghostfolio/common/interfaces'; |
|||
|
|||
import { Order } from '../order'; |
|||
|
|||
export interface PortfolioInterface { |
|||
get(aDate?: Date): PortfolioItem[]; |
|||
|
|||
getFees(): number; |
|||
|
|||
getPositions(aDate: Date): { |
|||
[symbol: string]: Position; |
|||
}; |
|||
|
|||
getSymbols(aDate?: Date): string[]; |
|||
|
|||
getTotalBuy(): number; |
|||
|
|||
getTotalSell(): number; |
|||
|
|||
getOrders(): Order[]; |
|||
|
|||
getValue(aDate?: Date): number; |
|||
} |
@ -1,83 +0,0 @@ |
|||
import { IOrder } from '@ghostfolio/api/services/interfaces/interfaces'; |
|||
|
|||
import { Account, SymbolProfile, Type as ActivityType } from '@prisma/client'; |
|||
import { v4 as uuidv4 } from 'uuid'; |
|||
|
|||
export class Order { |
|||
private account: Account; |
|||
private currency: string; |
|||
private fee: number; |
|||
private date: string; |
|||
private id: string; |
|||
private isDraft: boolean; |
|||
private quantity: number; |
|||
private symbol: string; |
|||
private symbolProfile: SymbolProfile; |
|||
private total: number; |
|||
private type: ActivityType; |
|||
private unitPrice: number; |
|||
|
|||
public constructor(data: IOrder) { |
|||
this.account = data.account; |
|||
this.currency = data.currency; |
|||
this.fee = data.fee; |
|||
this.date = data.date; |
|||
this.id = data.id || uuidv4(); |
|||
this.isDraft = data.isDraft; |
|||
this.quantity = data.quantity; |
|||
this.symbol = data.symbol; |
|||
this.symbolProfile = data.symbolProfile; |
|||
this.type = data.type; |
|||
this.unitPrice = data.unitPrice; |
|||
|
|||
this.total = this.quantity * data.unitPrice; |
|||
} |
|||
|
|||
public getAccount() { |
|||
return this.account; |
|||
} |
|||
|
|||
public getCurrency() { |
|||
return this.currency; |
|||
} |
|||
|
|||
public getDate() { |
|||
return this.date; |
|||
} |
|||
|
|||
public getFee() { |
|||
return this.fee; |
|||
} |
|||
|
|||
public getId() { |
|||
return this.id; |
|||
} |
|||
|
|||
public getIsDraft() { |
|||
return this.isDraft; |
|||
} |
|||
|
|||
public getQuantity() { |
|||
return this.quantity; |
|||
} |
|||
|
|||
public getSymbol() { |
|||
return this.symbol; |
|||
} |
|||
|
|||
getSymbolProfile() { |
|||
return this.symbolProfile; |
|||
} |
|||
|
|||
public getTotal() { |
|||
return this.total; |
|||
} |
|||
|
|||
public getType() { |
|||
return this.type; |
|||
} |
|||
|
|||
public getUnitPrice() { |
|||
return this.unitPrice; |
|||
} |
|||
} |
@ -1,115 +1,94 @@ |
|||
<div class="container"> |
|||
<div class="row"> |
|||
<div class="col"> |
|||
<div class="d-flex justify-content-end"> |
|||
<a |
|||
color="primary" |
|||
i18n |
|||
mat-flat-button |
|||
[queryParams]="{ createPlatformDialog: true }" |
|||
[routerLink]="[]" |
|||
> |
|||
Add Platform |
|||
</a> |
|||
</div> |
|||
<table |
|||
class="gf-table w-100" |
|||
mat-table |
|||
matSort |
|||
matSortActive="name" |
|||
matSortDirection="asc" |
|||
[dataSource]="dataSource" |
|||
> |
|||
<ng-container matColumnDef="name"> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1" |
|||
mat-header-cell |
|||
mat-sort-header="name" |
|||
> |
|||
<ng-container i18n>Name</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
@if (element.url) { |
|||
<gf-asset-profile-icon |
|||
class="d-inline mr-1" |
|||
[tooltip]="element.name" |
|||
[url]="element.url" |
|||
/> |
|||
} |
|||
<span>{{ element.name }}</span> |
|||
</td></ng-container |
|||
> |
|||
<div class="d-flex justify-content-end"> |
|||
<a |
|||
color="primary" |
|||
i18n |
|||
mat-flat-button |
|||
[queryParams]="{ createPlatformDialog: true }" |
|||
[routerLink]="[]" |
|||
> |
|||
Add Platform |
|||
</a> |
|||
</div> |
|||
<table |
|||
class="gf-table w-100" |
|||
mat-table |
|||
matSort |
|||
matSortActive="name" |
|||
matSortDirection="asc" |
|||
[dataSource]="dataSource" |
|||
> |
|||
<ng-container matColumnDef="name"> |
|||
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header="name"> |
|||
<ng-container i18n>Name</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
@if (element.url) { |
|||
<gf-asset-profile-icon |
|||
class="d-inline mr-1" |
|||
[tooltip]="element.name" |
|||
[url]="element.url" |
|||
/> |
|||
} |
|||
<span>{{ element.name }}</span> |
|||
</td></ng-container |
|||
> |
|||
|
|||
<ng-container matColumnDef="url"> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1" |
|||
mat-header-cell |
|||
mat-sort-header="url" |
|||
> |
|||
<ng-container i18n>Url</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
{{ element.url }} |
|||
</td> |
|||
</ng-container> |
|||
<ng-container matColumnDef="url"> |
|||
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header="url"> |
|||
<ng-container i18n>Url</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
{{ element.url }} |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<ng-container matColumnDef="accounts"> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1" |
|||
mat-header-cell |
|||
mat-sort-header="accountCount" |
|||
> |
|||
<ng-container i18n>Accounts</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
{{ element.accountCount }} |
|||
</td> |
|||
</ng-container> |
|||
<ng-container matColumnDef="accounts"> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1" |
|||
mat-header-cell |
|||
mat-sort-header="accountCount" |
|||
> |
|||
<ng-container i18n>Accounts</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1 text-right" mat-cell> |
|||
{{ element.accountCount }} |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<ng-container matColumnDef="actions" stickyEnd> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1 text-center" |
|||
i18n |
|||
mat-header-cell |
|||
></th> |
|||
<td *matCellDef="let element" class="px-1 text-center" mat-cell> |
|||
<button |
|||
class="mx-1 no-min-width px-2" |
|||
mat-button |
|||
[matMenuTriggerFor]="platformMenu" |
|||
(click)="$event.stopPropagation()" |
|||
> |
|||
<ion-icon name="ellipsis-horizontal" /> |
|||
</button> |
|||
<mat-menu #platformMenu="matMenu" xPosition="before"> |
|||
<button mat-menu-item (click)="onUpdatePlatform(element)"> |
|||
<span class="align-items-center d-flex"> |
|||
<ion-icon class="mr-2" name="create-outline" /> |
|||
<span i18n>Edit</span> |
|||
</span> |
|||
</button> |
|||
<hr class="m-0" /> |
|||
<button |
|||
mat-menu-item |
|||
[disabled]="element.accountCount > 0" |
|||
(click)="onDeletePlatform(element.id)" |
|||
> |
|||
<span class="align-items-center d-flex"> |
|||
<ion-icon class="mr-2" name="trash-outline" /> |
|||
<span i18n>Delete</span> |
|||
</span> |
|||
</button> |
|||
</mat-menu> |
|||
</td> |
|||
</ng-container> |
|||
<ng-container matColumnDef="actions" stickyEnd> |
|||
<th *matHeaderCellDef class="px-1 text-center" i18n mat-header-cell></th> |
|||
<td *matCellDef="let element" class="px-1 text-center" mat-cell> |
|||
<button |
|||
class="mx-1 no-min-width px-2" |
|||
mat-button |
|||
[matMenuTriggerFor]="platformMenu" |
|||
(click)="$event.stopPropagation()" |
|||
> |
|||
<ion-icon name="ellipsis-horizontal" /> |
|||
</button> |
|||
<mat-menu #platformMenu="matMenu" xPosition="before"> |
|||
<button mat-menu-item (click)="onUpdatePlatform(element)"> |
|||
<span class="align-items-center d-flex"> |
|||
<ion-icon class="mr-2" name="create-outline" /> |
|||
<span i18n>Edit</span> |
|||
</span> |
|||
</button> |
|||
<hr class="m-0" /> |
|||
<button |
|||
mat-menu-item |
|||
[disabled]="element.accountCount > 0" |
|||
(click)="onDeletePlatform(element.id)" |
|||
> |
|||
<span class="align-items-center d-flex"> |
|||
<ion-icon class="mr-2" name="trash-outline" /> |
|||
<span i18n>Delete</span> |
|||
</span> |
|||
</button> |
|||
</mat-menu> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr> |
|||
<tr *matRowDef="let row; columns: displayedColumns" mat-row></tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr> |
|||
<tr *matRowDef="let row; columns: displayedColumns" mat-row></tr> |
|||
</table> |
|||
|
@ -1,3 +1,15 @@ |
|||
:host { |
|||
display: block; |
|||
|
|||
.mat-mdc-progress-bar { |
|||
--mdc-linear-progress-active-indicator-height: 0.5rem; |
|||
--mdc-linear-progress-track-height: 0.5rem; |
|||
border-radius: 0.25rem; |
|||
|
|||
::ng-deep { |
|||
.mdc-linear-progress__buffer-bar { |
|||
background-color: rgb(var(--palette-background-unselected-chip)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
@ -1,108 +1,87 @@ |
|||
<div class="container"> |
|||
<div class="row"> |
|||
<div class="col"> |
|||
<div class="d-flex justify-content-end"> |
|||
<a |
|||
color="primary" |
|||
i18n |
|||
mat-flat-button |
|||
[queryParams]="{ createTagDialog: true }" |
|||
[routerLink]="[]" |
|||
> |
|||
Add Tag |
|||
</a> |
|||
</div> |
|||
<table |
|||
class="gf-table w-100" |
|||
mat-table |
|||
matSort |
|||
matSortActive="name" |
|||
matSortDirection="asc" |
|||
[dataSource]="dataSource" |
|||
> |
|||
<ng-container matColumnDef="name"> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1" |
|||
mat-header-cell |
|||
mat-sort-header="name" |
|||
> |
|||
<ng-container i18n>Name</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
{{ element.name }} |
|||
</td> |
|||
</ng-container> |
|||
<div class="d-flex justify-content-end"> |
|||
<a |
|||
color="primary" |
|||
i18n |
|||
mat-flat-button |
|||
[queryParams]="{ createTagDialog: true }" |
|||
[routerLink]="[]" |
|||
> |
|||
Add Tag |
|||
</a> |
|||
</div> |
|||
<table |
|||
class="gf-table w-100" |
|||
mat-table |
|||
matSort |
|||
matSortActive="name" |
|||
matSortDirection="asc" |
|||
[dataSource]="dataSource" |
|||
> |
|||
<ng-container matColumnDef="name"> |
|||
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header="name"> |
|||
<ng-container i18n>Name</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
{{ element.name }} |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<ng-container matColumnDef="userId"> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1" |
|||
mat-header-cell |
|||
mat-sort-header="userId" |
|||
> |
|||
<ng-container i18n>User</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
<span class="text-monospace">{{ element.userId }}</span> |
|||
</td> |
|||
</ng-container> |
|||
<ng-container matColumnDef="userId"> |
|||
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header="userId"> |
|||
<ng-container i18n>User</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
<span class="text-monospace">{{ element.userId }}</span> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<ng-container matColumnDef="activities"> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1" |
|||
mat-header-cell |
|||
mat-sort-header="activityCount" |
|||
> |
|||
<ng-container i18n>Activities</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1" mat-cell> |
|||
{{ element.activityCount }} |
|||
</td> |
|||
</ng-container> |
|||
<ng-container matColumnDef="activities"> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1" |
|||
mat-header-cell |
|||
mat-sort-header="activityCount" |
|||
> |
|||
<ng-container i18n>Activities</ng-container> |
|||
</th> |
|||
<td *matCellDef="let element" class="px-1 text-right" mat-cell> |
|||
{{ element.activityCount }} |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<ng-container matColumnDef="actions" stickyEnd> |
|||
<th |
|||
*matHeaderCellDef |
|||
class="px-1 text-center" |
|||
i18n |
|||
mat-header-cell |
|||
></th> |
|||
<td *matCellDef="let element" class="px-1 text-center" mat-cell> |
|||
<button |
|||
class="mx-1 no-min-width px-2" |
|||
mat-button |
|||
[matMenuTriggerFor]="tagMenu" |
|||
(click)="$event.stopPropagation()" |
|||
> |
|||
<ion-icon name="ellipsis-horizontal" /> |
|||
</button> |
|||
<mat-menu #tagMenu="matMenu" xPosition="before"> |
|||
<button mat-menu-item (click)="onUpdateTag(element)"> |
|||
<span class="align-items-center d-flex"> |
|||
<ion-icon class="mr-2" name="create-outline" /> |
|||
<span i18n>Edit</span> |
|||
</span> |
|||
</button> |
|||
<hr class="m-0" /> |
|||
<button |
|||
mat-menu-item |
|||
[disabled]="element.activityCount > 0" |
|||
(click)="onDeleteTag(element.id)" |
|||
> |
|||
<span class="align-items-center d-flex"> |
|||
<ion-icon class="mr-2" name="trash-outline" /> |
|||
<span i18n>Delete</span> |
|||
</span> |
|||
</button> |
|||
</mat-menu> |
|||
</td> |
|||
</ng-container> |
|||
<ng-container matColumnDef="actions" stickyEnd> |
|||
<th *matHeaderCellDef class="px-1 text-center" i18n mat-header-cell></th> |
|||
<td *matCellDef="let element" class="px-1 text-center" mat-cell> |
|||
<button |
|||
class="mx-1 no-min-width px-2" |
|||
mat-button |
|||
[matMenuTriggerFor]="tagMenu" |
|||
(click)="$event.stopPropagation()" |
|||
> |
|||
<ion-icon name="ellipsis-horizontal" /> |
|||
</button> |
|||
<mat-menu #tagMenu="matMenu" xPosition="before"> |
|||
<button mat-menu-item (click)="onUpdateTag(element)"> |
|||
<span class="align-items-center d-flex"> |
|||
<ion-icon class="mr-2" name="create-outline" /> |
|||
<span i18n>Edit</span> |
|||
</span> |
|||
</button> |
|||
<hr class="m-0" /> |
|||
<button |
|||
mat-menu-item |
|||
[disabled]="element.activityCount > 0" |
|||
(click)="onDeleteTag(element.id)" |
|||
> |
|||
<span class="align-items-center d-flex"> |
|||
<ion-icon class="mr-2" name="trash-outline" /> |
|||
<span i18n>Delete</span> |
|||
</span> |
|||
</button> |
|||
</mat-menu> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr> |
|||
<tr *matRowDef="let row; columns: displayedColumns" mat-row></tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr> |
|||
<tr *matRowDef="let row; columns: displayedColumns" mat-row></tr> |
|||
</table> |
|||
|
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -1,9 +0,0 @@ |
|||
import { Position } from '@ghostfolio/common/interfaces'; |
|||
|
|||
export interface PortfolioItem { |
|||
date: string; |
|||
grossPerformancePercent: number; |
|||
investment: number; |
|||
positions: { [symbol: string]: Position }; |
|||
value: number; |
|||
} |
@ -1,8 +0,0 @@ |
|||
export interface PortfolioOverview { |
|||
cash: number; |
|||
committedFunds: number; |
|||
fees: number; |
|||
ordersCount: number; |
|||
totalBuy: number; |
|||
totalSell: number; |
|||
} |
File diff suppressed because it is too large
Loading…
Reference in new issue