From dab91540921a8eea950057ff6a178ccfbdb52739 Mon Sep 17 00:00:00 2001 From: Kevin Viet Date: Thu, 23 Feb 2023 18:09:35 +0100 Subject: [PATCH 01/11] Add support for armv7 processors (#1738) * Add support for armv7 processors * Update changelog --- .github/workflows/docker-image.yml | 2 +- CHANGELOG.md | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 6b85f639b..26ccb9b8d 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: uses: docker/build-push-action@v3 with: context: . - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64,linux/arm/v7,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.output.labels }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 96aafcb82..569f7d128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## Unreleased + +### Added + +- Added the configuration to publish a `linux/arm/v7` docker image + ## 1.237.0 - 2023-02-19 ### Added @@ -757,7 +763,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added the alias to the `Access` database schema - Added support for translated time distances -- Added a _GitHub Action_ to create an `arm64` docker image +- Added a _GitHub Action_ to create an `linux/arm64` docker image ### Changed From 494ba36d449a6a738fb418b2ffa77183c090cb98 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 24 Feb 2023 20:44:20 +0100 Subject: [PATCH 02/11] Feature/reset letter spacing in buttons (#1742) * Reset letter spacing in buttons * Update changelog --- CHANGELOG.md | 4 ++++ apps/client/src/styles/theme.scss | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 569f7d128..239f057e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added the configuration to publish a `linux/arm/v7` docker image +### Fixed + +- Reset the letter spacing in buttons + ## 1.237.0 - 2023-02-19 ### Added diff --git a/apps/client/src/styles/theme.scss b/apps/client/src/styles/theme.scss index a6f6107c2..6a538caa2 100644 --- a/apps/client/src/styles/theme.scss +++ b/apps/client/src/styles/theme.scss @@ -69,6 +69,8 @@ $gf-secondary: ( ) ); +$gf-typography: mat.define-typography-config(); + @include mat.core(); @include mat.legacy-core(); @@ -80,7 +82,7 @@ $gf-theme-default: mat.define-light-theme( accent: mat.define-palette($gf-secondary, 500, 900, A100) ), density: 0, - typography: mat.define-typography-config() + typography: $gf-typography ) ); @include mat.all-component-themes($gf-theme-default); @@ -94,7 +96,7 @@ $gf-theme-dark: mat.define-dark-theme( accent: mat.define-palette($gf-secondary, 500, 900, A100) ), density: 0, - typography: mat.define-typography-config() + typography: $gf-typography ) ); .is-dark-theme { @@ -107,4 +109,6 @@ $gf-theme-dark: mat.define-dark-theme( --gf-theme-primary-500-rgb: 0, 187, 255; --gf-theme-secondary-500: #3686cf; --gf-theme-secondary-500-rgb: 78, 208, 94; + + --mdc-typography-button-letter-spacing: normal; } From 80d06389220e595f8bcf8caa1036f5933be26c90 Mon Sep 17 00:00:00 2001 From: Mirio Date: Sat, 25 Feb 2023 09:45:01 +0100 Subject: [PATCH 03/11] Adding Coingecko Data Provider (#1736) * Adding Coingecko Data Provider * Update changelog --------- Co-authored-by: Thomas <4159106+dtslvr@users.noreply.github.com> --- CHANGELOG.md | 1 + apps/api/src/app/order/order.service.ts | 3 - .../coingecko/coingecko.service.ts | 191 ++++++++++++++++++ .../data-provider/data-provider.module.ts | 5 + .../migration.sql | 2 + prisma/schema.prisma | 1 + 6 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 apps/api/src/services/data-provider/coingecko/coingecko.service.ts create mode 100644 prisma/migrations/20230222200407_added_coingecko_to_data_source/migration.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 239f057e3..087480e8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added `COINGECKO` as a new data source type - Added the configuration to publish a `linux/arm/v7` docker image ### Fixed diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index 077f2227b..2d0cb7376 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -110,9 +110,6 @@ export class OrderService { dataSource, symbol: id }; - } else { - data.SymbolProfile.connectOrCreate.create.symbol = - data.SymbolProfile.connectOrCreate.create.symbol.toUpperCase(); } await this.dataGatheringService.addJobToQueue( diff --git a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts new file mode 100644 index 000000000..7bd852f5d --- /dev/null +++ b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts @@ -0,0 +1,191 @@ +import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; +import { DataProviderInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface'; +import { + IDataProviderHistoricalResponse, + IDataProviderResponse +} from '@ghostfolio/api/services/interfaces/interfaces'; +import { DATE_FORMAT } from '@ghostfolio/common/helper'; +import { Granularity } from '@ghostfolio/common/types'; +import { Injectable, Logger } from '@nestjs/common'; +import { + AssetClass, + AssetSubClass, + DataSource, + SymbolProfile +} from '@prisma/client'; +import bent from 'bent'; +import { format, fromUnixTime, getUnixTime } from 'date-fns'; + +@Injectable() +export class CoinGeckoService implements DataProviderInterface { + private baseCurrency: string; + private readonly URL = 'https://api.coingecko.com/api/v3'; + + public constructor( + private readonly configurationService: ConfigurationService + ) { + this.baseCurrency = this.configurationService.get('BASE_CURRENCY'); + } + + public canHandle(symbol: string) { + return true; + } + + public async getAssetProfile( + aSymbol: string + ): Promise> { + const response: Partial = { + assetClass: AssetClass.CASH, + assetSubClass: AssetSubClass.CRYPTOCURRENCY, + currency: this.baseCurrency, + dataSource: this.getName(), + symbol: aSymbol + }; + + try { + const get = bent(`${this.URL}/coins/${aSymbol}`, 'GET', 'json', 200); + const { name } = await get(); + + response.name = name; + } catch (error) { + Logger.error(error, 'CoinGeckoService'); + } + + return response; + } + + public async getDividends({ + from, + granularity = 'day', + symbol, + to + }: { + from: Date; + granularity: Granularity; + symbol: string; + to: Date; + }) { + return {}; + } + + public async getHistorical( + aSymbol: string, + aGranularity: Granularity = 'day', + from: Date, + to: Date + ): Promise<{ + [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; + }> { + try { + const get = bent( + `${ + this.URL + }/coins/${aSymbol}/market_chart/range?vs_currency=${this.baseCurrency.toLowerCase()}&from=${getUnixTime( + from + )}&to=${getUnixTime(to)}`, + 'GET', + 'json', + 200 + ); + const { prices } = await get(); + + const result: { + [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; + } = { + [aSymbol]: {} + }; + + for (const [timestamp, marketPrice] of prices) { + result[aSymbol][format(fromUnixTime(timestamp / 1000), DATE_FORMAT)] = { + marketPrice + }; + } + + return result; + } catch (error) { + throw new Error( + `Could not get historical market data for ${aSymbol} (${this.getName()}) from ${format( + from, + DATE_FORMAT + )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}` + ); + } + } + + public getMaxNumberOfSymbolsPerRequest() { + return 50; + } + + public getName(): DataSource { + return DataSource.COINGECKO; + } + + public async getQuotes( + aSymbols: string[] + ): Promise<{ [symbol: string]: IDataProviderResponse }> { + const results: { [symbol: string]: IDataProviderResponse } = {}; + + if (aSymbols.length <= 0) { + return {}; + } + + try { + const get = bent( + `${this.URL}/simple/price?ids=${aSymbols.join( + ',' + )}&vs_currencies=${this.baseCurrency.toLowerCase()}`, + 'GET', + 'json', + 200 + ); + const response = await get(); + + for (const symbol in response) { + if (Object.prototype.hasOwnProperty.call(response, symbol)) { + results[symbol] = { + currency: this.baseCurrency, + dataSource: DataSource.COINGECKO, + marketPrice: response[symbol][this.baseCurrency.toLowerCase()], + marketState: 'open' + }; + } + } + } catch (error) { + Logger.error(error, 'CoinGeckoService'); + } + + return results; + } + + public async search(aQuery: string): Promise<{ items: LookupItem[] }> { + let items: LookupItem[] = []; + + if (aQuery.length <= 2) { + return { items }; + } + + try { + const get = bent( + `${this.URL}/search?query=${aQuery}`, + 'GET', + 'json', + 200 + ); + const { coins } = await get(); + + items = coins.map(({ id: symbol, name }) => { + return { + name, + symbol, + currency: this.baseCurrency, + dataSource: this.getName() + }; + }); + } catch (error) { + Logger.error(error, 'CoinGeckoService'); + } + + return { items }; + } +} diff --git a/apps/api/src/services/data-provider/data-provider.module.ts b/apps/api/src/services/data-provider/data-provider.module.ts index abafe6189..d36a12aa6 100644 --- a/apps/api/src/services/data-provider/data-provider.module.ts +++ b/apps/api/src/services/data-provider/data-provider.module.ts @@ -1,6 +1,7 @@ import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module'; import { CryptocurrencyModule } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.module'; import { AlphaVantageService } from '@ghostfolio/api/services/data-provider/alpha-vantage/alpha-vantage.service'; +import { CoinGeckoService } from '@ghostfolio/api/services/data-provider/coingecko/coingecko.service'; import { EodHistoricalDataService } from '@ghostfolio/api/services/data-provider/eod-historical-data/eod-historical-data.service'; import { GoogleSheetsService } from '@ghostfolio/api/services/data-provider/google-sheets/google-sheets.service'; import { ManualService } from '@ghostfolio/api/services/data-provider/manual/manual.service'; @@ -21,6 +22,7 @@ import { DataProviderService } from './data-provider.service'; ], providers: [ AlphaVantageService, + CoinGeckoService, DataProviderService, EodHistoricalDataService, GoogleSheetsService, @@ -30,6 +32,7 @@ import { DataProviderService } from './data-provider.service'; { inject: [ AlphaVantageService, + CoinGeckoService, EodHistoricalDataService, GoogleSheetsService, ManualService, @@ -39,6 +42,7 @@ import { DataProviderService } from './data-provider.service'; provide: 'DataProviderInterfaces', useFactory: ( alphaVantageService, + coinGeckoService, eodHistoricalDataService, googleSheetsService, manualService, @@ -46,6 +50,7 @@ import { DataProviderService } from './data-provider.service'; yahooFinanceService ) => [ alphaVantageService, + coinGeckoService, eodHistoricalDataService, googleSheetsService, manualService, diff --git a/prisma/migrations/20230222200407_added_coingecko_to_data_source/migration.sql b/prisma/migrations/20230222200407_added_coingecko_to_data_source/migration.sql new file mode 100644 index 000000000..2b40d220a --- /dev/null +++ b/prisma/migrations/20230222200407_added_coingecko_to_data_source/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "DataSource" ADD VALUE 'COINGECKO'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 937897a1d..dc4c1302d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -205,6 +205,7 @@ enum AssetSubClass { enum DataSource { ALPHA_VANTAGE + COINGECKO EOD_HISTORICAL_DATA GOOGLE_SHEETS MANUAL From aef840c2ccc73090bff5dc66aaedf7890df60bca Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 25 Feb 2023 10:15:25 +0100 Subject: [PATCH 04/11] Bugfix/fix maximum call stack size exceeded error in value redaction (#1743) * Bugfix for RangeError: Maximum call stack size exceeded * Update changelog --- CHANGELOG.md | 1 + apps/api/src/helper/object.helper.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 087480e8d..b2c0912f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed `RangeError: Maximum call stack size exceeded` for values of type `Big` in the value redaction interceptor for the impersonation mode - Reset the letter spacing in buttons ## 1.237.0 - 2023-02-19 diff --git a/apps/api/src/helper/object.helper.ts b/apps/api/src/helper/object.helper.ts index 7ee07b468..6db53b0a1 100644 --- a/apps/api/src/helper/object.helper.ts +++ b/apps/api/src/helper/object.helper.ts @@ -1,3 +1,4 @@ +import Big from 'big.js'; import { cloneDeep, isArray, isObject } from 'lodash'; export function hasNotDefinedValuesInObject(aObject: Object): boolean { @@ -59,7 +60,10 @@ export function redactAttributes({ return redactAttributes({ options, object: currentObject }); } ); - } else if (isObject(redactedObject[property])) { + } else if ( + isObject(redactedObject[property]) && + !(redactedObject[property] instanceof Big) + ) { // Recursively call the function on the nested object redactedObject[property] = redactAttributes({ options, From 897e941e7a93d47e0595fd986da5614d6cfa66d1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 25 Feb 2023 10:33:45 +0100 Subject: [PATCH 05/11] Feature/add data provider info to position (#1730) * Add data provider info * Update changelog --- CHANGELOG.md | 1 + .../portfolio/current-rate.service.mock.ts | 14 ++-- .../portfolio/current-rate.service.spec.ts | 31 ++++--- .../src/app/portfolio/current-rate.service.ts | 20 ++++- .../portfolio-position-detail.interface.ts | 2 + .../src/app/portfolio/portfolio-calculator.ts | 52 ++++++++---- .../src/app/portfolio/portfolio.service.ts | 3 + .../coingecko/coingecko.service.ts | 9 ++ .../api/src/services/interfaces/interfaces.ts | 3 +- .../position-detail-dialog.component.ts | 4 + .../position-detail-dialog.html | 10 ++- .../position-detail-dialog.module.ts | 2 + apps/client/src/locales/messages.de.xlf | 82 ++++++++++--------- apps/client/src/locales/messages.es.xlf | 82 ++++++++++--------- apps/client/src/locales/messages.fr.xlf | 82 ++++++++++--------- apps/client/src/locales/messages.it.xlf | 82 ++++++++++--------- apps/client/src/locales/messages.nl.xlf | 82 ++++++++++--------- apps/client/src/locales/messages.pt.xlf | 82 ++++++++++--------- apps/client/src/locales/messages.xlf | 81 +++++++++--------- .../data-provider-info.interface.ts | 4 + libs/common/src/lib/interfaces/index.ts | 2 + .../data-provider-credits.component.html | 9 ++ .../data-provider-credits.component.scss | 7 ++ .../data-provider-credits.component.ts | 14 ++++ .../data-provider-credits.module.ts | 12 +++ .../ui/src/lib/data-provider-credits/index.ts | 1 + 26 files changed, 474 insertions(+), 299 deletions(-) create mode 100644 libs/common/src/lib/interfaces/data-provider-info.interface.ts create mode 100644 libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html create mode 100644 libs/ui/src/lib/data-provider-credits/data-provider-credits.component.scss create mode 100644 libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts create mode 100644 libs/ui/src/lib/data-provider-credits/data-provider-credits.module.ts create mode 100644 libs/ui/src/lib/data-provider-credits/index.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index b2c0912f1..a2cc2b94a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added `COINGECKO` as a new data source type +- Added support for data provider information to the position detail dialog - Added the configuration to publish a `linux/arm/v7` docker image ### Fixed diff --git a/apps/api/src/app/portfolio/current-rate.service.mock.ts b/apps/api/src/app/portfolio/current-rate.service.mock.ts index 004f642bf..cac110f05 100644 --- a/apps/api/src/app/portfolio/current-rate.service.mock.ts +++ b/apps/api/src/app/portfolio/current-rate.service.mock.ts @@ -1,4 +1,5 @@ import { parseDate, resetHours } from '@ghostfolio/common/helper'; +import { DataProviderInfo } from '@ghostfolio/common/interfaces'; import { addDays, endOfDay, isBefore, isSameDay } from 'date-fns'; import { GetValueObject } from './interfaces/get-value-object.interface'; @@ -48,8 +49,11 @@ export const CurrentRateServiceMock = { getValues: ({ dataGatheringItems, dateQuery - }: GetValuesParams): Promise => { - const result: GetValueObject[] = []; + }: GetValuesParams): Promise<{ + dataProviderInfos: DataProviderInfo[]; + values: GetValueObject[]; + }> => { + const values: GetValueObject[] = []; if (dateQuery.lt) { for ( let date = resetHours(dateQuery.gte); @@ -57,7 +61,7 @@ export const CurrentRateServiceMock = { date = addDays(date, 1) ) { for (const dataGatheringItem of dataGatheringItems) { - result.push({ + values.push({ date, marketPriceInBaseCurrency: mockGetValue( dataGatheringItem.symbol, @@ -70,7 +74,7 @@ export const CurrentRateServiceMock = { } else { for (const date of dateQuery.in) { for (const dataGatheringItem of dataGatheringItems) { - result.push({ + values.push({ date, marketPriceInBaseCurrency: mockGetValue( dataGatheringItem.symbol, @@ -81,6 +85,6 @@ export const CurrentRateServiceMock = { } } } - return Promise.resolve(result); + return Promise.resolve({ values, dataProviderInfos: [] }); } }; diff --git a/apps/api/src/app/portfolio/current-rate.service.spec.ts b/apps/api/src/app/portfolio/current-rate.service.spec.ts index 9528f980f..9171e5fa3 100644 --- a/apps/api/src/app/portfolio/current-rate.service.spec.ts +++ b/apps/api/src/app/portfolio/current-rate.service.spec.ts @@ -1,6 +1,7 @@ import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data.service'; +import { DataProviderInfo } from '@ghostfolio/common/interfaces'; import { DataSource, MarketData } from '@prisma/client'; import { CurrentRateService } from './current-rate.service'; @@ -103,17 +104,23 @@ describe('CurrentRateService', () => { }, userCurrency: 'CHF' }) - ).toMatchObject([ - { - date: undefined, - marketPriceInBaseCurrency: 1841.823902, - symbol: 'AMZN' - }, - { - date: undefined, - marketPriceInBaseCurrency: 1847.839966, - symbol: 'AMZN' - } - ]); + ).toMatchObject<{ + dataProviderInfos: DataProviderInfo[]; + values: GetValueObject[]; + }>({ + dataProviderInfos: [], + values: [ + { + date: undefined, + marketPriceInBaseCurrency: 1841.823902, + symbol: 'AMZN' + }, + { + date: undefined, + marketPriceInBaseCurrency: 1847.839966, + symbol: 'AMZN' + } + ] + }); }); }); diff --git a/apps/api/src/app/portfolio/current-rate.service.ts b/apps/api/src/app/portfolio/current-rate.service.ts index 86020ce2e..b3a432521 100644 --- a/apps/api/src/app/portfolio/current-rate.service.ts +++ b/apps/api/src/app/portfolio/current-rate.service.ts @@ -2,6 +2,7 @@ import { DataProviderService } from '@ghostfolio/api/services/data-provider/data import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data.service'; import { resetHours } from '@ghostfolio/common/helper'; +import { DataProviderInfo } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; import { isBefore, isToday } from 'date-fns'; import { flatten } from 'lodash'; @@ -22,7 +23,11 @@ export class CurrentRateService { dataGatheringItems, dateQuery, userCurrency - }: GetValuesParams): Promise { + }: GetValuesParams): Promise<{ + dataProviderInfos: DataProviderInfo[]; + values: GetValueObject[]; + }> { + const dataProviderInfos: DataProviderInfo[] = []; const includeToday = (!dateQuery.lt || isBefore(new Date(), dateQuery.lt)) && (!dateQuery.gte || isBefore(dateQuery.gte, new Date())) && @@ -38,6 +43,14 @@ export class CurrentRateService { .then((dataResultProvider) => { const result: GetValueObject[] = []; for (const dataGatheringItem of dataGatheringItems) { + if ( + dataResultProvider?.[dataGatheringItem.symbol]?.dataProviderInfo + ) { + dataProviderInfos.push( + dataResultProvider[dataGatheringItem.symbol].dataProviderInfo + ); + } + result.push({ date: today, marketPriceInBaseCurrency: @@ -81,7 +94,10 @@ export class CurrentRateService { }) ); - return flatten(await Promise.all(promises)); + return { + dataProviderInfos, + values: flatten(await Promise.all(promises)) + }; } private containsToday(dates: Date[]): boolean { diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts b/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts index 48a0ac671..827aa25fe 100644 --- a/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts @@ -1,4 +1,5 @@ import { + DataProviderInfo, EnhancedSymbolProfile, HistoricalDataItem } from '@ghostfolio/common/interfaces'; @@ -7,6 +8,7 @@ import { Tag } from '@prisma/client'; export interface PortfolioPositionDetail { averagePrice: number; + dataProviderInfo: DataProviderInfo; dividendInBaseCurrency: number; feeInBaseCurrency: number; firstBuyDate: string; diff --git a/apps/api/src/app/portfolio/portfolio-calculator.ts b/apps/api/src/app/portfolio/portfolio-calculator.ts index f99defd53..06c617166 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator.ts @@ -1,7 +1,11 @@ import { TimelineInfoInterface } from '@ghostfolio/api/app/portfolio/interfaces/timeline-info.interface'; import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces'; import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper'; -import { ResponseError, TimelinePosition } from '@ghostfolio/common/interfaces'; +import { + DataProviderInfo, + ResponseError, + TimelinePosition +} from '@ghostfolio/common/interfaces'; import { GroupBy } from '@ghostfolio/common/types'; import { Logger } from '@nestjs/common'; import { Type as TypeOfOrder } from '@prisma/client'; @@ -45,6 +49,7 @@ export class PortfolioCalculator { private currency: string; private currentRateService: CurrentRateService; + private dataProviderInfos: DataProviderInfo[]; private orders: PortfolioOrder[]; private transactionPoints: TransactionPoint[]; @@ -202,14 +207,17 @@ export class PortfolioCalculator { symbols[item.symbol] = true; } - const marketSymbols = await this.currentRateService.getValues({ - currencies, - dataGatheringItems, - dateQuery: { - in: dates - }, - userCurrency: this.currency - }); + const { dataProviderInfos, values: marketSymbols } = + await this.currentRateService.getValues({ + currencies, + dataGatheringItems, + dateQuery: { + in: dates + }, + userCurrency: this.currency + }); + + this.dataProviderInfos = dataProviderInfos; const marketSymbolMap: { [date: string]: { [symbol: string]: Big }; @@ -368,14 +376,17 @@ export class PortfolioCalculator { dates.push(resetHours(end)); - const marketSymbols = await this.currentRateService.getValues({ - currencies, - dataGatheringItems, - dateQuery: { - in: dates - }, - userCurrency: this.currency - }); + const { dataProviderInfos, values: marketSymbols } = + await this.currentRateService.getValues({ + currencies, + dataGatheringItems, + dateQuery: { + in: dates + }, + userCurrency: this.currency + }); + + this.dataProviderInfos = dataProviderInfos; const marketSymbolMap: { [date: string]: { [symbol: string]: Big }; @@ -463,6 +474,10 @@ export class PortfolioCalculator { }; } + public getDataProviderInfos() { + return this.dataProviderInfos; + } + public getInvestments(): { date: string; investment: Big }[] { if (this.transactionPoints.length === 0) { return []; @@ -748,7 +763,7 @@ export class PortfolioCalculator { let marketSymbols: GetValueObject[] = []; if (dataGatheringItems.length > 0) { try { - marketSymbols = await this.currentRateService.getValues({ + const { values } = await this.currentRateService.getValues({ currencies, dataGatheringItems, dateQuery: { @@ -757,6 +772,7 @@ export class PortfolioCalculator { }, userCurrency: this.currency }); + marketSymbols = values; } catch (error) { Logger.error( `Failed to fetch info for date ${startDate} with exception`, diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 2564d1d49..1677ffc29 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -678,6 +678,7 @@ export class PortfolioService { return { tags, averagePrice: undefined, + dataProviderInfo: undefined, dividendInBaseCurrency: undefined, feeInBaseCurrency: undefined, firstBuyDate: undefined, @@ -849,6 +850,7 @@ export class PortfolioService { tags, transactionCount, averagePrice: averagePrice.toNumber(), + dataProviderInfo: portfolioCalculator.getDataProviderInfos()?.[0], dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), feeInBaseCurrency: this.exchangeRateDataService.toCurrency( fee.toNumber(), @@ -911,6 +913,7 @@ export class PortfolioService { SymbolProfile, tags, averagePrice: 0, + dataProviderInfo: undefined, dividendInBaseCurrency: 0, feeInBaseCurrency: 0, firstBuyDate: undefined, diff --git a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts index 7bd852f5d..a96511246 100644 --- a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts +++ b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts @@ -6,6 +6,7 @@ import { IDataProviderResponse } from '@ghostfolio/api/services/interfaces/interfaces'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; +import { DataProviderInfo } from '@ghostfolio/common/interfaces'; import { Granularity } from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; import { @@ -145,6 +146,7 @@ export class CoinGeckoService implements DataProviderInterface { if (Object.prototype.hasOwnProperty.call(response, symbol)) { results[symbol] = { currency: this.baseCurrency, + dataProviderInfo: this.getDataProviderInfo(), dataSource: DataSource.COINGECKO, marketPrice: response[symbol][this.baseCurrency.toLowerCase()], marketState: 'open' @@ -188,4 +190,11 @@ export class CoinGeckoService implements DataProviderInterface { return { items }; } + + private getDataProviderInfo(): DataProviderInfo { + return { + name: 'CoinGecko', + url: 'https://coingecko.com' + }; + } } diff --git a/apps/api/src/services/interfaces/interfaces.ts b/apps/api/src/services/interfaces/interfaces.ts index 1148dd6af..58f25243c 100644 --- a/apps/api/src/services/interfaces/interfaces.ts +++ b/apps/api/src/services/interfaces/interfaces.ts @@ -1,4 +1,4 @@ -import { UniqueAsset } from '@ghostfolio/common/interfaces'; +import { DataProviderInfo, UniqueAsset } from '@ghostfolio/common/interfaces'; import { MarketState } from '@ghostfolio/common/types'; import { Account, @@ -28,6 +28,7 @@ export interface IDataProviderHistoricalResponse { export interface IDataProviderResponse { currency: string; + dataProviderInfo?: DataProviderInfo; dataSource: DataSource; marketPrice: number; marketState: MarketState; diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts index aa2880d81..9869ad453 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts @@ -13,6 +13,7 @@ import { import { DataService } from '@ghostfolio/client/services/data.service'; import { DATE_FORMAT, downloadAsFile } from '@ghostfolio/common/helper'; import { + DataProviderInfo, EnhancedSymbolProfile, LineChartItem } from '@ghostfolio/common/interfaces'; @@ -40,6 +41,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { public countries: { [code: string]: { name: string; value: number }; }; + public dataProviderInfo: DataProviderInfo; public dividendInBaseCurrency: number; public feeInBaseCurrency: number; public firstBuyDate: string; @@ -83,6 +85,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { .subscribe( ({ averagePrice, + dataProviderInfo, dividendInBaseCurrency, feeInBaseCurrency, firstBuyDate, @@ -105,6 +108,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.averagePrice = averagePrice; this.benchmarkDataItems = []; this.countries = {}; + this.dataProviderInfo = dataProviderInfo; this.dividendInBaseCurrency = dividendInBaseCurrency; this.feeInBaseCurrency = feeInBaseCurrency; this.firstBuyDate = firstBuyDate; diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html index 33aebd8f3..7b009d85e 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html @@ -227,6 +227,12 @@ +
+
+ + +
+
@@ -249,7 +255,7 @@
-
+
Tags
{{ tag.name }} @@ -261,7 +267,7 @@ *ngIf="data.hasPermissionToReportDataGlitch === true && orders?.length > 0" class="row" > -
+

apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 234 + 240 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -122,7 +122,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 72,74 + 75,77 libs/ui/src/lib/activities-table/activities-table.component.html @@ -158,7 +158,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 119,120 + 122,123 libs/ui/src/lib/activities-table/activities-table.component.html @@ -250,7 +250,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 88,90 + 91,93 @@ -342,7 +342,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 94,95 + 97,98 libs/ui/src/lib/activities-table/activities-table.component.html @@ -382,7 +382,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 250,254 + 253,257 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -414,7 +414,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 257,262 + 260,265 @@ -638,7 +638,7 @@ apps/client/src/app/components/header/header.component.html - 145 + 140 @@ -682,7 +682,7 @@ apps/client/src/app/components/header/header.component.html - 157 + 152 @@ -694,7 +694,7 @@ apps/client/src/app/components/header/header.component.html - 167 + 162 @@ -710,7 +710,7 @@ apps/client/src/app/components/header/header.component.html - 175 + 170 apps/client/src/app/pages/accounts/accounts-page.html @@ -726,7 +726,7 @@ apps/client/src/app/components/header/header.component.html - 192 + 186 @@ -738,7 +738,7 @@ apps/client/src/app/components/header/header.component.html - 203 + 197 apps/client/src/app/pages/resources/resources-page.html @@ -754,11 +754,11 @@ apps/client/src/app/components/header/header.component.html - 214 + 208 apps/client/src/app/components/header/header.component.html - 271 + 265 @@ -770,7 +770,7 @@ apps/client/src/app/components/header/header.component.html - 260 + 254 @@ -778,7 +778,7 @@ Ich apps/client/src/app/components/header/header.component.html - 127 + 123 @@ -786,7 +786,7 @@ Mein Ghostfolio apps/client/src/app/components/header/header.component.html - 183 + 177 @@ -794,7 +794,7 @@ Über Ghostfolio apps/client/src/app/components/header/header.component.html - 222 + 216 @@ -802,7 +802,7 @@ Features apps/client/src/app/components/header/header.component.html - 249 + 243 @@ -810,7 +810,7 @@ Märkte apps/client/src/app/components/header/header.component.html - 283 + 277 apps/client/src/app/components/home-market/home-market.html @@ -934,7 +934,7 @@ Einloggen apps/client/src/app/components/header/header.component.html - 292 + 286 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1098,7 +1098,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 117,119 + 120,122 @@ -1146,11 +1146,11 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 253 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 209,211 + 212,214 @@ -1158,7 +1158,7 @@ Datenfehler melden apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 268 + 274 @@ -1566,7 +1566,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 78,80 + 81,83 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1894,7 +1894,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 108,109 + 111,112 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1906,7 +1906,7 @@ Stückpreis apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 120,123 + 123,126 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1918,11 +1918,11 @@ Gebühr apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 141,142 + 144,145 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 158,159 + 161,162 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1938,7 +1938,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 167,170 + 170,173 @@ -1958,7 +1958,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 181,183 + 184,186 @@ -2174,7 +2174,7 @@ Möchtest du diese Aktivität wirklich löschen? libs/ui/src/lib/activities-table/activities-table.component.ts - 200 + 201 @@ -2246,7 +2246,7 @@ Registrieren apps/client/src/app/components/header/header.component.html - 300 + 294 @@ -2342,7 +2342,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196,198 + 199,201 @@ -2526,7 +2526,7 @@ Filtern nach Konto, Währung, Symbol oder Typ... libs/ui/src/lib/activities-table/activities-table.component.ts - 389 + 390 @@ -3473,6 +3473,14 @@ 10 + + Market data provided by + Marktdaten bereitgestellt von + + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 + + diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index 3c8a8e30b..4d4cf9a5a 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -103,7 +103,7 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 234 + 240 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -123,7 +123,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 72,74 + 75,77 libs/ui/src/lib/activities-table/activities-table.component.html @@ -159,7 +159,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 119,120 + 122,123 libs/ui/src/lib/activities-table/activities-table.component.html @@ -251,7 +251,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 88,90 + 91,93 @@ -343,7 +343,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 94,95 + 97,98 libs/ui/src/lib/activities-table/activities-table.component.html @@ -383,7 +383,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 250,254 + 253,257 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -415,7 +415,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 257,262 + 260,265 @@ -639,7 +639,7 @@ apps/client/src/app/components/header/header.component.html - 145 + 140 @@ -683,7 +683,7 @@ apps/client/src/app/components/header/header.component.html - 157 + 152 @@ -695,7 +695,7 @@ apps/client/src/app/components/header/header.component.html - 167 + 162 @@ -711,7 +711,7 @@ apps/client/src/app/components/header/header.component.html - 175 + 170 apps/client/src/app/pages/accounts/accounts-page.html @@ -727,7 +727,7 @@ apps/client/src/app/components/header/header.component.html - 192 + 186 @@ -739,7 +739,7 @@ apps/client/src/app/components/header/header.component.html - 203 + 197 apps/client/src/app/pages/resources/resources-page.html @@ -755,11 +755,11 @@ apps/client/src/app/components/header/header.component.html - 214 + 208 apps/client/src/app/components/header/header.component.html - 271 + 265 @@ -771,7 +771,7 @@ apps/client/src/app/components/header/header.component.html - 260 + 254 @@ -779,7 +779,7 @@ apps/client/src/app/components/header/header.component.html - 127 + 123 @@ -787,7 +787,7 @@ Mi Ghostfolio apps/client/src/app/components/header/header.component.html - 183 + 177 @@ -795,7 +795,7 @@ Sobre Ghostfolio apps/client/src/app/components/header/header.component.html - 222 + 216 @@ -803,7 +803,7 @@ Funcionalidades apps/client/src/app/components/header/header.component.html - 249 + 243 @@ -811,7 +811,7 @@ Mercados apps/client/src/app/components/header/header.component.html - 283 + 277 apps/client/src/app/components/home-market/home-market.html @@ -935,7 +935,7 @@ Iniciar sesión apps/client/src/app/components/header/header.component.html - 292 + 286 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1099,7 +1099,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 117,119 + 120,122 @@ -1147,11 +1147,11 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 253 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 209,211 + 212,214 @@ -1159,7 +1159,7 @@ Reporta un anomalía de los datos apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 268 + 274 @@ -1567,7 +1567,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 78,80 + 81,83 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1895,7 +1895,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 108,109 + 111,112 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1907,7 +1907,7 @@ Precio unitario apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 120,123 + 123,126 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1919,11 +1919,11 @@ Comisión apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 141,142 + 144,145 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 158,159 + 161,162 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1939,7 +1939,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 167,170 + 170,173 @@ -1959,7 +1959,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 181,183 + 184,186 @@ -2175,7 +2175,7 @@ ¿Estás seguro de eliminar esta operación? libs/ui/src/lib/activities-table/activities-table.component.ts - 200 + 201 @@ -2247,7 +2247,7 @@ Comenzar apps/client/src/app/components/header/header.component.html - 300 + 294 @@ -2323,7 +2323,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196,198 + 199,201 @@ -2527,7 +2527,7 @@ Filtrar por cuenta, divisa, símbolo o tipo... libs/ui/src/lib/activities-table/activities-table.component.ts - 389 + 390 @@ -3474,6 +3474,14 @@ 10 + + Market data provided by + Market data provided by + + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 + + diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index bdec2d456..0806edb02 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -126,7 +126,7 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 234 + 240 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -146,7 +146,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 72,74 + 75,77 libs/ui/src/lib/activities-table/activities-table.component.html @@ -186,7 +186,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 78,80 + 81,83 libs/ui/src/lib/activities-table/activities-table.component.html @@ -218,7 +218,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 119,120 + 122,123 libs/ui/src/lib/activities-table/activities-table.component.html @@ -302,7 +302,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 88,90 + 91,93 @@ -402,7 +402,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 94,95 + 97,98 libs/ui/src/lib/activities-table/activities-table.component.html @@ -442,7 +442,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 250,254 + 253,257 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -474,7 +474,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 257,262 + 260,265 @@ -502,7 +502,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 181,183 + 184,186 @@ -522,7 +522,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196,198 + 199,201 @@ -698,7 +698,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 167,170 + 170,173 @@ -798,11 +798,11 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 253 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 209,211 + 212,214 @@ -886,7 +886,7 @@ apps/client/src/app/components/header/header.component.html - 145 + 140 @@ -910,7 +910,7 @@ apps/client/src/app/components/header/header.component.html - 175 + 170 apps/client/src/app/pages/accounts/accounts-page.html @@ -994,7 +994,7 @@ apps/client/src/app/components/header/header.component.html - 157 + 152 @@ -1006,7 +1006,7 @@ apps/client/src/app/components/header/header.component.html - 167 + 162 @@ -1018,7 +1018,7 @@ apps/client/src/app/components/header/header.component.html - 192 + 186 @@ -1030,7 +1030,7 @@ apps/client/src/app/components/header/header.component.html - 203 + 197 apps/client/src/app/pages/resources/resources-page.html @@ -1046,11 +1046,11 @@ apps/client/src/app/components/header/header.component.html - 214 + 208 apps/client/src/app/components/header/header.component.html - 271 + 265 @@ -1062,7 +1062,7 @@ apps/client/src/app/components/header/header.component.html - 260 + 254 @@ -1070,7 +1070,7 @@ Moi apps/client/src/app/components/header/header.component.html - 127 + 123 @@ -1078,7 +1078,7 @@ Mon Ghostfolio apps/client/src/app/components/header/header.component.html - 183 + 177 @@ -1086,7 +1086,7 @@ À propos de Ghostfolio apps/client/src/app/components/header/header.component.html - 222 + 216 @@ -1094,7 +1094,7 @@ Fonctionnalités apps/client/src/app/components/header/header.component.html - 249 + 243 @@ -1102,7 +1102,7 @@ Marchés apps/client/src/app/components/header/header.component.html - 283 + 277 apps/client/src/app/components/home-market/home-market.html @@ -1114,7 +1114,7 @@ Se connecter apps/client/src/app/components/header/header.component.html - 292 + 286 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1126,7 +1126,7 @@ Démarrer apps/client/src/app/components/header/header.component.html - 300 + 294 @@ -1454,7 +1454,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 117,119 + 120,122 @@ -1506,7 +1506,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 108,109 + 111,112 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1534,7 +1534,7 @@ Signaler une Erreur de Données apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 268 + 274 @@ -2130,7 +2130,7 @@ Prix Unitaire apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 120,123 + 123,126 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2142,11 +2142,11 @@ Frais apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 141,142 + 144,145 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 158,159 + 161,162 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2710,7 +2710,7 @@ Voulez-vous vraiment supprimer cette activité ? libs/ui/src/lib/activities-table/activities-table.component.ts - 200 + 201 @@ -2718,7 +2718,7 @@ Filtrer par compte, devise, symbole, ou type... libs/ui/src/lib/activities-table/activities-table.component.ts - 389 + 390 @@ -3472,6 +3472,14 @@ 10 + + Market data provided by + Market data provided by + + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 + + diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 138be0c06..fa26ac4d7 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -103,7 +103,7 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 234 + 240 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -123,7 +123,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 72,74 + 75,77 libs/ui/src/lib/activities-table/activities-table.component.html @@ -159,7 +159,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 119,120 + 122,123 libs/ui/src/lib/activities-table/activities-table.component.html @@ -251,7 +251,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 88,90 + 91,93 @@ -343,7 +343,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 94,95 + 97,98 libs/ui/src/lib/activities-table/activities-table.component.html @@ -383,7 +383,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 250,254 + 253,257 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -415,7 +415,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 257,262 + 260,265 @@ -639,7 +639,7 @@ apps/client/src/app/components/header/header.component.html - 145 + 140 @@ -683,7 +683,7 @@ apps/client/src/app/components/header/header.component.html - 157 + 152 @@ -695,7 +695,7 @@ apps/client/src/app/components/header/header.component.html - 167 + 162 @@ -711,7 +711,7 @@ apps/client/src/app/components/header/header.component.html - 175 + 170 apps/client/src/app/pages/accounts/accounts-page.html @@ -727,7 +727,7 @@ apps/client/src/app/components/header/header.component.html - 192 + 186 @@ -739,7 +739,7 @@ apps/client/src/app/components/header/header.component.html - 203 + 197 apps/client/src/app/pages/resources/resources-page.html @@ -755,11 +755,11 @@ apps/client/src/app/components/header/header.component.html - 214 + 208 apps/client/src/app/components/header/header.component.html - 271 + 265 @@ -771,7 +771,7 @@ apps/client/src/app/components/header/header.component.html - 260 + 254 @@ -779,7 +779,7 @@ Io apps/client/src/app/components/header/header.component.html - 127 + 123 @@ -787,7 +787,7 @@ Il mio Ghostfolio apps/client/src/app/components/header/header.component.html - 183 + 177 @@ -795,7 +795,7 @@ Informazioni su Ghostfolio apps/client/src/app/components/header/header.component.html - 222 + 216 @@ -803,7 +803,7 @@ Funzionalità apps/client/src/app/components/header/header.component.html - 249 + 243 @@ -811,7 +811,7 @@ Mercati apps/client/src/app/components/header/header.component.html - 283 + 277 apps/client/src/app/components/home-market/home-market.html @@ -935,7 +935,7 @@ Accedi apps/client/src/app/components/header/header.component.html - 292 + 286 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1099,7 +1099,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 117,119 + 120,122 @@ -1147,11 +1147,11 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 253 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 209,211 + 212,214 @@ -1159,7 +1159,7 @@ Segnala un'anomalia dei dati apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 268 + 274 @@ -1567,7 +1567,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 78,80 + 81,83 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1895,7 +1895,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 108,109 + 111,112 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1907,7 +1907,7 @@ Prezzo unitario apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 120,123 + 123,126 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1919,11 +1919,11 @@ Commissione apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 141,142 + 144,145 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 158,159 + 161,162 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1939,7 +1939,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 167,170 + 170,173 @@ -1959,7 +1959,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 181,183 + 184,186 @@ -2175,7 +2175,7 @@ Vuoi davvero eliminare questa attività? libs/ui/src/lib/activities-table/activities-table.component.ts - 200 + 201 @@ -2247,7 +2247,7 @@ Inizia apps/client/src/app/components/header/header.component.html - 300 + 294 @@ -2323,7 +2323,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196,198 + 199,201 @@ -2527,7 +2527,7 @@ Filtra per account, valuta, simbolo o tipo... libs/ui/src/lib/activities-table/activities-table.component.ts - 389 + 390 @@ -3474,6 +3474,14 @@ 10 + + Market data provided by + Market data provided by + + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 + + diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 761a2d880..49781c2ea 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -102,7 +102,7 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 234 + 240 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -122,7 +122,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 72,74 + 75,77 libs/ui/src/lib/activities-table/activities-table.component.html @@ -158,7 +158,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 119,120 + 122,123 libs/ui/src/lib/activities-table/activities-table.component.html @@ -250,7 +250,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 88,90 + 91,93 @@ -342,7 +342,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 94,95 + 97,98 libs/ui/src/lib/activities-table/activities-table.component.html @@ -382,7 +382,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 250,254 + 253,257 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -414,7 +414,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 257,262 + 260,265 @@ -638,7 +638,7 @@ apps/client/src/app/components/header/header.component.html - 145 + 140 @@ -682,7 +682,7 @@ apps/client/src/app/components/header/header.component.html - 157 + 152 @@ -694,7 +694,7 @@ apps/client/src/app/components/header/header.component.html - 167 + 162 @@ -710,7 +710,7 @@ apps/client/src/app/components/header/header.component.html - 175 + 170 apps/client/src/app/pages/accounts/accounts-page.html @@ -726,7 +726,7 @@ apps/client/src/app/components/header/header.component.html - 192 + 186 @@ -738,7 +738,7 @@ apps/client/src/app/components/header/header.component.html - 203 + 197 apps/client/src/app/pages/resources/resources-page.html @@ -754,11 +754,11 @@ apps/client/src/app/components/header/header.component.html - 214 + 208 apps/client/src/app/components/header/header.component.html - 271 + 265 @@ -770,7 +770,7 @@ apps/client/src/app/components/header/header.component.html - 260 + 254 @@ -778,7 +778,7 @@ Ik apps/client/src/app/components/header/header.component.html - 127 + 123 @@ -786,7 +786,7 @@ Mijn Ghostfolio apps/client/src/app/components/header/header.component.html - 183 + 177 @@ -794,7 +794,7 @@ Over Ghostfolio apps/client/src/app/components/header/header.component.html - 222 + 216 @@ -802,7 +802,7 @@ Kenmerken apps/client/src/app/components/header/header.component.html - 249 + 243 @@ -810,7 +810,7 @@ Markten apps/client/src/app/components/header/header.component.html - 283 + 277 apps/client/src/app/components/home-market/home-market.html @@ -934,7 +934,7 @@ Aanmelden apps/client/src/app/components/header/header.component.html - 292 + 286 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1098,7 +1098,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 117,119 + 120,122 @@ -1146,11 +1146,11 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 253 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 209,211 + 212,214 @@ -1158,7 +1158,7 @@ Gegevensstoring melden apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 268 + 274 @@ -1566,7 +1566,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 78,80 + 81,83 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1894,7 +1894,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 108,109 + 111,112 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1906,7 +1906,7 @@ Prijs per eenheid apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 120,123 + 123,126 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1918,11 +1918,11 @@ Transactiekosten apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 141,142 + 144,145 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 158,159 + 161,162 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1938,7 +1938,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 167,170 + 170,173 @@ -1958,7 +1958,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 181,183 + 184,186 @@ -2174,7 +2174,7 @@ Wilt u deze activiteit echt verwijderen? libs/ui/src/lib/activities-table/activities-table.component.ts - 200 + 201 @@ -2246,7 +2246,7 @@ Aan de slag apps/client/src/app/components/header/header.component.html - 300 + 294 @@ -2322,7 +2322,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196,198 + 199,201 @@ -2526,7 +2526,7 @@ Filter op rekening, valuta, symbool of type... libs/ui/src/lib/activities-table/activities-table.component.ts - 389 + 390 @@ -3473,6 +3473,14 @@ 10 + + Market data provided by + Market data provided by + + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 + + diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 790f8b726..ff3affa36 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -126,7 +126,7 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 234 + 240 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -146,7 +146,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 72,74 + 75,77 libs/ui/src/lib/activities-table/activities-table.component.html @@ -186,7 +186,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 78,80 + 81,83 libs/ui/src/lib/activities-table/activities-table.component.html @@ -218,7 +218,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 119,120 + 122,123 libs/ui/src/lib/activities-table/activities-table.component.html @@ -302,7 +302,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 88,90 + 91,93 @@ -402,7 +402,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 94,95 + 97,98 libs/ui/src/lib/activities-table/activities-table.component.html @@ -442,7 +442,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 250,254 + 253,257 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -474,7 +474,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 257,262 + 260,265 @@ -502,7 +502,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 181,183 + 184,186 @@ -522,7 +522,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196,198 + 199,201 @@ -770,7 +770,7 @@ apps/client/src/app/components/header/header.component.html - 145 + 140 @@ -794,7 +794,7 @@ apps/client/src/app/components/header/header.component.html - 175 + 170 apps/client/src/app/pages/accounts/accounts-page.html @@ -878,7 +878,7 @@ apps/client/src/app/components/header/header.component.html - 157 + 152 @@ -890,7 +890,7 @@ apps/client/src/app/components/header/header.component.html - 167 + 162 @@ -902,7 +902,7 @@ apps/client/src/app/components/header/header.component.html - 192 + 186 @@ -914,7 +914,7 @@ apps/client/src/app/components/header/header.component.html - 203 + 197 apps/client/src/app/pages/resources/resources-page.html @@ -930,11 +930,11 @@ apps/client/src/app/components/header/header.component.html - 214 + 208 apps/client/src/app/components/header/header.component.html - 271 + 265 @@ -946,7 +946,7 @@ apps/client/src/app/components/header/header.component.html - 260 + 254 @@ -954,7 +954,7 @@ Me apps/client/src/app/components/header/header.component.html - 127 + 123 @@ -962,7 +962,7 @@ My Ghostfolio apps/client/src/app/components/header/header.component.html - 183 + 177 @@ -970,7 +970,7 @@ About Ghostfolio apps/client/src/app/components/header/header.component.html - 222 + 216 @@ -978,7 +978,7 @@ Features apps/client/src/app/components/header/header.component.html - 249 + 243 @@ -986,7 +986,7 @@ Markets apps/client/src/app/components/header/header.component.html - 283 + 277 apps/client/src/app/components/home-market/home-market.html @@ -998,7 +998,7 @@ Sign in apps/client/src/app/components/header/header.component.html - 292 + 286 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1010,7 +1010,7 @@ Get started apps/client/src/app/components/header/header.component.html - 300 + 294 @@ -1354,7 +1354,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 117,119 + 120,122 @@ -1406,7 +1406,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 108,109 + 111,112 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1494,11 +1494,11 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 253 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 209,211 + 212,214 @@ -1506,7 +1506,7 @@ Report Data Glitch apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 268 + 274 @@ -2078,7 +2078,7 @@ Unit Price apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 120,123 + 123,126 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2090,11 +2090,11 @@ Fee apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 141,142 + 144,145 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 158,159 + 161,162 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2110,7 +2110,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 167,170 + 170,173 @@ -2626,7 +2626,7 @@ Do you really want to delete this activity? libs/ui/src/lib/activities-table/activities-table.component.ts - 200 + 201 @@ -2634,7 +2634,7 @@ Filter by account, currency, symbol or type... libs/ui/src/lib/activities-table/activities-table.component.ts - 389 + 390 @@ -3473,6 +3473,14 @@ 10 + + Market data provided by + Market data provided by + + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 + + diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 8250ad2e9..075ae04a7 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -95,7 +95,7 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 234 + 240 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -114,7 +114,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 72,74 + 75,77 libs/ui/src/lib/activities-table/activities-table.component.html @@ -148,7 +148,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 119,120 + 122,123 libs/ui/src/lib/activities-table/activities-table.component.html @@ -234,7 +234,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 88,90 + 91,93 @@ -315,7 +315,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 94,95 + 97,98 libs/ui/src/lib/activities-table/activities-table.component.html @@ -353,7 +353,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 250,254 + 253,257 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -384,7 +384,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 257,262 + 260,265 @@ -583,7 +583,7 @@ apps/client/src/app/components/header/header.component.html - 145 + 140 @@ -622,7 +622,7 @@ apps/client/src/app/components/header/header.component.html - 157 + 152 @@ -633,7 +633,7 @@ apps/client/src/app/components/header/header.component.html - 167 + 162 @@ -648,7 +648,7 @@ apps/client/src/app/components/header/header.component.html - 175 + 170 apps/client/src/app/pages/accounts/accounts-page.html @@ -663,7 +663,7 @@ apps/client/src/app/components/header/header.component.html - 192 + 186 @@ -674,7 +674,7 @@ apps/client/src/app/components/header/header.component.html - 203 + 197 apps/client/src/app/pages/resources/resources-page.html @@ -689,11 +689,11 @@ apps/client/src/app/components/header/header.component.html - 214 + 208 apps/client/src/app/components/header/header.component.html - 271 + 265 @@ -704,42 +704,42 @@ apps/client/src/app/components/header/header.component.html - 260 + 254 Me apps/client/src/app/components/header/header.component.html - 127 + 123 My Ghostfolio apps/client/src/app/components/header/header.component.html - 183 + 177 About Ghostfolio apps/client/src/app/components/header/header.component.html - 222 + 216 Features apps/client/src/app/components/header/header.component.html - 249 + 243 Markets apps/client/src/app/components/header/header.component.html - 283 + 277 apps/client/src/app/components/home-market/home-market.html @@ -851,7 +851,7 @@ Sign in apps/client/src/app/components/header/header.component.html - 292 + 286 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -998,7 +998,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 117,119 + 120,122 @@ -1042,18 +1042,18 @@ apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 253 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 209,211 + 212,214 Report Data Glitch apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 268 + 274 @@ -1415,7 +1415,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 78,80 + 81,83 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1707,7 +1707,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 108,109 + 111,112 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1718,7 +1718,7 @@ Unit Price apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 120,123 + 123,126 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1729,11 +1729,11 @@ Fee apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 141,142 + 144,145 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 158,159 + 161,162 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1748,7 +1748,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 167,170 + 170,173 @@ -1767,7 +1767,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 181,183 + 184,186 @@ -1958,7 +1958,7 @@ Do you really want to delete this activity? libs/ui/src/lib/activities-table/activities-table.component.ts - 200 + 201 @@ -2021,7 +2021,7 @@ Get started apps/client/src/app/components/header/header.component.html - 300 + 294 @@ -2091,7 +2091,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196,198 + 199,201 @@ -2274,7 +2274,7 @@ Filter by account, currency, symbol or type... libs/ui/src/lib/activities-table/activities-table.component.ts - 389 + 390 @@ -3116,6 +3116,13 @@ 295 + + Market data provided by + + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 + + diff --git a/libs/common/src/lib/interfaces/data-provider-info.interface.ts b/libs/common/src/lib/interfaces/data-provider-info.interface.ts new file mode 100644 index 000000000..59f3a0b69 --- /dev/null +++ b/libs/common/src/lib/interfaces/data-provider-info.interface.ts @@ -0,0 +1,4 @@ +export interface DataProviderInfo { + name: string; + url: string; +} diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index a8ff96e0f..68b882601 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -10,6 +10,7 @@ import { import { BenchmarkMarketDataDetails } from './benchmark-market-data-details.interface'; import { Benchmark } from './benchmark.interface'; import { Coupon } from './coupon.interface'; +import { DataProviderInfo } from './data-provider-info.interface'; import { EnhancedSymbolProfile } from './enhanced-symbol-profile.interface'; import { Export } from './export.interface'; import { FilterGroup } from './filter-group.interface'; @@ -54,6 +55,7 @@ export { BenchmarkMarketDataDetails, BenchmarkResponse, Coupon, + DataProviderInfo, EnhancedSymbolProfile, Export, Filter, diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html new file mode 100644 index 000000000..fb9f2c13b --- /dev/null +++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html @@ -0,0 +1,9 @@ + + Market data provided by {{ + dataProviderInfo.name + }}, . + diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.scss b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.scss new file mode 100644 index 000000000..d732e2f02 --- /dev/null +++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.scss @@ -0,0 +1,7 @@ +:host { + display: block; + + a { + color: rgba(var(--palette-primary-500), 1); + } +} diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts new file mode 100644 index 000000000..1da2fcfc9 --- /dev/null +++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts @@ -0,0 +1,14 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { DataProviderInfo } from '@ghostfolio/common/interfaces'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'gf-data-provider-credits', + styleUrls: ['./data-provider-credits.component.scss'], + templateUrl: './data-provider-credits.component.html' +}) +export class DataProviderCreditsComponent { + @Input() dataProviderInfos: DataProviderInfo[]; + + public constructor() {} +} diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.module.ts b/libs/ui/src/lib/data-provider-credits/data-provider-credits.module.ts new file mode 100644 index 000000000..e5dd9d3b9 --- /dev/null +++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; + +import { DataProviderCreditsComponent } from './data-provider-credits.component'; + +@NgModule({ + declarations: [DataProviderCreditsComponent], + exports: [DataProviderCreditsComponent], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GfDataProviderCreditsModule {} diff --git a/libs/ui/src/lib/data-provider-credits/index.ts b/libs/ui/src/lib/data-provider-credits/index.ts new file mode 100644 index 000000000..5d3759577 --- /dev/null +++ b/libs/ui/src/lib/data-provider-credits/index.ts @@ -0,0 +1 @@ +export * from './data-provider-credits.module'; From a9819b9e252f800354b5c6730f7a5791184e5682 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 25 Feb 2023 10:33:59 +0100 Subject: [PATCH 06/11] Feature/upgrade zone.js to version 0.12.0 (#1740) * Upgrade zone.js * Update changelog --- CHANGELOG.md | 4 ++++ package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2cc2b94a..02eb7be8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for data provider information to the position detail dialog - Added the configuration to publish a `linux/arm/v7` docker image +### Changed + +- Upgraded `zone.js` from version `0.11.8` to `0.12.0` + ### Fixed - Fixed `RangeError: Maximum call stack size exceeded` for values of type `Big` in the value redaction interceptor for the impersonation mode diff --git a/package.json b/package.json index 74292f7da..239e053ae 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "twitter-api-v2": "1.10.3", "uuid": "9.0.0", "yahoo-finance2": "2.3.10", - "zone.js": "0.11.8" + "zone.js": "0.12.0" }, "devDependencies": { "@angular-devkit/build-angular": "15.1.6", diff --git a/yarn.lock b/yarn.lock index 5fa255777..3cc6b6798 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21932,10 +21932,10 @@ yocto-queue@^0.1.0: resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zone.js@0.11.8: - version "0.11.8" - resolved "https://registry.npmjs.org/zone.js/-/zone.js-0.11.8.tgz" - integrity sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA== +zone.js@0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.12.0.tgz#a4a6e5fab6d34bd37d89c77e89ac2e6f4a3d2c30" + integrity sha512-XtC+I5dXU14HrzidAKBNMqneIVUykLEAA1x+v4KVrd6AUPWlwYORF8KgsVqvgdHiKZ4BkxxjvYi/ksEixTPR0Q== dependencies: tslib "^2.3.0" From 545180b88fb19289c64cbd353dbd5774872c47e8 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 25 Feb 2023 11:20:04 +0100 Subject: [PATCH 07/11] Feature/add reddit and umbrel logos to landing page (#1745) * Add Reddit and Umbrel logos * Update changelog --- CHANGELOG.md | 2 ++ .../src/app/pages/landing/landing-page.html | 16 ++++++++++++++++ .../src/app/pages/landing/landing-page.scss | 12 ++++++++++++ apps/client/src/assets/images/logo-reddit.svg | 7 +++++++ apps/client/src/assets/images/logo-umbrel.svg | 4 ++++ 5 files changed, 41 insertions(+) create mode 100644 apps/client/src/assets/images/logo-reddit.svg create mode 100644 apps/client/src/assets/images/logo-umbrel.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 02eb7be8d..13220027b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `COINGECKO` as a new data source type - Added support for data provider information to the position detail dialog - Added the configuration to publish a `linux/arm/v7` docker image +- Added _Reddit_ to the _As seen in_ section on the landing page +- Added _Umbrel_ to the _As seen in_ section on the landing page ### Changed diff --git a/apps/client/src/app/pages/landing/landing-page.html b/apps/client/src/app/pages/landing/landing-page.html index cb2fbd649..4ba24f77a 100644 --- a/apps/client/src/app/pages/landing/landing-page.html +++ b/apps/client/src/app/pages/landing/landing-page.html @@ -165,6 +165,14 @@ title="Product Hunt – The best new products in tech." >
+
+ +
+
+ +

Ghostfolio, the web-based personal + finance management software, is now available in the + Umbrel App Store, a + home server OS for self-hosting. +

+

+ In recent years, we have seen an increasing number of individuals + and organizations moving their data to the cloud. While cloud + computing has its benefits, such as accessibility and scalability, + it also comes with some concerns regarding data privacy and + security. However, there is an alternative to cloud computing that + provides the convenience of the cloud while giving you ownership and + control of your data: personal servers. +

+
+
+

Umbrel – A personal server OS for self-hosting

+

+ Umbrel + is an operating system based on + Docker that + allows you to run a personal server in your home. With it, you can + self-host open source apps directly from an integrated app store. + This means that you can discover self-hosted apps directly in the + Umbrel App Store + and install them in one click. You can get up and running Umbrel on + a Raspberry Pi 4, any Ubuntu / Debian system, or a VPS in only 5 + minutes. +

+

+ Umbrel offers numerous advantages for running a personal server in + your home, such as enhanced data privacy and security, ownership and + control of your data, and access to a diverse selection of + self-hosted apps. +

+
+
+

+ Ghostfolio – Track your portfolio without being tracked +

+

+ Keeping track of multiple assets can make managing your personal + finance a challenging task. However, there are tools available + beyond spreadsheets that can help you streamline the process and + make well-informed investment decisions based on data. +

+

+ Ghostfolio + is a modern open source web application designed to manage your + personal finance with ease and confidence. It presents your current + assets in real-time, including stocks, ETFs, cryptocurrencies, + commodities, and more. It allows you to track and analyze your + investments in one place. +

+

+ The application has a range of features such as real-time asset + tracking, data import and export and advanced portfolio analytics + tools. +

+
+
+

+ To participate in the ongoing development of Ghostfolio, please feel + free to reach out to us on our + Slack channel + or via Twitter + @ghostfolio_. We look forward to hearing from you! +

+
+
+
    +
  • + Announcement +
  • +
  • + App Store +
  • +
  • + Assets +
  • +
  • + Cloud +
  • +
  • + Commodity +
  • +
  • + Cryptocurrency +
  • +
  • + Debian +
  • +
  • + Development +
  • +
  • + Docker +
  • +
  • + ETF +
  • +
  • + Fintech +
  • +
  • + Ghostfolio +
  • +
  • + Home Server +
  • +
  • + Investing +
  • +
  • + Linux +
  • +
  • + Open Source +
  • +
  • + Operating System +
  • +
  • + OS +
  • +
  • + OSS +
  • +
  • + Personal Finance +
  • +
  • + Personal Server +
  • +
  • + Portfolio +
  • +
  • + Privacy +
  • +
  • + Raspberry Pi +
  • +
  • + Security +
  • +
  • + Software +
  • +
  • + Spreadsheet +
  • +
  • + Stocks +
  • +
  • + Ubuntu +
  • +
  • + Umbrel +
  • +
  • + VPS +
  • +
  • + Wealth Management +
  • +
+
+
+
+
+
diff --git a/apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.module.ts b/apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.module.ts new file mode 100644 index 000000000..b15ca1c2c --- /dev/null +++ b/apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.module.ts @@ -0,0 +1,13 @@ +import { CommonModule } from '@angular/common'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { GhostfolioMeetsUmbrelPageRoutingModule } from './ghostfolio-meets-umbrel-page-routing.module'; +import { GhostfolioMeetsUmbrelPageComponent } from './ghostfolio-meets-umbrel-page.component'; + +@NgModule({ + declarations: [GhostfolioMeetsUmbrelPageComponent], + imports: [CommonModule, GhostfolioMeetsUmbrelPageRoutingModule, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GhostfolioMeetsUmbrelPageModule {} diff --git a/apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.scss b/apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.scss new file mode 100644 index 000000000..5d4e87f30 --- /dev/null +++ b/apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/apps/client/src/app/pages/blog/blog-page.html b/apps/client/src/app/pages/blog/blog-page.html index 69b5000b9..0349eb168 100644 --- a/apps/client/src/app/pages/blog/blog-page.html +++ b/apps/client/src/app/pages/blog/blog-page.html @@ -2,6 +2,32 @@

Blog

+ + + + +
diff --git a/apps/client/src/assets/images/blog/ghostfolio-x-umbrel.png b/apps/client/src/assets/images/blog/ghostfolio-x-umbrel.png new file mode 100644 index 0000000000000000000000000000000000000000..7f491959730d45ea45737ac0bafe9473e01116f0 GIT binary patch literal 16324 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 XhB(>|QJj3(c1?`T&zJpq^Zx$<>;yUf literal 0 HcmV?d00001 diff --git a/apps/client/src/assets/sitemap.xml b/apps/client/src/assets/sitemap.xml index b64993b80..341181346 100644 --- a/apps/client/src/assets/sitemap.xml +++ b/apps/client/src/assets/sitemap.xml @@ -6,94 +6,98 @@ http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> https://ghostfol.io - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/de/blog - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/de/blog/2021/07/hallo-ghostfolio - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/de/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/de/pricing - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/about - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/about/changelog - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog/2021/07/hello-ghostfolio - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog/2022/01/ghostfolio-first-months-in-open-source - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog/2022/07/ghostfolio-meets-internet-identity - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog/2022/07/how-do-i-get-my-finances-in-order - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog/2022/08/500-stars-on-github - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog/2022/10/hacktoberfest-2022 - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog/2022/11/black-friday-2022 - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/blog/2022/12/the-importance-of-tracking-your-personal-finances - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 + + + https://ghostfol.io/en/blog/2023/02/ghostfolio-meets-umbrel + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/demo - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/faq - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/features - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/markets - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/pricing - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/register - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00 https://ghostfol.io/en/resources - 2023-01-30T00:00:00+00:00 + 2023-02-25T00:00:00+00:00