Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
0439a7beaa | |||
608b195ba9 | |||
8cb5fd64dd | |||
ef317a86ed | |||
19ada83d0b | |||
6ecf66ea2a | |||
65ba16c07c |
12
CHANGELOG.md
12
CHANGELOG.md
@ -5,6 +5,18 @@ 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/),
|
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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## 0.92.0 - 25.04.2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Prepared further for multi accounts support: store account for new transactions
|
||||||
|
- Added a horizontal scrollbar to the user table of the admin control panel
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed an issue in the header with outdated data
|
||||||
|
- Fixed an issue on the about page with outdated data
|
||||||
|
|
||||||
## 0.91.0 - 25.04.2021
|
## 0.91.0 - 25.04.2021
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -97,7 +97,7 @@ export class AdminService {
|
|||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
_count: {
|
_count: {
|
||||||
select: { Order: true }
|
select: { Account: true, Order: true }
|
||||||
},
|
},
|
||||||
alias: true,
|
alias: true,
|
||||||
Analytics: {
|
Analytics: {
|
||||||
|
@ -36,6 +36,8 @@ export class ExperimentalService {
|
|||||||
const ordersWithPlatform: OrderWithPlatform[] = aOrders.map((order) => {
|
const ordersWithPlatform: OrderWithPlatform[] = aOrders.map((order) => {
|
||||||
return {
|
return {
|
||||||
...order,
|
...order,
|
||||||
|
accountId: undefined,
|
||||||
|
accountUserId: undefined,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
date: parseISO(order.date),
|
date: parseISO(order.date),
|
||||||
fee: 0,
|
fee: 0,
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
import { Settings, User } from '@prisma/client';
|
import { Account, Settings, User } from '@prisma/client';
|
||||||
|
|
||||||
export type UserWithSettings = User & { Settings: Settings };
|
export type UserWithSettings = User & {
|
||||||
|
Account: Account[];
|
||||||
|
Settings: Settings;
|
||||||
|
};
|
||||||
|
@ -2,6 +2,9 @@ import { Currency, Type } from '@prisma/client';
|
|||||||
import { IsISO8601, IsNumber, IsString, ValidateIf } from 'class-validator';
|
import { IsISO8601, IsNumber, IsString, ValidateIf } from 'class-validator';
|
||||||
|
|
||||||
export class CreateOrderDto {
|
export class CreateOrderDto {
|
||||||
|
@IsString()
|
||||||
|
accountId: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
currency: Currency;
|
currency: Currency;
|
||||||
|
|
||||||
|
@ -118,6 +118,9 @@ export class OrderController {
|
|||||||
|
|
||||||
const date = parseISO(data.date);
|
const date = parseISO(data.date);
|
||||||
|
|
||||||
|
const accountId = data.accountId;
|
||||||
|
delete data.accountId;
|
||||||
|
|
||||||
if (data.platformId) {
|
if (data.platformId) {
|
||||||
const platformId = data.platformId;
|
const platformId = data.platformId;
|
||||||
delete data.platformId;
|
delete data.platformId;
|
||||||
@ -126,6 +129,11 @@ export class OrderController {
|
|||||||
{
|
{
|
||||||
...data,
|
...data,
|
||||||
date,
|
date,
|
||||||
|
Account: {
|
||||||
|
connect: {
|
||||||
|
id_userId: { id: accountId, userId: this.request.user.id }
|
||||||
|
}
|
||||||
|
},
|
||||||
Platform: { connect: { id: platformId } },
|
Platform: { connect: { id: platformId } },
|
||||||
User: { connect: { id: this.request.user.id } }
|
User: { connect: { id: this.request.user.id } }
|
||||||
},
|
},
|
||||||
@ -138,6 +146,11 @@ export class OrderController {
|
|||||||
{
|
{
|
||||||
...data,
|
...data,
|
||||||
date,
|
date,
|
||||||
|
Account: {
|
||||||
|
connect: {
|
||||||
|
id_userId: { id: accountId, userId: this.request.user.id }
|
||||||
|
}
|
||||||
|
},
|
||||||
User: { connect: { id: this.request.user.id } }
|
User: { connect: { id: this.request.user.id } }
|
||||||
},
|
},
|
||||||
this.request.user.id
|
this.request.user.id
|
||||||
@ -169,6 +182,9 @@ export class OrderController {
|
|||||||
|
|
||||||
const date = parseISO(data.date);
|
const date = parseISO(data.date);
|
||||||
|
|
||||||
|
const accountId = data.accountId;
|
||||||
|
delete data.accountId;
|
||||||
|
|
||||||
if (data.platformId) {
|
if (data.platformId) {
|
||||||
const platformId = data.platformId;
|
const platformId = data.platformId;
|
||||||
delete data.platformId;
|
delete data.platformId;
|
||||||
@ -178,6 +194,11 @@ export class OrderController {
|
|||||||
data: {
|
data: {
|
||||||
...data,
|
...data,
|
||||||
date,
|
date,
|
||||||
|
Account: {
|
||||||
|
connect: {
|
||||||
|
id_userId: { id: accountId, userId: this.request.user.id }
|
||||||
|
}
|
||||||
|
},
|
||||||
Platform: { connect: { id: platformId } },
|
Platform: { connect: { id: platformId } },
|
||||||
User: { connect: { id: this.request.user.id } }
|
User: { connect: { id: this.request.user.id } }
|
||||||
},
|
},
|
||||||
@ -199,6 +220,11 @@ export class OrderController {
|
|||||||
data: {
|
data: {
|
||||||
...data,
|
...data,
|
||||||
date,
|
date,
|
||||||
|
Account: {
|
||||||
|
connect: {
|
||||||
|
id_userId: { id: accountId, userId: this.request.user.id }
|
||||||
|
}
|
||||||
|
},
|
||||||
Platform: originalOrder.platformId
|
Platform: originalOrder.platformId
|
||||||
? { disconnect: true }
|
? { disconnect: true }
|
||||||
: undefined,
|
: undefined,
|
||||||
|
@ -2,6 +2,9 @@ import { Currency, Type } from '@prisma/client';
|
|||||||
import { IsISO8601, IsNumber, IsString, ValidateIf } from 'class-validator';
|
import { IsISO8601, IsNumber, IsString, ValidateIf } from 'class-validator';
|
||||||
|
|
||||||
export class UpdateOrderDto {
|
export class UpdateOrderDto {
|
||||||
|
@IsString()
|
||||||
|
accountId: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
currency: Currency;
|
currency: Currency;
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { Currency } from '@prisma/client';
|
import { Account, Currency } from '@prisma/client';
|
||||||
|
|
||||||
import { Access } from './access.interface';
|
import { Access } from './access.interface';
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
access: Access[];
|
access: Access[];
|
||||||
|
accounts: Account[];
|
||||||
alias?: string;
|
alias?: string;
|
||||||
id: string;
|
id: string;
|
||||||
permissions: string[];
|
permissions: string[];
|
||||||
|
@ -25,6 +25,7 @@ export class UserService {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async getUser({
|
public async getUser({
|
||||||
|
Account,
|
||||||
alias,
|
alias,
|
||||||
id,
|
id,
|
||||||
role,
|
role,
|
||||||
@ -53,6 +54,7 @@ export class UserService {
|
|||||||
id: accessItem.id
|
id: accessItem.id
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
accounts: Account,
|
||||||
permissions: currentPermissions,
|
permissions: currentPermissions,
|
||||||
settings: {
|
settings: {
|
||||||
baseCurrency: Settings?.currency || UserService.DEFAULT_CURRENCY,
|
baseCurrency: Settings?.currency || UserService.DEFAULT_CURRENCY,
|
||||||
@ -69,7 +71,7 @@ export class UserService {
|
|||||||
userWhereUniqueInput: Prisma.UserWhereUniqueInput
|
userWhereUniqueInput: Prisma.UserWhereUniqueInput
|
||||||
): Promise<UserWithSettings | null> {
|
): Promise<UserWithSettings | null> {
|
||||||
const user = await this.prisma.user.findUnique({
|
const user = await this.prisma.user.findUnique({
|
||||||
include: { Settings: true },
|
include: { Account: true, Settings: true },
|
||||||
where: userWhereUniqueInput
|
where: userWhereUniqueInput
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,6 +14,9 @@ import { PrismaService } from '../services/prisma.service';
|
|||||||
import { RulesService } from '../services/rules.service';
|
import { RulesService } from '../services/rules.service';
|
||||||
import { Portfolio } from './portfolio';
|
import { Portfolio } from './portfolio';
|
||||||
|
|
||||||
|
const DEFAULT_ACCOUNT_ID = '693a834b-eb89-42c9-ae47-35196c25d269';
|
||||||
|
const USER_ID = 'ca6ce867-5d31-495a-bce9-5942bbca9237';
|
||||||
|
|
||||||
describe('Portfolio', () => {
|
describe('Portfolio', () => {
|
||||||
let alphaVantageService: AlphaVantageService;
|
let alphaVantageService: AlphaVantageService;
|
||||||
let configurationService: ConfigurationService;
|
let configurationService: ConfigurationService;
|
||||||
@ -69,13 +72,13 @@ describe('Portfolio', () => {
|
|||||||
accessToken: null,
|
accessToken: null,
|
||||||
alias: 'Test',
|
alias: 'Test',
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
id: '',
|
id: USER_ID,
|
||||||
provider: null,
|
provider: null,
|
||||||
role: Role.USER,
|
role: Role.USER,
|
||||||
Settings: {
|
Settings: {
|
||||||
currency: Currency.CHF,
|
currency: Currency.CHF,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
userId: ''
|
userId: USER_ID
|
||||||
},
|
},
|
||||||
thirdPartyId: null,
|
thirdPartyId: null,
|
||||||
updatedAt: new Date()
|
updatedAt: new Date()
|
||||||
@ -126,6 +129,8 @@ describe('Portfolio', () => {
|
|||||||
it('should return ["BTC"]', async () => {
|
it('should return ["BTC"]', async () => {
|
||||||
await portfolio.setOrders([
|
await portfolio.setOrders([
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.USD,
|
currency: Currency.USD,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
@ -137,7 +142,7 @@ describe('Portfolio', () => {
|
|||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 49631.24,
|
unitPrice: 49631.24,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -224,6 +229,8 @@ describe('Portfolio', () => {
|
|||||||
it('should return ["ETHUSD"]', async () => {
|
it('should return ["ETHUSD"]', async () => {
|
||||||
await portfolio.setOrders([
|
await portfolio.setOrders([
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.USD,
|
currency: Currency.USD,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
@ -235,7 +242,7 @@ describe('Portfolio', () => {
|
|||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 991.49,
|
unitPrice: 991.49,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -276,7 +283,7 @@ describe('Portfolio', () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
quantity: 0.2,
|
quantity: 0.2,
|
||||||
shareCurrent: 1,
|
// shareCurrent: 1,
|
||||||
shareInvestment: 1,
|
shareInvestment: 1,
|
||||||
symbol: 'ETHUSD',
|
symbol: 'ETHUSD',
|
||||||
type: 'Cryptocurrency'
|
type: 'Cryptocurrency'
|
||||||
@ -316,6 +323,8 @@ describe('Portfolio', () => {
|
|||||||
it('should return ["ETHUSD"]', async () => {
|
it('should return ["ETHUSD"]', async () => {
|
||||||
await portfolio.setOrders([
|
await portfolio.setOrders([
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.USD,
|
currency: Currency.USD,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
@ -327,9 +336,11 @@ describe('Portfolio', () => {
|
|||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 991.49,
|
unitPrice: 991.49,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.USD,
|
currency: Currency.USD,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
@ -341,7 +352,7 @@ describe('Portfolio', () => {
|
|||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 1050,
|
unitPrice: 1050,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -388,6 +399,8 @@ describe('Portfolio', () => {
|
|||||||
it('should return ["BTCUSD", "ETHUSD"]', async () => {
|
it('should return ["BTCUSD", "ETHUSD"]', async () => {
|
||||||
await portfolio.setOrders([
|
await portfolio.setOrders([
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.EUR,
|
currency: Currency.EUR,
|
||||||
date: new Date(getUtc('2017-08-16')),
|
date: new Date(getUtc('2017-08-16')),
|
||||||
@ -399,9 +412,11 @@ describe('Portfolio', () => {
|
|||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 3562.089535970158,
|
unitPrice: 3562.089535970158,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.USD,
|
currency: Currency.USD,
|
||||||
fee: 2.99,
|
fee: 2.99,
|
||||||
@ -413,7 +428,7 @@ describe('Portfolio', () => {
|
|||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 991.49,
|
unitPrice: 991.49,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -473,6 +488,8 @@ describe('Portfolio', () => {
|
|||||||
it('should work with buy and sell', async () => {
|
it('should work with buy and sell', async () => {
|
||||||
await portfolio.setOrders([
|
await portfolio.setOrders([
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.USD,
|
currency: Currency.USD,
|
||||||
fee: 1.0,
|
fee: 1.0,
|
||||||
@ -484,9 +501,11 @@ describe('Portfolio', () => {
|
|||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 991.49,
|
unitPrice: 991.49,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.USD,
|
currency: Currency.USD,
|
||||||
fee: 1.0,
|
fee: 1.0,
|
||||||
@ -498,9 +517,11 @@ describe('Portfolio', () => {
|
|||||||
type: Type.SELL,
|
type: Type.SELL,
|
||||||
unitPrice: 1050,
|
unitPrice: 1050,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
accountId: DEFAULT_ACCOUNT_ID,
|
||||||
|
accountUserId: USER_ID,
|
||||||
createdAt: null,
|
createdAt: null,
|
||||||
currency: Currency.USD,
|
currency: Currency.USD,
|
||||||
fee: 1.0,
|
fee: 1.0,
|
||||||
@ -512,7 +533,7 @@ describe('Portfolio', () => {
|
|||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 1050,
|
unitPrice: 1050,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
userId: null
|
userId: USER_ID
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@
|
|||||||
>Account</a
|
>Account</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
*ngIf="hasPermissionForAdminControl"
|
*ngIf="hasPermissionToAccessAdminControl"
|
||||||
class="d-block d-sm-none"
|
class="d-block d-sm-none"
|
||||||
[routerLink]="['/admin']"
|
[routerLink]="['/admin']"
|
||||||
i18n
|
i18n
|
||||||
|
@ -34,16 +34,16 @@
|
|||||||
<div *ngIf="showDetails" class="row">
|
<div *ngIf="showDetails" class="row">
|
||||||
<div class="d-flex col justify-content-end">
|
<div class="d-flex col justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
colorizeSign="true"
|
[colorizeSign]="true"
|
||||||
isCurrency="true"
|
[isCurrency]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : performance?.currentNetPerformance"
|
[value]="isLoading ? undefined : performance?.currentNetPerformance"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<gf-value
|
<gf-value
|
||||||
colorizeSign="true"
|
[colorizeSign]="true"
|
||||||
isPercent="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="
|
[value]="
|
||||||
isLoading ? undefined : performance?.currentNetPerformancePercent
|
isLoading ? undefined : performance?.currentNetPerformancePercent
|
||||||
|
@ -16,17 +16,17 @@
|
|||||||
<div class="d-flex flex-column flex-wrap justify-content-end">
|
<div class="d-flex flex-column flex-wrap justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
class="justify-content-end mb-2"
|
class="justify-content-end mb-2"
|
||||||
colorizeSign="true"
|
|
||||||
position="end"
|
position="end"
|
||||||
|
[colorizeSign]="true"
|
||||||
[currency]="baseCurrency"
|
[currency]="baseCurrency"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : performance?.currentGrossPerformance"
|
[value]="isLoading ? undefined : performance?.currentGrossPerformance"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
<gf-value
|
<gf-value
|
||||||
class="justify-content-end"
|
class="justify-content-end"
|
||||||
colorizeSign="true"
|
|
||||||
isPercent="true"
|
|
||||||
position="end"
|
position="end"
|
||||||
|
[colorizeSign]="true"
|
||||||
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="
|
[value]="
|
||||||
isLoading ? undefined : performance?.currentGrossPerformancePercent
|
isLoading ? undefined : performance?.currentGrossPerformancePercent
|
||||||
@ -39,17 +39,17 @@
|
|||||||
<div class="d-flex flex-column flex-wrap justify-content-end">
|
<div class="d-flex flex-column flex-wrap justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
class="justify-content-end mb-2"
|
class="justify-content-end mb-2"
|
||||||
colorizeSign="true"
|
|
||||||
position="end"
|
position="end"
|
||||||
|
[colorizeSign]="true"
|
||||||
[currency]="baseCurrency"
|
[currency]="baseCurrency"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : performance?.currentNetPerformance"
|
[value]="isLoading ? undefined : performance?.currentNetPerformance"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
<gf-value
|
<gf-value
|
||||||
class="justify-content-end"
|
class="justify-content-end"
|
||||||
colorizeSign="true"
|
|
||||||
isPercent="true"
|
|
||||||
position="end"
|
position="end"
|
||||||
|
[colorizeSign]="true"
|
||||||
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="
|
[value]="
|
||||||
isLoading ? undefined : performance?.currentNetPerformancePercent
|
isLoading ? undefined : performance?.currentNetPerformancePercent
|
||||||
|
@ -21,10 +21,10 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6 mb-3">
|
<div class="col-6 mb-3">
|
||||||
<gf-value
|
<gf-value
|
||||||
colorizeSign="true"
|
|
||||||
isPercent="true"
|
|
||||||
label="Performance"
|
label="Performance"
|
||||||
size="medium"
|
size="medium"
|
||||||
|
[colorizeSign]="true"
|
||||||
|
[isPercent]="true"
|
||||||
[locale]="data.locale"
|
[locale]="data.locale"
|
||||||
[value]="grossPerformancePercent"
|
[value]="grossPerformancePercent"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
@ -76,9 +76,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-6 mb-3">
|
<div class="col-6 mb-3">
|
||||||
<gf-value
|
<gf-value
|
||||||
isCurrency="true"
|
|
||||||
label="Quantity"
|
label="Quantity"
|
||||||
size="medium"
|
size="medium"
|
||||||
|
[isCurrency]="true"
|
||||||
[value]="quantity"
|
[value]="quantity"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,14 +42,14 @@
|
|||||||
<div class="d-flex mt-1">
|
<div class="d-flex mt-1">
|
||||||
<gf-value
|
<gf-value
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
colorizeSign="true"
|
[colorizeSign]="true"
|
||||||
[currency]="position?.currency"
|
[currency]="position?.currency"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="position?.grossPerformance"
|
[value]="position?.grossPerformance"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
<gf-value
|
<gf-value
|
||||||
colorizeSign="true"
|
[colorizeSign]="true"
|
||||||
isPercent="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="position?.grossPerformancePercent"
|
[value]="position?.grossPerformancePercent"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
<td class="d-none d-lg-table-cell" mat-cell *matCellDef="let element">
|
<td class="d-none d-lg-table-cell" mat-cell *matCellDef="let element">
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
colorizeSign="true"
|
[colorizeSign]="true"
|
||||||
isPercent="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : element.grossPerformancePercent"
|
[value]="isLoading ? undefined : element.grossPerformancePercent"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
isPercent="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : element.shareInvestment"
|
[value]="isLoading ? undefined : element.shareInvestment"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
@ -71,7 +71,7 @@
|
|||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
isPercent="true"
|
[isPercent]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : element.shareCurrent"
|
[value]="isLoading ? undefined : element.shareCurrent"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
|
@ -116,7 +116,7 @@
|
|||||||
<td *matCellDef="let element" class="d-none d-lg-table-cell" mat-cell>
|
<td *matCellDef="let element" class="d-none d-lg-table-cell" mat-cell>
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
isCurrency="true"
|
[isCurrency]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : element.quantity"
|
[value]="isLoading ? undefined : element.quantity"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
@ -137,7 +137,7 @@
|
|||||||
<td *matCellDef="let element" class="d-none d-lg-table-cell" mat-cell>
|
<td *matCellDef="let element" class="d-none d-lg-table-cell" mat-cell>
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
isCurrency="true"
|
[isCurrency]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : element.unitPrice"
|
[value]="isLoading ? undefined : element.unitPrice"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
@ -158,7 +158,7 @@
|
|||||||
<td class="d-none d-lg-table-cell" mat-cell *matCellDef="let element">
|
<td class="d-none d-lg-table-cell" mat-cell *matCellDef="let element">
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<gf-value
|
<gf-value
|
||||||
isCurrency="true"
|
[isCurrency]="true"
|
||||||
[locale]="locale"
|
[locale]="locale"
|
||||||
[value]="isLoading ? undefined : element.fee"
|
[value]="isLoading ? undefined : element.fee"
|
||||||
></gf-value>
|
></gf-value>
|
||||||
|
@ -42,6 +42,8 @@ export class AboutPageComponent implements OnInit {
|
|||||||
info.globalPermissions,
|
info.globalPermissions,
|
||||||
permissions.enableSubscription
|
permissions.enableSubscription
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.cd.markForCheck();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.isLoggedIn = !!this.tokenStorageService.getToken();
|
this.isLoggedIn = !!this.tokenStorageService.getToken();
|
||||||
|
@ -70,42 +70,36 @@
|
|||||||
<div class="col">
|
<div class="col">
|
||||||
<h3 class="mb-3 text-center" i18n>Users</h3>
|
<h3 class="mb-3 text-center" i18n>Users</h3>
|
||||||
<mat-card class="px-0">
|
<mat-card class="px-0">
|
||||||
<mat-card-content>
|
<mat-card-content class="users">
|
||||||
<table class="users w-100">
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="mat-header-row">
|
<tr class="mat-header-row">
|
||||||
<th class="mat-header-cell pl-2 py-2 text-truncate" i18n>
|
<th class="mat-header-cell pl-2 py-2" i18n>User</th>
|
||||||
User
|
<th class="mat-header-cell pr-2 py-2" i18n>
|
||||||
</th>
|
|
||||||
<th class="mat-header-cell pr-2 py-2 text-truncate" i18n>
|
|
||||||
Registration Date
|
Registration Date
|
||||||
</th>
|
</th>
|
||||||
<th class="mat-header-cell pr-2 py-2 text-truncate" i18n>
|
<th class="mat-header-cell pr-2 py-2" i18n>Accounts</th>
|
||||||
Transactions
|
<th class="mat-header-cell pr-2 py-2" i18n>Transactions</th>
|
||||||
</th>
|
<th class="mat-header-cell pr-2 py-2" i18n>Engagement</th>
|
||||||
<th class="mat-header-cell pr-2 py-2 text-truncate" i18n>
|
<th class="mat-header-cell pr-2 py-2" i18n>Last Activitiy</th>
|
||||||
Engagement
|
|
||||||
</th>
|
|
||||||
<th class="mat-header-cell pr-2 py-2 text-truncate" i18n>
|
|
||||||
Last Activitiy
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let userItem of users" class="mat-row">
|
<tr *ngFor="let userItem of users" class="mat-row">
|
||||||
<td class="mat-cell pl-2 py-2 text-truncate">
|
<td class="mat-cell pl-2 py-2">
|
||||||
{{ userItem.alias || userItem.id }}
|
{{ userItem.alias || userItem.id }}
|
||||||
</td>
|
</td>
|
||||||
<td class="mat-cell pr-2 py-2 text-truncate">
|
<td class="mat-cell pr-2 py-2">
|
||||||
{{ userItem.createdAt | date: defaultDateFormat }}
|
{{ userItem.createdAt | date: defaultDateFormat }}
|
||||||
</td>
|
</td>
|
||||||
<td class="mat-cell pr-2 py-2 text-truncate">
|
<td class="mat-cell pr-2 py-2">
|
||||||
{{ userItem._count?.Order }}
|
{{ userItem._count?.Account }}
|
||||||
</td>
|
</td>
|
||||||
<td class="mat-cell pr-2 py-2 text-truncate">
|
<td class="mat-cell pr-2 py-2">{{ userItem._count?.Order }}</td>
|
||||||
|
<td class="mat-cell pr-2 py-2">
|
||||||
{{ userItem.Analytics?.activityCount }}
|
{{ userItem.Analytics?.activityCount }}
|
||||||
</td>
|
</td>
|
||||||
<td class="mat-cell pr-2 py-2 text-truncate">
|
<td class="mat-cell pr-2 py-2">
|
||||||
{{ formatDistanceToNow(userItem.Analytics?.updatedAt) }}
|
{{ formatDistanceToNow(userItem.Analytics?.updatedAt) }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -2,16 +2,23 @@
|
|||||||
color: rgb(var(--dark-primary-text));
|
color: rgb(var(--dark-primary-text));
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
table {
|
.mat-card-content {
|
||||||
&.users {
|
&.users {
|
||||||
table-layout: fixed;
|
overflow-x: auto;
|
||||||
|
|
||||||
tr {
|
table {
|
||||||
&:nth-child(even) {
|
tr {
|
||||||
background-color: rgba(
|
&:nth-child(even) {
|
||||||
var(--dark-primary-text),
|
background-color: rgba(
|
||||||
var(--palette-background-hover-alpha)
|
var(--dark-primary-text),
|
||||||
);
|
var(--palette-background-hover-alpha)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-row,
|
||||||
|
.mat-header-row {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import { FormControl, Validators } from '@angular/forms';
|
|||||||
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
|
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
|
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
|
||||||
import { Currency, Order as OrderModel } from '@prisma/client';
|
import { Currency } from '@prisma/client';
|
||||||
import { Observable, Subject } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
debounceTime,
|
debounceTime,
|
||||||
@ -19,6 +19,7 @@ import {
|
|||||||
} from 'rxjs/operators';
|
} from 'rxjs/operators';
|
||||||
|
|
||||||
import { DataService } from '../../../services/data.service';
|
import { DataService } from '../../../services/data.service';
|
||||||
|
import { CreateOrUpdateTransactionDialogParams } from './interfaces/interfaces';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'h-100' },
|
host: { class: 'h-100' },
|
||||||
@ -33,7 +34,7 @@ export class CreateOrUpdateTransactionDialog {
|
|||||||
public isLoading = false;
|
public isLoading = false;
|
||||||
public platforms: { id: string; name: string }[];
|
public platforms: { id: string; name: string }[];
|
||||||
public searchSymbolCtrl = new FormControl(
|
public searchSymbolCtrl = new FormControl(
|
||||||
this.data.symbol,
|
this.data.transaction.symbol,
|
||||||
Validators.required
|
Validators.required
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ export class CreateOrUpdateTransactionDialog {
|
|||||||
private cd: ChangeDetectorRef,
|
private cd: ChangeDetectorRef,
|
||||||
private dataService: DataService,
|
private dataService: DataService,
|
||||||
public dialogRef: MatDialogRef<CreateOrUpdateTransactionDialog>,
|
public dialogRef: MatDialogRef<CreateOrUpdateTransactionDialog>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: OrderModel
|
@Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateTransactionDialogParams
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -72,14 +73,14 @@ export class CreateOrUpdateTransactionDialog {
|
|||||||
|
|
||||||
public onUpdateSymbol(event: MatAutocompleteSelectedEvent) {
|
public onUpdateSymbol(event: MatAutocompleteSelectedEvent) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.data.symbol = event.option.value;
|
this.data.transaction.symbol = event.option.value;
|
||||||
|
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchSymbolItem(this.data.symbol)
|
.fetchSymbolItem(this.data.transaction.symbol)
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe(({ currency, marketPrice }) => {
|
.subscribe(({ currency, marketPrice }) => {
|
||||||
this.data.currency = currency;
|
this.data.transaction.currency = currency;
|
||||||
this.data.unitPrice = marketPrice;
|
this.data.transaction.unitPrice = marketPrice;
|
||||||
|
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
|
||||||
@ -88,10 +89,10 @@ export class CreateOrUpdateTransactionDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onUpdateSymbolByTyping(value: string) {
|
public onUpdateSymbolByTyping(value: string) {
|
||||||
this.data.currency = null;
|
this.data.transaction.currency = null;
|
||||||
this.data.unitPrice = null;
|
this.data.transaction.unitPrice = null;
|
||||||
|
|
||||||
this.data.symbol = value;
|
this.data.transaction.symbol = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy() {
|
public ngOnDestroy() {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<form #addTransactionForm="ngForm" class="d-flex flex-column h-100">
|
<form #addTransactionForm="ngForm" class="d-flex flex-column h-100">
|
||||||
<h1 *ngIf="data.id" mat-dialog-title i18n>Update transaction</h1>
|
<h1 *ngIf="data.transaction.id" mat-dialog-title i18n>Update transaction</h1>
|
||||||
<h1 *ngIf="!data.id" mat-dialog-title i18n>Add transaction</h1>
|
<h1 *ngIf="!data.transaction.id" mat-dialog-title i18n>Add transaction</h1>
|
||||||
<div class="flex-grow-1" mat-dialog-content>
|
<div class="flex-grow-1" mat-dialog-content>
|
||||||
<div>
|
<div>
|
||||||
<mat-form-field appearance="outline" class="w-100">
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<mat-form-field appearance="outline" class="w-100">
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
<mat-label i18n>Type</mat-label>
|
<mat-label i18n>Type</mat-label>
|
||||||
<mat-select name="type" required [(value)]="data.type">
|
<mat-select name="type" required [(value)]="data.transaction.type">
|
||||||
<mat-option value="BUY" i18n> BUY </mat-option>
|
<mat-option value="BUY" i18n> BUY </mat-option>
|
||||||
<mat-option value="SELL" i18n> SELL </mat-option>
|
<mat-option value="SELL" i18n> SELL </mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
disabled
|
disabled
|
||||||
name="currency"
|
name="currency"
|
||||||
required
|
required
|
||||||
[(value)]="data.currency"
|
[(value)]="data.transaction.currency"
|
||||||
>
|
>
|
||||||
<mat-option *ngFor="let currency of currencies" [value]="currency"
|
<mat-option *ngFor="let currency of currencies" [value]="currency"
|
||||||
>{{ currency }}</mat-option
|
>{{ currency }}</mat-option
|
||||||
@ -67,7 +67,7 @@
|
|||||||
name="date"
|
name="date"
|
||||||
required
|
required
|
||||||
[matDatepicker]="date"
|
[matDatepicker]="date"
|
||||||
[(ngModel)]="data.date"
|
[(ngModel)]="data.transaction.date"
|
||||||
/>
|
/>
|
||||||
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
|
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
|
||||||
<mat-datepicker #date disabled="false"></mat-datepicker>
|
<mat-datepicker #date disabled="false"></mat-datepicker>
|
||||||
@ -81,7 +81,7 @@
|
|||||||
name="fee"
|
name="fee"
|
||||||
required
|
required
|
||||||
type="number"
|
type="number"
|
||||||
[(ngModel)]="data.fee"
|
[(ngModel)]="data.transaction.fee"
|
||||||
/>
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
@ -93,7 +93,7 @@
|
|||||||
name="quantity"
|
name="quantity"
|
||||||
required
|
required
|
||||||
type="number"
|
type="number"
|
||||||
[(ngModel)]="data.quantity"
|
[(ngModel)]="data.transaction.quantity"
|
||||||
/>
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
@ -105,14 +105,28 @@
|
|||||||
name="unitPrice"
|
name="unitPrice"
|
||||||
required
|
required
|
||||||
type="number"
|
type="number"
|
||||||
[(ngModel)]="data.unitPrice"
|
[(ngModel)]="data.transaction.unitPrice"
|
||||||
/>
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-none">
|
||||||
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
|
<mat-label i18n>Account</mat-label>
|
||||||
|
<mat-select
|
||||||
|
name="accountId"
|
||||||
|
required
|
||||||
|
[(value)]="data.transaction.accountId"
|
||||||
|
>
|
||||||
|
<mat-option *ngFor="let account of data.accounts" [value]="account.id"
|
||||||
|
>{{ account.name }}</mat-option
|
||||||
|
>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<mat-form-field appearance="outline" class="w-100">
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
<mat-label i18n>Platform</mat-label>
|
<mat-label i18n>Platform</mat-label>
|
||||||
<mat-select name="platformId" [(value)]="data.platformId">
|
<mat-select name="platformId" [(value)]="data.transaction.platformId">
|
||||||
<mat-option [value]="null"></mat-option>
|
<mat-option [value]="null"></mat-option>
|
||||||
<mat-option *ngFor="let platform of platforms" [value]="platform.id"
|
<mat-option *ngFor="let platform of platforms" [value]="platform.id"
|
||||||
>{{ platform.name }}</mat-option
|
>{{ platform.name }}</mat-option
|
||||||
@ -127,7 +141,7 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
i18n
|
i18n
|
||||||
mat-flat-button
|
mat-flat-button
|
||||||
[disabled]="!(addTransactionForm.form.valid && data.symbol)"
|
[disabled]="!(addTransactionForm.form.valid && data.transaction.symbol)"
|
||||||
[mat-dialog-close]="data"
|
[mat-dialog-close]="data"
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { Order } from '../../interfaces/order.interface';
|
||||||
|
import { Account } from '@prisma/client';
|
||||||
|
|
||||||
|
export interface CreateOrUpdateTransactionDialogParams {
|
||||||
|
accountId: string;
|
||||||
|
accounts: Account[];
|
||||||
|
transaction: Order;
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
export interface Order {
|
export interface Order {
|
||||||
|
accountId: string;
|
||||||
currency: string;
|
currency: string;
|
||||||
date: Date;
|
date: Date;
|
||||||
fee: number;
|
fee: number;
|
||||||
|
id: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
platformId: string;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
type: string;
|
type: string;
|
||||||
unitPrice: number;
|
unitPrice: number;
|
||||||
|
@ -122,36 +122,8 @@ export class TransactionsPageComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private openCreateTransactionDialog(): void {
|
|
||||||
const dialogRef = this.dialog.open(CreateOrUpdateTransactionDialog, {
|
|
||||||
data: {
|
|
||||||
currency: null,
|
|
||||||
date: new Date(),
|
|
||||||
fee: 0,
|
|
||||||
platformId: null,
|
|
||||||
quantity: null,
|
|
||||||
symbol: null,
|
|
||||||
type: 'BUY',
|
|
||||||
unitPrice: null
|
|
||||||
},
|
|
||||||
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh',
|
|
||||||
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
|
|
||||||
});
|
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((order: UpdateOrderDto) => {
|
|
||||||
if (order) {
|
|
||||||
this.dataService.postOrder(order).subscribe({
|
|
||||||
next: () => {
|
|
||||||
this.fetchOrders();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.router.navigate(['.'], { relativeTo: this.route });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public openUpdateTransactionDialog({
|
public openUpdateTransactionDialog({
|
||||||
|
accountId,
|
||||||
currency,
|
currency,
|
||||||
date,
|
date,
|
||||||
fee,
|
fee,
|
||||||
@ -164,23 +136,29 @@ export class TransactionsPageComponent implements OnInit {
|
|||||||
}: OrderModel): void {
|
}: OrderModel): void {
|
||||||
const dialogRef = this.dialog.open(CreateOrUpdateTransactionDialog, {
|
const dialogRef = this.dialog.open(CreateOrUpdateTransactionDialog, {
|
||||||
data: {
|
data: {
|
||||||
currency,
|
accounts: this.user.accounts,
|
||||||
date,
|
transaction: {
|
||||||
fee,
|
accountId,
|
||||||
id,
|
currency,
|
||||||
platformId,
|
date,
|
||||||
quantity,
|
fee,
|
||||||
symbol,
|
id,
|
||||||
type,
|
platformId,
|
||||||
unitPrice
|
quantity,
|
||||||
|
symbol,
|
||||||
|
type,
|
||||||
|
unitPrice
|
||||||
|
}
|
||||||
},
|
},
|
||||||
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh',
|
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh',
|
||||||
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
|
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((order: UpdateOrderDto) => {
|
dialogRef.afterClosed().subscribe((data: any) => {
|
||||||
if (order) {
|
const transaction: UpdateOrderDto = data?.transaction;
|
||||||
this.dataService.putOrder(order).subscribe({
|
|
||||||
|
if (transaction) {
|
||||||
|
this.dataService.putOrder(transaction).subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
this.fetchOrders();
|
this.fetchOrders();
|
||||||
}
|
}
|
||||||
@ -195,4 +173,41 @@ export class TransactionsPageComponent implements OnInit {
|
|||||||
this.unsubscribeSubject.next();
|
this.unsubscribeSubject.next();
|
||||||
this.unsubscribeSubject.complete();
|
this.unsubscribeSubject.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private openCreateTransactionDialog(): void {
|
||||||
|
const dialogRef = this.dialog.open(CreateOrUpdateTransactionDialog, {
|
||||||
|
data: {
|
||||||
|
accounts: this.user.accounts,
|
||||||
|
transaction: {
|
||||||
|
accountId: this.user.accounts.find((account) => {
|
||||||
|
return account.isDefault;
|
||||||
|
})?.id,
|
||||||
|
currency: null,
|
||||||
|
date: new Date(),
|
||||||
|
fee: 0,
|
||||||
|
platformId: null,
|
||||||
|
quantity: null,
|
||||||
|
symbol: null,
|
||||||
|
type: 'BUY',
|
||||||
|
unitPrice: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh',
|
||||||
|
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe((data: any) => {
|
||||||
|
const transaction: UpdateOrderDto = data?.transaction;
|
||||||
|
|
||||||
|
if (transaction) {
|
||||||
|
this.dataService.postOrder(transaction).subscribe({
|
||||||
|
next: () => {
|
||||||
|
this.fetchOrders();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.router.navigate(['.'], { relativeTo: this.route });
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,5 +12,9 @@
|
|||||||
{
|
{
|
||||||
"path": "./tsconfig.editor.json"
|
"path": "./tsconfig.editor.json"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictTemplates": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ghostfolio",
|
"name": "ghostfolio",
|
||||||
"version": "0.91.0",
|
"version": "0.92.0",
|
||||||
"homepage": "https://ghostfol.io",
|
"homepage": "https://ghostfol.io",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -82,6 +82,16 @@ async function main() {
|
|||||||
create: {
|
create: {
|
||||||
accessToken:
|
accessToken:
|
||||||
'c689bcc894e4a420cb609ee34271f3e07f200594f7d199c50d75add7102889eb60061a04cd2792ebc853c54e37308271271e7bf588657c9e0c37faacbc28c3c6',
|
'c689bcc894e4a420cb609ee34271f3e07f200594f7d199c50d75add7102889eb60061a04cd2792ebc853c54e37308271271e7bf588657c9e0c37faacbc28c3c6',
|
||||||
|
Account: {
|
||||||
|
create: [
|
||||||
|
{
|
||||||
|
accountType: AccountType.SECURITIES,
|
||||||
|
id: 'f4425b66-9ba9-4ac4-93d7-fdf9a145e8cb',
|
||||||
|
isDefault: true,
|
||||||
|
name: 'Default Account'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
alias: 'Admin',
|
alias: 'Admin',
|
||||||
id: '4e1af723-95f6-44f8-92a7-464df17f6ec3',
|
id: '4e1af723-95f6-44f8-92a7-464df17f6ec3',
|
||||||
role: Role.ADMIN
|
role: Role.ADMIN
|
||||||
|
Reference in New Issue
Block a user