-
Black Friday 2023
-
2023-11-18
+
Black Week 2023
+
2023-11-19
@@ -23,7 +23,7 @@
[enableLink]="false"
>
- annual plan with our exclusive Black Friday deal. Elevate your
+ annual plan with our exclusive Black Week deal. Elevate your
financial strategy with the power of Ghostfolio designed to give you
the full picture of your assets.
@@ -37,8 +37,8 @@
>
is a modern web application to manage personal finances. This Open
Source Software (OSS) dynamically aggregates your diverse assets
- including stocks, ETFs, cryptocurrencies, commodities, and more,
- presenting a comprehensive overview of your portfolio in real-time.
+ including stocks, ETFs, cryptocurrencies, commodities, etc. and
+ presents a comprehensive overview of your portfolio in real-time.
Empower yourself to make informed, data-driven investment decisions
with the robust analytics at your fingertips. Explore the numerous
features to enhance your
@@ -47,8 +47,8 @@
- Snap the limited Black Friday 2023 deal before it’s gone. For
- detailed information on plans and pricing, please visit our
+ Snap the limited Black Week 2023 deal before it’s gone. For detailed
+ information on plans and pricing, please visit our
pricing page .
@@ -65,6 +65,9 @@
Black Friday
+
+ Black Week
+
Cloud
@@ -148,7 +151,7 @@
aria-current="page"
class="active breadcrumb-item text-truncate"
>
- Black Friday 2023
+ Black Week 2023
diff --git a/apps/client/src/app/pages/blog/blog-page-routing.module.ts b/apps/client/src/app/pages/blog/blog-page-routing.module.ts
index 9f725960d..487f53f02 100644
--- a/apps/client/src/app/pages/blog/blog-page-routing.module.ts
+++ b/apps/client/src/app/pages/blog/blog-page-routing.module.ts
@@ -175,12 +175,12 @@ const routes: Routes = [
},
{
canActivate: [AuthGuard],
- path: '2023/11/black-friday-2023',
+ path: '2023/11/black-week-2023',
loadComponent: () =>
- import(
- './2023/11/black-friday-2023/black-friday-2023-page.component'
- ).then((c) => c.BlackFriday2023PageComponent),
- title: 'Black Friday 2023'
+ import('./2023/11/black-week-2023/black-week-2023-page.component').then(
+ (c) => c.BlackWeek2023PageComponent
+ ),
+ title: 'Black Week 2023'
}
];
diff --git a/apps/client/src/app/pages/blog/blog-page.html b/apps/client/src/app/pages/blog/blog-page.html
index 2bf207209..70bf771e3 100644
--- a/apps/client/src/app/pages/blog/blog-page.html
+++ b/apps/client/src/app/pages/blog/blog-page.html
@@ -18,11 +18,11 @@
-
Black Friday 2023
-
2023-11-17
+
Black Week 2023
+
2023-11-19
- {{ product1.name }}
+ Alternative
- {{ product2.name }}
+ App
- Alternative
+ Budgeting
- App
+ Community
- Community
+ Family Office
Fintech
+
+ {{ product1.name }}
+
Investment
@@ -280,9 +283,15 @@
Wealth
+
+ WealthTech
+
Wealth Management
+
+ {{ product2.name }}
+
diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/products.ts b/apps/client/src/app/pages/resources/personal-finance-tools/products.ts
index 0cd32adc3..93b945d27 100644
--- a/apps/client/src/app/pages/resources/personal-finance-tools/products.ts
+++ b/apps/client/src/app/pages/resources/personal-finance-tools/products.ts
@@ -6,10 +6,13 @@ import { BasilFinancePageComponent } from './products/basil-finance-page.compone
import { BeanvestPageComponent } from './products/beanvest-page.component';
import { CapitallyPageComponent } from './products/capitally-page.component';
import { CapMonPageComponent } from './products/capmon-page.component';
+import { CompoundPlanningPageComponent } from './products/compound-planning-page.component';
import { CopilotMoneyPageComponent } from './products/copilot-money-page.component';
+import { DeFiPageComponent } from './products/de.fi-page.component';
import { DeltaPageComponent } from './products/delta-page.component';
import { DivvyDiaryPageComponent } from './products/divvydiary-page.component';
import { EightFiguresPageComponent } from './products/eightfigures-page.component';
+import { EmpowerPageComponent } from './products/empower-page.component';
import { ExirioPageComponent } from './products/exirio-page.component';
import { FinaryPageComponent } from './products/finary-page.component';
import { FinWisePageComponent } from './products/finwise-page.component';
@@ -37,9 +40,11 @@ import { SnowballAnalyticsPageComponent } from './products/snowball-analytics-pa
import { StocklePageComponent } from './products/stockle-page.component';
import { StockMarketEyePageComponent } from './products/stockmarketeye-page.component';
import { SumioPageComponent } from './products/sumio-page.component';
+import { TillerPageComponent } from './products/tiller-page.component';
import { UtlunaPageComponent } from './products/utluna-page.component';
import { VyzerPageComponent } from './products/vyzer-page.component';
import { WealthicaPageComponent } from './products/wealthica-page.component';
+import { WhalPageComponent } from './products/whal-page.component';
import { YeekateePageComponent } from './products/yeekatee-page.component';
import { YnabPageComponent } from './products/ynab-page.component';
@@ -125,6 +130,14 @@ export const products: Product[] = [
note: 'CapMon.org has discontinued in 2023',
slogan: 'Next Generation Assets Tracking'
},
+ {
+ component: CompoundPlanningPageComponent,
+ founded: 2019,
+ key: 'compound-planning',
+ name: 'Compound Planning',
+ origin: $localize`United States`,
+ slogan: 'Modern Wealth & Investment Management'
+ },
{
component: CopilotMoneyPageComponent,
founded: 2019,
@@ -136,6 +149,14 @@ export const products: Product[] = [
pricingPerYear: '$70',
slogan: 'Do money better with Copilot'
},
+ {
+ component: DeFiPageComponent,
+ founded: 2020,
+ key: 'de.fi',
+ languages: ['English'],
+ name: 'De.Fi',
+ slogan: 'DeFi Portfolio Tracker'
+ },
{
component: DeltaPageComponent,
founded: 2017,
@@ -159,6 +180,16 @@ export const products: Product[] = [
pricingPerYear: '€65',
slogan: 'Your personal Dividend Calendar'
},
+ {
+ component: EmpowerPageComponent,
+ founded: 2009,
+ hasSelfHostingAbility: false,
+ key: 'empower',
+ name: 'Empower',
+ note: 'Originally named as Personal Capital',
+ origin: $localize`United States`,
+ slogan: 'Get answers to your money questions'
+ },
{
alias: '8figures',
component: EightFiguresPageComponent,
@@ -455,6 +486,17 @@ export const products: Product[] = [
pricingPerYear: '$20',
slogan: 'Sum up and build your wealth.'
},
+ {
+ component: TillerPageComponent,
+ founded: 2016,
+ hasFreePlan: false,
+ key: 'tiller',
+ name: 'Tiller',
+ origin: $localize`United States`,
+ pricingPerYear: '$79',
+ slogan:
+ 'Your financial life in a spreadsheet, automatically updated each day'
+ },
{
component: UtlunaPageComponent,
hasFreePlan: true,
@@ -489,14 +531,23 @@ export const products: Product[] = [
pricingPerYear: '$50',
slogan: 'See all your investments in one place'
},
+ {
+ component: WhalPageComponent,
+ key: 'whal',
+ name: 'Whal',
+ origin: $localize`United States`,
+ slogan: 'Manage your investments in one place'
+ },
{
component: YeekateePageComponent,
founded: 2021,
+ hasFreePlan: true,
hasSelfHostingAbility: false,
key: 'yeekatee',
+ languages: ['Deutsch', 'English', 'Español', 'Français', 'Italiano'],
name: 'yeekatee',
origin: $localize`Switzerland`,
- region: $localize`Switzerland`,
+ region: $localize`Global`,
slogan: 'Connect. Share. Invest.'
},
{
diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/products/compound-planning-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/products/compound-planning-page.component.ts
new file mode 100644
index 000000000..03a7317c4
--- /dev/null
+++ b/apps/client/src/app/pages/resources/personal-finance-tools/products/compound-planning-page.component.ts
@@ -0,0 +1,31 @@
+import { CommonModule } from '@angular/common';
+import { Component } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { RouterModule } from '@angular/router';
+
+import { products } from '../products';
+
+@Component({
+ host: { class: 'page' },
+ imports: [CommonModule, MatButtonModule, RouterModule],
+ selector: 'gf-compound-planning-page',
+ standalone: true,
+ styleUrls: ['../product-page-template.scss'],
+ templateUrl: '../product-page-template.html'
+})
+export class CompoundPlanningPageComponent {
+ public product1 = products.find(({ key }) => {
+ return key === 'ghostfolio';
+ });
+
+ public product2 = products.find(({ key }) => {
+ return key === 'compound-planning';
+ });
+
+ public routerLinkAbout = ['/' + $localize`about`];
+ public routerLinkFeatures = ['/' + $localize`features`];
+ public routerLinkResourcesPersonalFinanceTools = [
+ '/' + $localize`resources`,
+ 'personal-finance-tools'
+ ];
+}
diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/products/de.fi-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/products/de.fi-page.component.ts
new file mode 100644
index 000000000..7ece232d1
--- /dev/null
+++ b/apps/client/src/app/pages/resources/personal-finance-tools/products/de.fi-page.component.ts
@@ -0,0 +1,31 @@
+import { CommonModule } from '@angular/common';
+import { Component } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { RouterModule } from '@angular/router';
+
+import { products } from '../products';
+
+@Component({
+ host: { class: 'page' },
+ imports: [CommonModule, MatButtonModule, RouterModule],
+ selector: 'gf-de-fi-page',
+ standalone: true,
+ styleUrls: ['../product-page-template.scss'],
+ templateUrl: '../product-page-template.html'
+})
+export class DeFiPageComponent {
+ public product1 = products.find(({ key }) => {
+ return key === 'ghostfolio';
+ });
+
+ public product2 = products.find(({ key }) => {
+ return key === 'de.fi';
+ });
+
+ public routerLinkAbout = ['/' + $localize`about`];
+ public routerLinkFeatures = ['/' + $localize`features`];
+ public routerLinkResourcesPersonalFinanceTools = [
+ '/' + $localize`resources`,
+ 'personal-finance-tools'
+ ];
+}
diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/products/empower-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/products/empower-page.component.ts
new file mode 100644
index 000000000..0abdc5fbf
--- /dev/null
+++ b/apps/client/src/app/pages/resources/personal-finance-tools/products/empower-page.component.ts
@@ -0,0 +1,31 @@
+import { CommonModule } from '@angular/common';
+import { Component } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { RouterModule } from '@angular/router';
+
+import { products } from '../products';
+
+@Component({
+ host: { class: 'page' },
+ imports: [CommonModule, MatButtonModule, RouterModule],
+ selector: 'gf-empower-page',
+ standalone: true,
+ styleUrls: ['../product-page-template.scss'],
+ templateUrl: '../product-page-template.html'
+})
+export class EmpowerPageComponent {
+ public product1 = products.find(({ key }) => {
+ return key === 'ghostfolio';
+ });
+
+ public product2 = products.find(({ key }) => {
+ return key === 'empower';
+ });
+
+ public routerLinkAbout = ['/' + $localize`about`];
+ public routerLinkFeatures = ['/' + $localize`features`];
+ public routerLinkResourcesPersonalFinanceTools = [
+ '/' + $localize`resources`,
+ 'personal-finance-tools'
+ ];
+}
diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/products/tiller-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/products/tiller-page.component.ts
new file mode 100644
index 000000000..8f2218434
--- /dev/null
+++ b/apps/client/src/app/pages/resources/personal-finance-tools/products/tiller-page.component.ts
@@ -0,0 +1,31 @@
+import { CommonModule } from '@angular/common';
+import { Component } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { RouterModule } from '@angular/router';
+
+import { products } from '../products';
+
+@Component({
+ host: { class: 'page' },
+ imports: [CommonModule, MatButtonModule, RouterModule],
+ selector: 'gf-tiller-page',
+ standalone: true,
+ styleUrls: ['../product-page-template.scss'],
+ templateUrl: '../product-page-template.html'
+})
+export class TillerPageComponent {
+ public product1 = products.find(({ key }) => {
+ return key === 'ghostfolio';
+ });
+
+ public product2 = products.find(({ key }) => {
+ return key === 'tiller';
+ });
+
+ public routerLinkAbout = ['/' + $localize`about`];
+ public routerLinkFeatures = ['/' + $localize`features`];
+ public routerLinkResourcesPersonalFinanceTools = [
+ '/' + $localize`resources`,
+ 'personal-finance-tools'
+ ];
+}
diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/products/whal-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/products/whal-page.component.ts
new file mode 100644
index 000000000..c1a2ddc98
--- /dev/null
+++ b/apps/client/src/app/pages/resources/personal-finance-tools/products/whal-page.component.ts
@@ -0,0 +1,31 @@
+import { CommonModule } from '@angular/common';
+import { Component } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { RouterModule } from '@angular/router';
+
+import { products } from '../products';
+
+@Component({
+ host: { class: 'page' },
+ imports: [CommonModule, MatButtonModule, RouterModule],
+ selector: 'gf-whal-page',
+ standalone: true,
+ styleUrls: ['../product-page-template.scss'],
+ templateUrl: '../product-page-template.html'
+})
+export class WhalPageComponent {
+ public product1 = products.find(({ key }) => {
+ return key === 'ghostfolio';
+ });
+
+ public product2 = products.find(({ key }) => {
+ return key === 'whal';
+ });
+
+ public routerLinkAbout = ['/' + $localize`about`];
+ public routerLinkFeatures = ['/' + $localize`features`];
+ public routerLinkResourcesPersonalFinanceTools = [
+ '/' + $localize`resources`,
+ 'personal-finance-tools'
+ ];
+}
diff --git a/apps/client/src/assets/images/blog/black-friday-2023.jpg b/apps/client/src/assets/images/blog/black-friday-2023.jpg
deleted file mode 100644
index 45fe74149..000000000
Binary files a/apps/client/src/assets/images/blog/black-friday-2023.jpg and /dev/null differ
diff --git a/apps/client/src/assets/images/blog/black-week-2023.jpg b/apps/client/src/assets/images/blog/black-week-2023.jpg
new file mode 100644
index 000000000..5e9a77438
Binary files /dev/null and b/apps/client/src/assets/images/blog/black-week-2023.jpg differ
diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts
index a5500bee6..362d15b9c 100644
--- a/libs/common/src/lib/permissions.ts
+++ b/libs/common/src/lib/permissions.ts
@@ -35,7 +35,7 @@ export const permissions = {
updateTag: 'updateTag',
updateUserSettings: 'updateUserSettings',
updateViewMode: 'updateViewMode'
-};
+} as const;
export function getPermissions(aRole: Role): string[] {
switch (aRole) {
diff --git a/package.json b/package.json
index bfee5f054..f252aebfa 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ghostfolio",
- "version": "2.24.0",
+ "version": "2.25.1",
"homepage": "https://ghostfol.io",
"license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio",
@@ -81,7 +81,7 @@
"@nestjs/platform-express": "10.1.3",
"@nestjs/schedule": "3.0.2",
"@nestjs/serve-static": "4.0.0",
- "@prisma/client": "5.5.2",
+ "@prisma/client": "5.6.0",
"@simplewebauthn/browser": "8.3.1",
"@simplewebauthn/server": "8.3.2",
"@stripe/stripe-js": "1.47.0",
@@ -123,14 +123,14 @@
"passport": "0.6.0",
"passport-google-oauth20": "2.0.0",
"passport-jwt": "4.0.0",
- "prisma": "5.5.2",
+ "prisma": "5.6.0",
"reflect-metadata": "0.1.13",
"rxjs": "7.5.6",
"stripe": "11.12.0",
"svgmap": "2.6.0",
"twitter-api-v2": "1.14.2",
"uuid": "9.0.1",
- "yahoo-finance2": "2.8.1",
+ "yahoo-finance2": "2.9.0",
"zone.js": "0.13.1"
},
"devDependencies": {
diff --git a/yarn.lock b/yarn.lock
index 2ca5d7a14..bbc457a0f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4345,22 +4345,22 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
-"@prisma/client@5.5.2":
- version "5.5.2"
- resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.5.2.tgz#ce6389e7ad9e9cf0fc2a7c6a0032ad2e12a9fd61"
- integrity sha512-54XkqR8M+fxbzYqe+bIXimYnkkcGqgOh0dn0yWtIk6CQT4IUCAvNFNcQZwk2KqaLU+/1PHTSWrcHtx4XjluR5w==
+"@prisma/client@5.6.0":
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.6.0.tgz#1c15932250d5658fe0127e62faf4ecd96a877259"
+ integrity sha512-mUDefQFa1wWqk4+JhKPYq8BdVoFk9NFMBXUI8jAkBfQTtgx8WPx02U2HB/XbAz3GSUJpeJOKJQtNvaAIDs6sug==
dependencies:
- "@prisma/engines-version" "5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a"
+ "@prisma/engines-version" "5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee"
-"@prisma/engines-version@5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a":
- version "5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a"
- resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a.tgz#35cd59ed65ee1f9e333f4865ec86a4432c4d0a9c"
- integrity sha512-O+qHFnZvAyOFk1tUco2/VdiqS0ym42a3+6CYLScllmnpbyiTplgyLt2rK/B9BTjYkSHjrgMhkG47S0oqzdIckA==
+"@prisma/engines-version@5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee":
+ version "5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee"
+ resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee.tgz#57b003ab5e1ea1523b5cdd7f06b24ebcf5c7fd8c"
+ integrity sha512-UoFgbV1awGL/3wXuUK3GDaX2SolqczeeJ5b4FVec9tzeGbSWJboPSbT0psSrmgYAKiKnkOPFSLlH6+b+IyOwAw==
-"@prisma/engines@5.5.2":
- version "5.5.2"
- resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.5.2.tgz#fe0d2361a48c7d59568ccf0d35c75432594e1ac1"
- integrity sha512-Be5hoNF8k+lkB3uEMiCHbhbfF6aj1GnrTBnn5iYFT7GEr3TsOEp1soviEcBR0tYCgHbxjcIxJMhdbvxALJhAqg==
+"@prisma/engines@5.6.0":
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.6.0.tgz#82c445aa10633bbc0388aa2d6e411a0bd94c9439"
+ integrity sha512-Mt2q+GNJpU2vFn6kif24oRSBQv1KOkYaterQsi0k2/lA+dLvhRX6Lm26gon6PYHwUM8/h8KRgXIUMU0PCLB6bw==
"@radix-ui/number@1.0.1":
version "1.0.1"
@@ -15943,12 +15943,12 @@ pretty-hrtime@^1.0.3:
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==
-prisma@5.5.2:
- version "5.5.2"
- resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.5.2.tgz#54ad2f04f0dd4174f27128e4447013e8d75c4d69"
- integrity sha512-WQtG6fevOL053yoPl6dbHV+IWgKo25IRN4/pwAGqcWmg7CrtoCzvbDbN9fXUc7QS2KK0LimHIqLsaCOX/vHl8w==
+prisma@5.6.0:
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.6.0.tgz#ae2c27fdfb4d53be7f7dafb50d6b8b7f55c93aa5"
+ integrity sha512-EEaccku4ZGshdr2cthYHhf7iyvCcXqwJDvnoQRAJg5ge2Tzpv0e2BaMCp+CbbDUwoVTzwgOap9Zp+d4jFa2O9A==
dependencies:
- "@prisma/engines" "5.5.2"
+ "@prisma/engines" "5.6.0"
prismjs@^1.28.0:
version "1.29.0"
@@ -19115,10 +19115,10 @@ y18n@^5.0.5:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
-yahoo-finance2@2.8.1:
- version "2.8.1"
- resolved "https://registry.yarnpkg.com/yahoo-finance2/-/yahoo-finance2-2.8.1.tgz#6fd59a84ef16be46cfbcf8a4ac0d32b81ffe074a"
- integrity sha512-1125oJYLQ5Bz9ne5jU1eACdE15cBFWMzYm04fY201eiqiWMK+s6YCJVuUyJVgWgXVt61wwr88/QageNCl0w04A==
+yahoo-finance2@2.9.0:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/yahoo-finance2/-/yahoo-finance2-2.9.0.tgz#7842580de36606197f7d64897dd2e5e55b9371d3"
+ integrity sha512-Q1UhB5uA0Uj2bBcSDqsZLt0tCxoHwrWCuvu4NMUgioyN8dlpq8ppbdKhZlzTD9ipIyKSgqG5TT7IlwB1x6eHZA==
dependencies:
"@types/tough-cookie" "^4.0.2"
ajv "8.10.0"