Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
7f3f75386d | |||
678544748a | |||
632f3e3872 | |||
87301ddbd5 |
28
CHANGELOG.md
28
CHANGELOG.md
@ -5,6 +5,20 @@ 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).
|
||||||
|
|
||||||
|
## 1.69.0 - 07.11.2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added the symbol mapping attribute to the symbol profile model
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Improved the registration page
|
||||||
|
|
||||||
|
### Todo
|
||||||
|
|
||||||
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.68.0 - 01.11.2021
|
## 1.68.0 - 01.11.2021
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@ -60,7 +74,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Todo
|
### Todo
|
||||||
|
|
||||||
- Apply data migration (`yarn prisma migrate deploy`)
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.62.0 - 17.10.2021
|
## 1.62.0 - 17.10.2021
|
||||||
|
|
||||||
@ -158,7 +172,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Todo
|
### Todo
|
||||||
|
|
||||||
- Apply data migration (`yarn prisma migrate deploy`)
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.55.0 - 20.09.2021
|
## 1.55.0 - 20.09.2021
|
||||||
|
|
||||||
@ -173,7 +187,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Todo
|
### Todo
|
||||||
|
|
||||||
- Apply data migration (`yarn prisma migrate deploy`)
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.54.0 - 18.09.2021
|
## 1.54.0 - 18.09.2021
|
||||||
|
|
||||||
@ -194,7 +208,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Todo
|
### Todo
|
||||||
|
|
||||||
- Apply data migration (`yarn prisma migrate deploy`)
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.53.0 - 13.09.2021
|
## 1.53.0 - 13.09.2021
|
||||||
|
|
||||||
@ -316,7 +330,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Todo
|
### Todo
|
||||||
|
|
||||||
- Apply data migration (`yarn prisma migrate deploy`)
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.41.0 - 21.08.2021
|
## 1.41.0 - 21.08.2021
|
||||||
|
|
||||||
@ -369,7 +383,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Todo
|
### Todo
|
||||||
|
|
||||||
- Apply data migration (`yarn prisma migrate deploy`)
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.38.0 - 14.08.2021
|
## 1.38.0 - 14.08.2021
|
||||||
|
|
||||||
@ -429,7 +443,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Todo
|
### Todo
|
||||||
|
|
||||||
- Apply data migration (`yarn prisma migrate deploy`)
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.34.0 - 07.08.2021
|
## 1.34.0 - 07.08.2021
|
||||||
|
|
||||||
|
12
README.md
12
README.md
@ -101,7 +101,7 @@ docker-compose -f docker/docker-compose-build-local.yml up
|
|||||||
Run the following command to setup the database once Ghostfolio is running:
|
Run the following command to setup the database once Ghostfolio is running:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose -f docker/docker-compose-build-local.yml exec ghostfolio yarn setup:database
|
docker-compose -f docker/docker-compose-build-local.yml exec ghostfolio yarn database:setup
|
||||||
```
|
```
|
||||||
|
|
||||||
### Fetch Historical Data
|
### Fetch Historical Data
|
||||||
@ -112,6 +112,14 @@ Open http://localhost:3333 in your browser and accomplish these steps:
|
|||||||
1. Go to the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data
|
1. Go to the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data
|
||||||
1. Click _Sign out_ and check out the _Live Demo_
|
1. Click _Sign out_ and check out the _Live Demo_
|
||||||
|
|
||||||
|
### Migrate Database
|
||||||
|
|
||||||
|
With the following command you can keep your database schema in sync after a Ghostfolio version update:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker/docker-compose-build-local.yml exec ghostfolio yarn database:migrate
|
||||||
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
@ -126,7 +134,7 @@ Open http://localhost:3333 in your browser and accomplish these steps:
|
|||||||
1. Run `cd docker`
|
1. Run `cd docker`
|
||||||
1. Run `docker compose up -d` to start [PostgreSQL](https://www.postgresql.org) and [Redis](https://redis.io)
|
1. Run `docker compose up -d` to start [PostgreSQL](https://www.postgresql.org) and [Redis](https://redis.io)
|
||||||
1. Run `cd -` to go back to the project root directory
|
1. Run `cd -` to go back to the project root directory
|
||||||
1. Run `yarn setup:database` to initialize the database schema and populate your database with (example) data
|
1. Run `yarn database:setup` to initialize the database schema and populate your database with (example) data
|
||||||
1. Start server and client (see [_Development_](#Development))
|
1. Start server and client (see [_Development_](#Development))
|
||||||
1. Login as _Admin_ with the following _Security Token_: `ae76872ae8f3419c6d6f64bf51888ecbcc703927a342d815fafe486acdb938da07d0cf44fca211a0be74a423238f535362d390a41e81e633a9ce668a6e31cdf9`
|
1. Login as _Admin_ with the following _Security Token_: `ae76872ae8f3419c6d6f64bf51888ecbcc703927a342d815fafe486acdb938da07d0cf44fca211a0be74a423238f535362d390a41e81e633a9ce668a6e31cdf9`
|
||||||
1. Go to the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data
|
1. Go to the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data
|
||||||
|
4
apps/api/src/app/cache/cache.module.ts
vendored
4
apps/api/src/app/cache/cache.module.ts
vendored
@ -6,6 +6,7 @@ import { DataGatheringService } from '@ghostfolio/api/services/data-gathering.se
|
|||||||
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
||||||
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
|
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
|
||||||
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
||||||
|
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile.module';
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { CacheController } from './cache.controller';
|
import { CacheController } from './cache.controller';
|
||||||
@ -15,7 +16,8 @@ import { CacheController } from './cache.controller';
|
|||||||
DataGatheringModule,
|
DataGatheringModule,
|
||||||
DataProviderModule,
|
DataProviderModule,
|
||||||
ExchangeRateDataModule,
|
ExchangeRateDataModule,
|
||||||
RedisCacheModule
|
RedisCacheModule,
|
||||||
|
SymbolProfileModule
|
||||||
],
|
],
|
||||||
controllers: [CacheController],
|
controllers: [CacheController],
|
||||||
providers: [
|
providers: [
|
||||||
|
@ -4,6 +4,7 @@ import { DataGatheringService } from '@ghostfolio/api/services/data-gathering.se
|
|||||||
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
||||||
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
|
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
|
||||||
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
||||||
|
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile.module';
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
|
|
||||||
@ -18,7 +19,8 @@ import { InfoService } from './info.service';
|
|||||||
JwtModule.register({
|
JwtModule.register({
|
||||||
secret: process.env.JWT_SECRET_KEY,
|
secret: process.env.JWT_SECRET_KEY,
|
||||||
signOptions: { expiresIn: '30 days' }
|
signOptions: { expiresIn: '30 days' }
|
||||||
})
|
}),
|
||||||
|
SymbolProfileModule
|
||||||
],
|
],
|
||||||
controllers: [InfoController],
|
controllers: [InfoController],
|
||||||
providers: [
|
providers: [
|
||||||
|
@ -8,7 +8,7 @@ import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-
|
|||||||
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
|
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
|
||||||
import { ImpersonationModule } from '@ghostfolio/api/services/impersonation.module';
|
import { ImpersonationModule } from '@ghostfolio/api/services/impersonation.module';
|
||||||
import { PrismaModule } from '@ghostfolio/api/services/prisma.module';
|
import { PrismaModule } from '@ghostfolio/api/services/prisma.module';
|
||||||
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service';
|
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile.module';
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { CurrentRateService } from './current-rate.service';
|
import { CurrentRateService } from './current-rate.service';
|
||||||
@ -27,6 +27,7 @@ import { RulesService } from './rules.service';
|
|||||||
ImpersonationModule,
|
ImpersonationModule,
|
||||||
OrderModule,
|
OrderModule,
|
||||||
PrismaModule,
|
PrismaModule,
|
||||||
|
SymbolProfileModule,
|
||||||
UserModule
|
UserModule
|
||||||
],
|
],
|
||||||
controllers: [PortfolioController],
|
controllers: [PortfolioController],
|
||||||
@ -35,8 +36,7 @@ import { RulesService } from './rules.service';
|
|||||||
CurrentRateService,
|
CurrentRateService,
|
||||||
MarketDataService,
|
MarketDataService,
|
||||||
PortfolioService,
|
PortfolioService,
|
||||||
RulesService,
|
RulesService
|
||||||
SymbolProfileService
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class PortfolioModule {}
|
export class PortfolioModule {}
|
||||||
|
@ -6,6 +6,7 @@ import { PrismaModule } from '@ghostfolio/api/services/prisma.module';
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { ExchangeRateDataModule } from './exchange-rate-data.module';
|
import { ExchangeRateDataModule } from './exchange-rate-data.module';
|
||||||
|
import { SymbolProfileModule } from './symbol-profile.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -13,7 +14,8 @@ import { ExchangeRateDataModule } from './exchange-rate-data.module';
|
|||||||
DataEnhancerModule,
|
DataEnhancerModule,
|
||||||
DataProviderModule,
|
DataProviderModule,
|
||||||
ExchangeRateDataModule,
|
ExchangeRateDataModule,
|
||||||
PrismaModule
|
PrismaModule,
|
||||||
|
SymbolProfileModule
|
||||||
],
|
],
|
||||||
providers: [DataGatheringService],
|
providers: [DataGatheringService],
|
||||||
exports: [DataEnhancerModule, DataGatheringService]
|
exports: [DataEnhancerModule, DataGatheringService]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service';
|
||||||
import {
|
import {
|
||||||
benchmarks,
|
benchmarks,
|
||||||
ghostfolioFearAndGreedIndexSymbol
|
ghostfolioFearAndGreedIndexSymbol
|
||||||
@ -32,7 +33,8 @@ export class DataGatheringService {
|
|||||||
private readonly dataProviderService: DataProviderService,
|
private readonly dataProviderService: DataProviderService,
|
||||||
private readonly exchangeRateDataService: ExchangeRateDataService,
|
private readonly exchangeRateDataService: ExchangeRateDataService,
|
||||||
private readonly ghostfolioScraperApi: GhostfolioScraperApiService,
|
private readonly ghostfolioScraperApi: GhostfolioScraperApiService,
|
||||||
private readonly prismaService: PrismaService
|
private readonly prismaService: PrismaService,
|
||||||
|
private readonly symbolProfileService: SymbolProfileService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async gather7Days() {
|
public async gather7Days() {
|
||||||
@ -132,13 +134,22 @@ export class DataGatheringService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const currentData = await this.dataProviderService.get(dataGatheringItems);
|
const currentData = await this.dataProviderService.get(dataGatheringItems);
|
||||||
|
const symbolProfiles = await this.symbolProfileService.getSymbolProfiles(
|
||||||
|
dataGatheringItems.map(({ symbol }) => {
|
||||||
|
return symbol;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
for (const [symbol, response] of Object.entries(currentData)) {
|
for (const [symbol, response] of Object.entries(currentData)) {
|
||||||
|
const symbolMapping = symbolProfiles.find((symbolProfile) => {
|
||||||
|
return symbolProfile.symbol === symbol;
|
||||||
|
})?.symbolMapping;
|
||||||
|
|
||||||
for (const dataEnhancer of this.dataEnhancers) {
|
for (const dataEnhancer of this.dataEnhancers) {
|
||||||
try {
|
try {
|
||||||
currentData[symbol] = await dataEnhancer.enhance({
|
currentData[symbol] = await dataEnhancer.enhance({
|
||||||
response,
|
response,
|
||||||
symbol
|
symbol: symbolMapping[dataEnhancer.getName()] ?? symbol
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to enhance data for symbol ${symbol}`, error);
|
console.error(`Failed to enhance data for symbol ${symbol}`, error);
|
||||||
|
@ -70,4 +70,8 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface {
|
|||||||
|
|
||||||
return Promise.resolve(response);
|
return Promise.resolve(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getName() {
|
||||||
|
return 'TRACKINSIGHT';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,4 +8,6 @@ export interface DataEnhancerInterface {
|
|||||||
response: IDataProviderResponse;
|
response: IDataProviderResponse;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
}): Promise<IDataProviderResponse>;
|
}): Promise<IDataProviderResponse>;
|
||||||
|
|
||||||
|
getName(): string;
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,14 @@ import { AssetClass, AssetSubClass, DataSource } from '@prisma/client';
|
|||||||
export interface EnhancedSymbolProfile {
|
export interface EnhancedSymbolProfile {
|
||||||
assetClass: AssetClass;
|
assetClass: AssetClass;
|
||||||
assetSubClass: AssetSubClass;
|
assetSubClass: AssetSubClass;
|
||||||
|
countries: Country[];
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
currency: string | null;
|
currency: string | null;
|
||||||
dataSource: DataSource;
|
dataSource: DataSource;
|
||||||
id: string;
|
id: string;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
updatedAt: Date;
|
|
||||||
symbol: string;
|
|
||||||
countries: Country[];
|
|
||||||
sectors: Sector[];
|
sectors: Sector[];
|
||||||
|
symbol: string;
|
||||||
|
symbolMapping?: { [key: string]: string };
|
||||||
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
11
apps/api/src/services/symbol-profile.module.ts
Normal file
11
apps/api/src/services/symbol-profile.module.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { PrismaModule } from '@ghostfolio/api/services/prisma.module';
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { SymbolProfileService } from './symbol-profile.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [PrismaModule],
|
||||||
|
providers: [SymbolProfileService],
|
||||||
|
exports: [SymbolProfileService]
|
||||||
|
})
|
||||||
|
export class SymbolProfileModule {}
|
@ -29,7 +29,8 @@ export class SymbolProfileService {
|
|||||||
return symbolProfiles.map((symbolProfile) => ({
|
return symbolProfiles.map((symbolProfile) => ({
|
||||||
...symbolProfile,
|
...symbolProfile,
|
||||||
countries: this.getCountries(symbolProfile),
|
countries: this.getCountries(symbolProfile),
|
||||||
sectors: this.getSectors(symbolProfile)
|
sectors: this.getSectors(symbolProfile),
|
||||||
|
symbolMapping: this.getSymbolMapping(symbolProfile)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,4 +62,12 @@ export class SymbolProfileService {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getSymbolMapping(symbolProfile: SymbolProfile) {
|
||||||
|
return (
|
||||||
|
(symbolProfile['symbolMapping'] as {
|
||||||
|
[key: string]: string;
|
||||||
|
}) ?? {}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,7 +229,13 @@
|
|||||||
mat-button
|
mat-button
|
||||||
[routerLink]="['/']"
|
[routerLink]="['/']"
|
||||||
>
|
>
|
||||||
<gf-logo [hideName]="!currentRoute || currentRoute === 'start'"></gf-logo>
|
<gf-logo
|
||||||
|
[hideName]="
|
||||||
|
!currentRoute ||
|
||||||
|
currentRoute === 'register' ||
|
||||||
|
currentRoute === 'start'
|
||||||
|
"
|
||||||
|
></gf-logo>
|
||||||
</a>
|
</a>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<a
|
<a
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||||
@ -6,6 +6,7 @@ import { TokenStorageService } from '@ghostfolio/client/services/token-storage.s
|
|||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ import { ShowAccessTokenDialog } from './show-access-token-dialog/show-access-to
|
|||||||
export class RegisterPageComponent implements OnDestroy, OnInit {
|
export class RegisterPageComponent implements OnDestroy, OnInit {
|
||||||
public currentYear = format(new Date(), 'yyyy');
|
public currentYear = format(new Date(), 'yyyy');
|
||||||
public demoAuthToken: string;
|
public demoAuthToken: string;
|
||||||
|
public deviceType: string;
|
||||||
public hasPermissionForSocialLogin: boolean;
|
public hasPermissionForSocialLogin: boolean;
|
||||||
public historicalDataItems: LineChartItem[];
|
public historicalDataItems: LineChartItem[];
|
||||||
|
|
||||||
@ -29,8 +31,8 @@ export class RegisterPageComponent implements OnDestroy, OnInit {
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
|
||||||
private dataService: DataService,
|
private dataService: DataService,
|
||||||
|
private deviceService: DeviceDetectorService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private tokenStorageService: TokenStorageService
|
private tokenStorageService: TokenStorageService
|
||||||
@ -45,6 +47,7 @@ export class RegisterPageComponent implements OnDestroy, OnInit {
|
|||||||
const { demoAuthToken, globalPermissions } = this.dataService.fetchInfo();
|
const { demoAuthToken, globalPermissions } = this.dataService.fetchInfo();
|
||||||
|
|
||||||
this.demoAuthToken = demoAuthToken;
|
this.demoAuthToken = demoAuthToken;
|
||||||
|
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
|
||||||
this.hasPermissionForSocialLogin = hasPermission(
|
this.hasPermissionForSocialLogin = hasPermission(
|
||||||
globalPermissions,
|
globalPermissions,
|
||||||
permissions.enableSocialLogin
|
permissions.enableSocialLogin
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
|
<div class="intro-container mb-5">
|
||||||
|
<div class="intro-inner-container mx-auto">
|
||||||
|
<div class="h-100 intro w-100"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div
|
||||||
<h3 class="d-flex justify-content-center mb-3 text-center" i18n>
|
class="align-items-center d-flex flex-column justify-content-center w-100"
|
||||||
Create your Account
|
>
|
||||||
</h3>
|
<gf-logo size="large"></gf-logo>
|
||||||
<mat-card class="mb-4">
|
<p class="lead m-0">Wealth Management Software</p>
|
||||||
<mat-card-content class="text-center">
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-container row">
|
||||||
|
<div class="align-items-center col d-flex justify-content-center">
|
||||||
|
<div class="py-5 text-center">
|
||||||
<button
|
<button
|
||||||
class="d-inline-block"
|
class="d-inline-block"
|
||||||
color="primary"
|
color="primary"
|
||||||
@ -17,14 +28,19 @@
|
|||||||
Create Account
|
Create Account
|
||||||
</button>
|
</button>
|
||||||
<ng-container *ngIf="hasPermissionForSocialLogin">
|
<ng-container *ngIf="hasPermissionForSocialLogin">
|
||||||
<div class="my-3 text-muted" i18n>or</div>
|
<div
|
||||||
|
class="m-3 text-muted"
|
||||||
|
i18n
|
||||||
|
[ngClass]="{'d-inline': deviceType !== 'mobile' }"
|
||||||
|
>
|
||||||
|
or
|
||||||
|
</div>
|
||||||
<a color="accent" href="/api/auth/google" mat-flat-button
|
<a color="accent" href="/api/auth/google" mat-flat-button
|
||||||
><ion-icon class="mr-1" name="logo-google"></ion-icon
|
><ion-icon class="mr-1" name="logo-google"></ion-icon
|
||||||
><span i18n>Continue with Google</span></a
|
><span i18n>Continue with Google</span></a
|
||||||
>
|
>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</mat-card-content>
|
</div>
|
||||||
</mat-card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
.mat-stroked-button {
|
||||||
|
background-color: var(--light-background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-container {
|
||||||
|
background-color: #ffffff;
|
||||||
|
margin-top: -5rem;
|
||||||
|
|
||||||
|
.intro-inner-container {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
max-height: 66vh;
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
background-image: url('/assets/intro.jpg');
|
||||||
|
background-position: top left;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ghostfolio",
|
"name": "ghostfolio",
|
||||||
"version": "1.68.0",
|
"version": "1.69.0",
|
||||||
"homepage": "https://ghostfol.io",
|
"homepage": "https://ghostfol.io",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -19,8 +19,10 @@
|
|||||||
"database:format-schema": "prisma format",
|
"database:format-schema": "prisma format",
|
||||||
"database:generate-typings": "prisma generate",
|
"database:generate-typings": "prisma generate",
|
||||||
"database:gui": "prisma studio",
|
"database:gui": "prisma studio",
|
||||||
|
"database:migrate": "prisma migrate deploy",
|
||||||
"database:push": "prisma db push",
|
"database:push": "prisma db push",
|
||||||
"database:seed": "prisma db seed --preview-feature",
|
"database:seed": "prisma db seed --preview-feature",
|
||||||
|
"database:setup": "yarn database:push && yarn database:seed",
|
||||||
"dep-graph": "nx dep-graph",
|
"dep-graph": "nx dep-graph",
|
||||||
"e2e": "ng e2e",
|
"e2e": "ng e2e",
|
||||||
"format": "nx format:write",
|
"format": "nx format:write",
|
||||||
@ -33,7 +35,6 @@
|
|||||||
"nx": "nx",
|
"nx": "nx",
|
||||||
"postinstall": "prisma generate && ngcc --properties es2015 browser module main",
|
"postinstall": "prisma generate && ngcc --properties es2015 browser module main",
|
||||||
"replace-placeholders-in-build": "node ./replace.build.js",
|
"replace-placeholders-in-build": "node ./replace.build.js",
|
||||||
"setup:database": "yarn database:push && yarn database:seed",
|
|
||||||
"start": "node dist/apps/api/main",
|
"start": "node dist/apps/api/main",
|
||||||
"start:client": "ng serve client --hmr -o",
|
"start:client": "ng serve client --hmr -o",
|
||||||
"start:prod": "node apps/api/main",
|
"start:prod": "node apps/api/main",
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "SymbolProfile" ADD COLUMN "symbolMapping" JSONB;
|
@ -130,6 +130,7 @@ model SymbolProfile {
|
|||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
sectors Json?
|
sectors Json?
|
||||||
symbol String
|
symbol String
|
||||||
|
symbolMapping Json?
|
||||||
|
|
||||||
@@unique([dataSource, symbol])
|
@@unique([dataSource, symbol])
|
||||||
}
|
}
|
||||||
|
2
test/import/ok.csv
Normal file
2
test/import/ok.csv
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Date,Code,Currency,Price,Quantity,Action,Fee
|
||||||
|
16/09/2021,MSFT,USD,298.580,5,buy,19.00
|
|
Reference in New Issue
Block a user