Browse Source

Merge branch 'ghostfolio:main' into main

pull/5859/head
Suyash sahu 2 days ago
committed by GitHub
parent
commit
ea3aed885b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      CHANGELOG.md
  2. 13
      README.md
  3. 79
      apps/api/src/app/endpoints/ai/ai.service.ts
  4. 24
      apps/client/src/app/pages/about/overview/about-overview-page.html
  5. 18
      apps/client/src/app/pages/resources/glossary/resources-glossary.component.html
  6. 4
      apps/client/src/app/pages/resources/guides/resources-guides.component.html
  7. 8
      apps/client/src/app/pages/resources/markets/resources-markets.component.html
  8. 2
      apps/client/src/app/pages/resources/overview/resources-overview.component.html

3
CHANGELOG.md

@ -10,10 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Added a close holding button to the holding detail dialog - Added a close holding button to the holding detail dialog
- Added the _Sponsors_ section to the about page
- Extended the user detail dialog in the users section of the admin control panel - Extended the user detail dialog in the users section of the admin control panel
### Changed ### Changed
- Refactored the generation of the holdings table in the _Copy AI prompt to clipboard for analysis_ action on the analysis page (experimental)
- Refactored the generation of the holdings table in the _Copy portfolio data to clipboard for AI prompt_ action on the analysis page (experimental)
- Improved the language localization for German (`de`) - Improved the language localization for German (`de`)
### Fixed ### Fixed

13
README.md

@ -297,7 +297,18 @@ Ghostfolio is **100% free** and **open source**. We encourage and support an act
Not sure what to work on? We have [some ideas](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22%20no%3Aassignee), even for [newcomers](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22%20no%3Aassignee). Please join the Ghostfolio [Slack](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) channel or post to [@ghostfolio\_](https://x.com/ghostfolio_) on _X_. We would love to hear from you. Not sure what to work on? We have [some ideas](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22%20no%3Aassignee), even for [newcomers](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22%20no%3Aassignee). Please join the Ghostfolio [Slack](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) channel or post to [@ghostfolio\_](https://x.com/ghostfolio_) on _X_. We would love to hear from you.
If you like to support this project, get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio). If you like to support this project, become a [**Sponsor**](https://github.com/sponsors/ghostfolio), get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio).
## Sponsors
<div align="center">
<p>
Browser testing via<br />
<a href="https://www.lambdatest.com?utm_medium=sponsor&utm_source=ghostfolio" target="_blank" title="LambdaTest - AI Powered Testing Tool">
<img alt="LambdaTest Logo" height="45" width="250" src="https://www.lambdatest.com/blue-logo.png" />
</a>
</p>
</div>
## Analytics ## Analytics

79
apps/api/src/app/endpoints/ai/ai.service.ts

@ -14,6 +14,27 @@ import type { ColumnDescriptor } from 'tablemark';
@Injectable() @Injectable()
export class AiService { export class AiService {
private static readonly HOLDINGS_TABLE_COLUMN_DEFINITIONS: ({
key:
| 'ALLOCATION_PERCENTAGE'
| 'ASSET_CLASS'
| 'ASSET_SUB_CLASS'
| 'CURRENCY'
| 'NAME'
| 'SYMBOL';
} & ColumnDescriptor)[] = [
{ key: 'NAME', name: 'Name' },
{ key: 'SYMBOL', name: 'Symbol' },
{ key: 'CURRENCY', name: 'Currency' },
{ key: 'ASSET_CLASS', name: 'Asset Class' },
{ key: 'ASSET_SUB_CLASS', name: 'Asset Sub Class' },
{
align: 'right',
key: 'ALLOCATION_PERCENTAGE',
name: 'Allocation in Percentage'
}
];
public constructor( public constructor(
private readonly portfolioService: PortfolioService, private readonly portfolioService: PortfolioService,
private readonly propertyService: PropertyService private readonly propertyService: PropertyService
@ -59,14 +80,10 @@ export class AiService {
userId userId
}); });
const holdingsTableColumns: ColumnDescriptor[] = [ const holdingsTableColumns: ColumnDescriptor[] =
{ name: 'Name' }, AiService.HOLDINGS_TABLE_COLUMN_DEFINITIONS.map(({ align, name }) => {
{ name: 'Symbol' }, return { name, align: align ?? 'left' };
{ name: 'Currency' }, });
{ name: 'Asset Class' },
{ name: 'Asset Sub Class' },
{ align: 'right', name: 'Allocation in Percentage' }
];
const holdingsTableRows = Object.values(holdings) const holdingsTableRows = Object.values(holdings)
.sort((a, b) => { .sort((a, b) => {
@ -78,17 +95,45 @@ export class AiService {
assetClass, assetClass,
assetSubClass, assetSubClass,
currency, currency,
name, name: label,
symbol symbol
}) => { }) => {
return { return AiService.HOLDINGS_TABLE_COLUMN_DEFINITIONS.reduce(
Name: name, (row, { key, name }) => {
Symbol: symbol, switch (key) {
Currency: currency, case 'ALLOCATION_PERCENTAGE':
'Asset Class': assetClass ?? '', row[name] = `${(allocationInPercentage * 100).toFixed(3)}%`;
'Asset Sub Class': assetSubClass ?? '', break;
'Allocation in Percentage': `${(allocationInPercentage * 100).toFixed(3)}%`
}; case 'ASSET_CLASS':
row[name] = assetClass ?? '';
break;
case 'ASSET_SUB_CLASS':
row[name] = assetSubClass ?? '';
break;
case 'CURRENCY':
row[name] = currency;
break;
case 'NAME':
row[name] = label;
break;
case 'SYMBOL':
row[name] = symbol;
break;
default:
row[name] = '';
break;
}
return row;
},
{} as Record<string, string>
);
} }
); );

24
apps/client/src/app/pages/about/overview/about-overview-page.html

@ -175,7 +175,7 @@
</div> </div>
</div> </div>
<div class="row"> <div class="mb-5 row">
<div <div
class="col-md-6 col-xs-12 my-2" class="col-md-6 col-xs-12 my-2"
[ngClass]="{ 'offset-md-3': hasPermissionForSubscription === false }" [ngClass]="{ 'offset-md-3': hasPermissionForSubscription === false }"
@ -201,4 +201,26 @@
</div> </div>
} }
</div> </div>
<div class="row">
<div class="col-12">
<h2 class="h4 mb-3">Sponsors</h2>
<div class="text-center">
<small>Browser testing via</small>
<br />
<a
href="https://www.lambdatest.com?utm_medium=sponsor&utm_source=ghostfolio"
target="_blank"
title="LambdaTest - AI Powered Testing Tool"
>
<img
alt="LambdaTest Logo"
height="45"
src="https://www.lambdatest.com/blue-logo.png"
width="250"
/>
</a>
</div>
</div>
</div>
</div> </div>

18
apps/client/src/app/pages/resources/glossary/resources-glossary.component.html

@ -5,7 +5,7 @@
<div> <div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Buy and Hold</h3> <h2 class="h5 mb-1 mt-0">Buy and Hold</h2>
<div class="mb-1"> <div class="mb-1">
Buy and hold is a passive investment strategy where you buy assets Buy and hold is a passive investment strategy where you buy assets
and hold them for a long period regardless of fluctuations in the and hold them for a long period regardless of fluctuations in the
@ -22,7 +22,7 @@
</div> </div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Deflation</h3> <h2 class="h5 mb-1 mt-0">Deflation</h2>
<div class="mb-1"> <div class="mb-1">
Deflation is a decrease of the general price level for goods and Deflation is a decrease of the general price level for goods and
services in an economy over a period of time. services in an economy over a period of time.
@ -38,7 +38,7 @@
</div> </div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Dollar-Cost Averaging (DCA)</h3> <h2 class="h5 mb-1 mt-0">Dollar-Cost Averaging (DCA)</h2>
<div class="mb-1"> <div class="mb-1">
Dollar-cost averaging is an investment strategy where you split Dollar-cost averaging is an investment strategy where you split
the total amount to be invested across periodic purchases of a the total amount to be invested across periodic purchases of a
@ -56,7 +56,7 @@
</div> </div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Financial Independence</h3> <h2 class="h5 mb-1 mt-0">Financial Independence</h2>
<div class="mb-1"> <div class="mb-1">
Financial independence is the status of having enough income, for Financial independence is the status of having enough income, for
example with a passive income like dividends, to cover your living example with a passive income like dividends, to cover your living
@ -73,7 +73,7 @@
</div> </div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">FIRE</h3> <h2 class="h5 mb-1 mt-0">FIRE</h2>
<div class="mb-1"> <div class="mb-1">
FIRE is a movement that promotes saving and investing to achieve FIRE is a movement that promotes saving and investing to achieve
financial independence and early retirement. financial independence and early retirement.
@ -85,7 +85,7 @@
</div> </div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Inflation</h3> <h2 class="h5 mb-1 mt-0">Inflation</h2>
<div class="mb-1"> <div class="mb-1">
Inflation is an increase of the general price level for goods and Inflation is an increase of the general price level for goods and
services in an economy over a period of time. services in an economy over a period of time.
@ -102,7 +102,7 @@
@if (hasPermissionForSubscription) { @if (hasPermissionForSubscription) {
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Personal Finance Tools</h3> <h2 class="h5 mb-1 mt-0">Personal Finance Tools</h2>
<div class="mb-1"> <div class="mb-1">
Personal finance tools are software applications that help Personal finance tools are software applications that help
manage your money, track expenses, set budgets, monitor manage your money, track expenses, set budgets, monitor
@ -118,7 +118,7 @@
} }
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Stagflation</h3> <h2 class="h5 mb-1 mt-0">Stagflation</h2>
<div class="mb-1"> <div class="mb-1">
Stagflation describes a situation in which there is a stagnant Stagflation describes a situation in which there is a stagnant
economy with high unemployment and high inflation. economy with high unemployment and high inflation.
@ -134,7 +134,7 @@
</div> </div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Stealth Wealth</h3> <h2 class="h5 mb-1 mt-0">Stealth Wealth</h2>
<div class="mb-1"> <div class="mb-1">
Stealth wealth is a lifestyle choice where you don’t openly show Stealth wealth is a lifestyle choice where you don’t openly show
off your wealth, but instead live quietly to maintain privacy and off your wealth, but instead live quietly to maintain privacy and

4
apps/client/src/app/pages/resources/guides/resources-guides.component.html

@ -5,7 +5,7 @@
<div class="mb-5"> <div class="mb-5">
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Boringly Getting Rich</h3> <h2 class="h5 mb-1 mt-0">Boringly Getting Rich</h2>
<div class="mb-1"> <div class="mb-1">
The <i>Boringly Getting Rich</i> guide supports you to get started The <i>Boringly Getting Rich</i> guide supports you to get started
with investing. It introduces a strategy utilizing a broadly with investing. It introduces a strategy utilizing a broadly
@ -21,7 +21,7 @@
</div> </div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">How do I get my finances in order?</h3> <h2 class="h5 mb-1 mt-0">How do I get my finances in order?</h2>
<div class="mb-1"> <div class="mb-1">
Before you can think of long-term investing, you have to get your Before you can think of long-term investing, you have to get your
finances in order. Learn how you can reach your financial goals finances in order. Learn how you can reach your financial goals

8
apps/client/src/app/pages/resources/markets/resources-markets.component.html

@ -3,7 +3,7 @@
<div class="mb-5"> <div class="mb-5">
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Crypto Coins Heatmap</h3> <h2 class="h5 mb-1 mt-0">Crypto Coins Heatmap</h2>
<div class="mb-1"> <div class="mb-1">
With the <i>Crypto Coins Heatmap</i> you can track the daily market With the <i>Crypto Coins Heatmap</i> you can track the daily market
movements of cryptocurrencies as a visual snapshot. movements of cryptocurrencies as a visual snapshot.
@ -17,7 +17,7 @@
</div> </div>
<div class="mb-4 media"> <div class="mb-4 media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Fear & Greed Index</h3> <h2 class="h5 mb-1 mt-0">Fear & Greed Index</h2>
<div class="mb-1"> <div class="mb-1">
The fear and greed index was developed by <i>CNNMoney</i> to measure The fear and greed index was developed by <i>CNNMoney</i> to measure
the primary emotions (fear and greed) that influence how much the primary emotions (fear and greed) that influence how much
@ -32,7 +32,7 @@
</div> </div>
<div class="media"> <div class="media">
<div class="mb-4 media"> <div class="mb-4 media">
<h3 class="h5 mt-0">Inflation Chart</h3> <h2 class="h5 mb-1 mt-0">Inflation Chart</h2>
<div class="mb-1"> <div class="mb-1">
<i>Inflation Chart</i> helps you find the intrinsic value of stock <i>Inflation Chart</i> helps you find the intrinsic value of stock
markets, stock prices, goods and services by adjusting them to the markets, stock prices, goods and services by adjusting them to the
@ -48,7 +48,7 @@
</div> </div>
<div class="media"> <div class="media">
<div class="media-body"> <div class="media-body">
<h3 class="h5 mt-0">Stock Heatmap</h3> <h2 class="h5 mb-1 mt-0">Stock Heatmap</h2>
<div class="mb-1"> <div class="mb-1">
With the <i>Stock Heatmap</i> you can track the daily market movements With the <i>Stock Heatmap</i> you can track the daily market movements
of stocks as a visual snapshot. of stocks as a visual snapshot.

2
apps/client/src/app/pages/resources/overview/resources-overview.component.html

@ -5,7 +5,7 @@
<div class="overview-list"> <div class="overview-list">
@for (item of overviewItems; track item) { @for (item of overviewItems; track item) {
<div class="mb-4"> <div class="mb-4">
<h3 class="h5 mt-0">{{ item.title }}</h3> <h2 class="h5 mb-1 mt-0">{{ item.title }}</h2>
<p class="mb-1">{{ item.description }}</p> <p class="mb-1">{{ item.description }}</p>
<a [routerLink]="item.routerLink">Explore {{ item.title }} →</a> <a [routerLink]="item.routerLink">Explore {{ item.title }} →</a>
</div> </div>

Loading…
Cancel
Save