Browse Source

Feature/refactor personal finance tools section (#3478)

* Refactoring
pull/3480/head
Thomas Kaul 9 months ago
committed by GitHub
parent
commit
cc92592d86
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 50
      apps/api/src/app/sitemap/sitemap.controller.ts
  2. 5
      apps/api/src/app/sitemap/sitemap.module.ts
  3. 1037
      apps/api/src/assets/sitemap.xml
  4. 17
      apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts
  5. 10
      apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts
  6. 16
      apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html
  7. 68
      apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
  8. 0
      apps/client/src/app/pages/resources/personal-finance-tools/product-page.html
  9. 0
      apps/client/src/app/pages/resources/personal-finance-tools/product-page.scss
  10. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/allinvestview-page.component.ts
  11. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/allvue-systems-page.component.ts
  12. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/altoo-page.component.ts
  13. 19
      apps/client/src/app/pages/resources/personal-finance-tools/products/base-page.component.ts
  14. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/basil-finance-page.component.ts
  15. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/beanvest-page.component.ts
  16. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/capitally-page.component.ts
  17. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/capmon-page.component.ts
  18. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/compound-planning-page.component.ts
  19. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/copilot-money-page.component.ts
  20. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/de.fi-page.component.ts
  21. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/delta-page.component.ts
  22. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/divvydiary-page.component.ts
  23. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/eightfigures-page.component.ts
  24. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/empower-page.component.ts
  25. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/exirio-page.component.ts
  26. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/fina-page.component.ts
  27. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/finary-page.component.ts
  28. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/finwise-page.component.ts
  29. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/folishare-page.component.ts
  30. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/getquin-page.component.ts
  31. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/gospatz-page.component.ts
  32. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/intuit-mint-page.component.ts
  33. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/justetf-page.component.ts
  34. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/koyfin-page.component.ts
  35. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/kubera-page.component.ts
  36. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/magnifi-page.component.ts
  37. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/markets.sh-page.component.ts
  38. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/maybe-finance-page.component.ts
  39. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/monarch-money-page.component.ts
  40. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/monse-page.component.ts
  41. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/navexa-page.component.ts
  42. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/parqet-page.component.ts
  43. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/plannix-page.component.ts
  44. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/portfolio-dividend-tracker-page.component.ts
  45. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/portfolio-visualizer-page.component.ts
  46. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/portseido-page.component.ts
  47. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/projectionlab-page.component.ts
  48. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/rocket-money-page.component.ts
  49. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/seeking-alpha-page.component.ts
  50. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/sharesight-page.component.ts
  51. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/simple-portfolio-page.component.ts
  52. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/snowball-analytics-page.component.ts
  53. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/stock-events-page.component.ts
  54. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/stockle-page.component.ts
  55. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/stockmarketeye-page.component.ts
  56. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/stonksfolio-page.component.ts
  57. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/sumio-page.component.ts
  58. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/tiller-page.component.ts
  59. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/utluna-page.component.ts
  60. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/vyzer-page.component.ts
  61. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/wallmine-page.component.ts
  62. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/wealthfolio-page.component.ts
  63. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/wealthica-page.component.ts
  64. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/whal-page.component.ts
  65. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/yeekatee-page.component.ts
  66. 32
      apps/client/src/app/pages/resources/personal-finance-tools/products/ynab-page.component.ts
  67. 12
      apps/client/src/locales/messages.es.xlf
  68. 102
      apps/client/src/locales/messages.fr.xlf
  69. 12
      apps/client/src/locales/messages.pt.xlf
  70. 1
      libs/common/src/lib/interfaces/product.ts
  71. 247
      libs/common/src/lib/personal-finance-tools.ts

50
apps/api/src/app/sitemap/sitemap.controller.ts

@ -1,8 +1,10 @@
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { import {
DATE_FORMAT, DATE_FORMAT,
getYesterday, getYesterday,
interpolate interpolate
} from '@ghostfolio/common/helper'; } from '@ghostfolio/common/helper';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { Controller, Get, Res, VERSION_NEUTRAL, Version } from '@nestjs/common'; import { Controller, Get, Res, VERSION_NEUTRAL, Version } from '@nestjs/common';
import { format } from 'date-fns'; import { format } from 'date-fns';
@ -14,7 +16,9 @@ import * as path from 'path';
export class SitemapController { export class SitemapController {
public sitemapXml = ''; public sitemapXml = '';
public constructor() { public constructor(
private readonly configurationService: ConfigurationService
) {
try { try {
this.sitemapXml = fs.readFileSync( this.sitemapXml = fs.readFileSync(
path.join(__dirname, 'assets', 'sitemap.xml'), path.join(__dirname, 'assets', 'sitemap.xml'),
@ -25,11 +29,51 @@ export class SitemapController {
@Get() @Get()
@Version(VERSION_NEUTRAL) @Version(VERSION_NEUTRAL)
public async flushCache(@Res() response: Response): Promise<void> { public async getSitemapXml(@Res() response: Response): Promise<void> {
const currentDate = format(getYesterday(), DATE_FORMAT);
response.setHeader('content-type', 'application/xml'); response.setHeader('content-type', 'application/xml');
response.send( response.send(
interpolate(this.sitemapXml, { interpolate(this.sitemapXml, {
currentDate: format(getYesterday(), DATE_FORMAT) currentDate,
personalFinanceTools: this.configurationService.get(
'ENABLE_FEATURE_SUBSCRIPTION'
)
? personalFinanceTools
.map(({ alias, key }) => {
return [
'<url>',
` <loc>https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-${alias ?? key}</loc>`,
` <lastmod>${currentDate}T00:00:00+00:00</lastmod>`,
'</url>',
'<url>',
` <loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-${alias ?? key}</loc>`,
` <lastmod>${currentDate}T00:00:00+00:00</lastmod>`,
'</url>',
'<url>',
` <loc>https://ghostfol.io/es/recursos/personal-finance-tools/alternativa-de-software-libre-a-${alias ?? key}</loc>`,
` <lastmod>${currentDate}T00:00:00+00:00</lastmod>`,
'</url>',
'<url>',
` <loc>https://ghostfol.io/fr/ressources/personal-finance-tools/alternative-open-source-a-${alias ?? key}</loc>`,
` <lastmod>${currentDate}T00:00:00+00:00</lastmod>`,
'</url>',
'<url>',
` <loc>https://ghostfol.io/it/risorse/personal-finance-tools/alternativa-open-source-a-${alias ?? key}</loc>`,
` <lastmod>${currentDate}T00:00:00+00:00</lastmod>`,
'</url>',
'<url>',
` <loc>https://ghostfol.io/nl/bronnen/personal-finance-tools/open-source-alternatief-voor-${alias ?? key}</loc>`,
` <lastmod>${currentDate}T00:00:00+00:00</lastmod>`,
'</url>',
'<url>',
` <loc>https://ghostfol.io/pt/recursos/personal-finance-tools/alternativa-de-software-livre-ao-${alias ?? key}</loc>`,
` <lastmod>${currentDate}T00:00:00+00:00</lastmod>`,
'</url>'
].join('\n');
})
.join('\n')
: ''
}) })
); );
} }

5
apps/api/src/app/sitemap/sitemap.module.ts

@ -1,8 +1,11 @@
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { SitemapController } from './sitemap.controller'; import { SitemapController } from './sitemap.controller';
@Module({ @Module({
controllers: [SitemapController] controllers: [SitemapController],
imports: [ConfigurationModule]
}) })
export class SitemapModule {} export class SitemapModule {}

1037
apps/api/src/assets/sitemap.xml

File diff suppressed because it is too large

17
apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts

@ -1,10 +1,10 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { PersonalFinanceToolsPageComponent } from './personal-finance-tools-page.component'; import { PersonalFinanceToolsPageComponent } from './personal-finance-tools-page.component';
import { products } from './products';
const routes: Routes = [ const routes: Routes = [
{ {
@ -13,16 +13,17 @@ const routes: Routes = [
path: '', path: '',
title: $localize`Personal Finance Tools` title: $localize`Personal Finance Tools`
}, },
...products ...personalFinanceTools.map(({ alias, key, name }) => {
.filter(({ key }) => {
return key !== 'ghostfolio';
})
.map(({ alias, component, key, name }) => {
return { return {
canActivate: [AuthGuard], canActivate: [AuthGuard],
path: $localize`open-source-alternative-to` + `-${alias ?? key}`, data: { key },
loadComponent: () => loadComponent: () =>
import(`./products/${key}-page.component`).then(() => component), import('./product-page.component').then(
({ GfProductPageComponent }) => {
return GfProductPageComponent;
}
),
path: $localize`open-source-alternative-to` + `-${alias ?? key}`,
title: $localize`Open Source Alternative to ${name}` title: $localize`Open Source Alternative to ${name}`
}; };
}) })

10
apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts

@ -1,8 +1,8 @@
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { Component, OnDestroy } from '@angular/core'; import { Component, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { products } from './products';
@Component({ @Component({
host: { class: 'page' }, host: { class: 'page' },
selector: 'gf-personal-finance-tools-page', selector: 'gf-personal-finance-tools-page',
@ -12,11 +12,7 @@ import { products } from './products';
export class PersonalFinanceToolsPageComponent implements OnDestroy { export class PersonalFinanceToolsPageComponent implements OnDestroy {
public pathAlternativeTo = $localize`open-source-alternative-to` + '-'; public pathAlternativeTo = $localize`open-source-alternative-to` + '-';
public pathResources = '/' + $localize`resources`; public pathResources = '/' + $localize`resources`;
public products = products public personalFinanceTools = personalFinanceTools.sort((a, b) => {
.filter(({ key }) => {
return key !== 'ghostfolio';
})
.sort((a, b) => {
return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }); return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
}); });
public routerLinkAbout = ['/' + $localize`about`]; public routerLinkAbout = ['/' + $localize`about`];

16
apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html

@ -18,25 +18,29 @@
with Ghostfolio. with Ghostfolio.
</p> </p>
</div> </div>
@for (product of products; track product) { @for (
personalFinanceTool of personalFinanceTools;
track personalFinanceTool
) {
<mat-card appearance="outlined" class="mb-3"> <mat-card appearance="outlined" class="mb-3">
<mat-card-content> <mat-card-content>
<div class="container p-0"> <div class="container p-0">
<div class="flex-nowrap no-gutters row"> <div class="flex-nowrap no-gutters row">
<a <a
class="d-flex overflow-hidden w-100" class="d-flex overflow-hidden w-100"
title="Compare Ghostfolio to {{ product.name }} - {{ title="Compare Ghostfolio to {{
product.slogan personalFinanceTool.name
}}" }} - {{ personalFinanceTool.slogan }}"
[routerLink]="[ [routerLink]="[
pathResources, pathResources,
'personal-finance-tools', 'personal-finance-tools',
pathAlternativeTo + (product.alias ?? product.key) pathAlternativeTo +
(personalFinanceTool.alias ?? personalFinanceTool.key)
]" ]"
> >
<div class="flex-grow-1 overflow-hidden"> <div class="flex-grow-1 overflow-hidden">
<div class="h6 m-0 text-truncate" i18n> <div class="h6 m-0 text-truncate" i18n>
Open Source Alternative to {{ product.name }} Open Source Alternative to {{ personalFinanceTool.name }}
</div> </div>
</div> </div>
<div class="align-items-center d-flex"> <div class="align-items-center d-flex">

68
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts

@ -0,0 +1,68 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { Product } from '@ghostfolio/common/interfaces';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { ActivatedRoute, RouterModule } from '@angular/router';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-product-page',
standalone: true,
styleUrls: ['./product-page.scss'],
templateUrl: './product-page.html'
})
export class GfProductPageComponent implements OnInit {
public key: string;
public price: number;
public product1: Product;
public product2: Product;
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
public constructor(
private dataService: DataService,
private route: ActivatedRoute
) {}
public ngOnInit() {
const { subscriptions } = this.dataService.fetchInfo();
this.price = subscriptions?.default?.price;
this.product1 = {
founded: 2021,
hasFreePlan: true,
hasSelfHostingAbility: true,
isOpenSource: true,
key: 'ghostfolio',
languages: [
'Deutsch',
'English',
'Español',
'Français',
'Italiano',
'Nederlands',
'Português',
'Türkçe',
'简体中文'
],
name: 'Ghostfolio',
origin: $localize`Switzerland`,
region: $localize`Global`,
slogan: 'Open Source Wealth Management',
useAnonymously: true
};
this.product2 = personalFinanceTools.find(({ key }) => {
return key === this.route.snapshot.data['key'];
});
}
}

0
apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html → apps/client/src/app/pages/resources/personal-finance-tools/product-page.html

0
apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.scss → apps/client/src/app/pages/resources/personal-finance-tools/product-page.scss

32
apps/client/src/app/pages/resources/personal-finance-tools/products/allinvestview-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-allinvestview-systems-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class AllInvestViewPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'allinvestview';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/allvue-systems-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-allvue-systems-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class AllvueSystemsPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'allvue-systems';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/altoo-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-altoo-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class AltooPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'altoo';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

19
apps/client/src/app/pages/resources/personal-finance-tools/products/base-page.component.ts

@ -1,19 +0,0 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'gf-base-product-page',
template: ''
})
export class BaseProductPageComponent implements OnInit {
public price: number;
public constructor(private dataService: DataService) {}
public ngOnInit() {
const { subscriptions } = this.dataService.fetchInfo();
this.price = subscriptions?.default?.price;
}
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/basil-finance-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-basil-finance-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class BasilFinancePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'basil-finance';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/beanvest-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-beanvest-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class BeanvestPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'beanvest';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/capitally-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-capitally-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class CapitallyPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'capitally';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/capmon-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-capmon-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class CapMonPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'capmon';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/compound-planning-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@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 extends BaseProductPageComponent {
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'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/copilot-money-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-copilot-money-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class CopilotMoneyPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'copilot-money';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/de.fi-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@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 extends BaseProductPageComponent {
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'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/delta-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-delta-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class DeltaPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'delta';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/divvydiary-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-divvy-diary-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class DivvyDiaryPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'divvydiary';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/eightfigures-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-eightfigures-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class EightFiguresPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'eightfigures';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/empower-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@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 extends BaseProductPageComponent {
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'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/exirio-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-exirio-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class ExirioPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'exirio';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/fina-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-fina-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class FinaPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'fina';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/finary-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-finary-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class FinaryPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'finary';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/finwise-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-finwise-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class FinWisePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'finwise';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/folishare-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-folishare-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class FolisharePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'folishare';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/getquin-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-getquin-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class GetquinPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'getquin';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/gospatz-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-gospatz-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class GoSpatzPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'gospatz';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/intuit-mint-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-intuit-mint-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class IntuitMintPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'intuit-mint';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/justetf-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-justetf-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class JustEtfPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'justetf';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/koyfin-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-koyfin-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class KoyfinPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'koyfin';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/kubera-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-kubera-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class KuberaPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'kubera';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/magnifi-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-magnifi-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class MagnifiPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'magnifi';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/markets.sh-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-markets-sh-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class MarketsShPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'markets.sh';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/maybe-finance-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-maybe-finance-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class MaybeFinancePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'maybe-finance';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/monarch-money-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-monarch-money-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class MonarchMoneyPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'monarch-money';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/monse-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-monse-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class MonsePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'monse';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/navexa-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-navexa-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class NavexaPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'navexa';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/parqet-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-parqet-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class ParqetPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'parqet';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/plannix-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-plannix-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class PlannixPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'plannix';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/portfolio-dividend-tracker-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-portfolio-dividend-tracker-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class PortfolioDividendTrackerPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'portfolio-dividend-tracker';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/portfolio-visualizer-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-portfolio-visualizer-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class PortfolioVisualizerPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'portfolio-visualizer';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/portseido-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-portseido-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class PortseidoPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'portseido';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/projectionlab-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-projection-lab-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class ProjectionLabPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'projectionlab';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/rocket-money-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-rocket-money-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class RocketMoneyPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'rocket-money';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/seeking-alpha-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-seeking-alpha-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SeekingAlphaPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'seeking-alpha';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/sharesight-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-sharesight-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SharesightPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'sharesight';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/simple-portfolio-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-simple-portfolio-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SimplePortfolioPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'simple-portfolio';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/snowball-analytics-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-snowball-analytics-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SnowballAnalyticsPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'snowball-analytics';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/stock-events-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-stock-events-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class StockEventsPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'stock-events';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/stockle-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-stockle-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class StocklePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'stockle';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/stockmarketeye-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-stockmarketeye-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class StockMarketEyePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'stockmarketeye';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/stonksfolio-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-stonksfolio-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class StonksfolioPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'stonksfolio';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/sumio-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-sumio-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SumioPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'sumio';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/tiller-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@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 extends BaseProductPageComponent {
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'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/utluna-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-utluna-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class UtlunaPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'utluna';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/vyzer-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-vyzer-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class VyzerPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'vyzer';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/wallmine-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-wallmine-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class WallminePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'wallmine';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/wealthfolio-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-wealthfolio-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class WealthfolioPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'wealthfolio';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/wealthica-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-wealthica-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class WealthicaPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'wealthica';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/whal-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@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 extends BaseProductPageComponent {
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'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/yeekatee-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-yeekatee-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class YeekateePageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'yeekatee';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

32
apps/client/src/app/pages/resources/personal-finance-tools/products/ynab-page.component.ts

@ -1,32 +0,0 @@
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';
import { BaseProductPageComponent } from './base-page.component';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-ynab-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class YnabPageComponent extends BaseProductPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'ynab';
});
public routerLinkAbout = ['/' + $localize`about`];
public routerLinkFeatures = ['/' + $localize`features`];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`resources`,
'personal-finance-tools'
];
}

12
apps/client/src/locales/messages.es.xlf

@ -5500,7 +5500,7 @@
</trans-unit> </trans-unit>
<trans-unit id="72aebdb25074909ed3dcb0866e277a1bef1a6916" datatype="html"> <trans-unit id="72aebdb25074909ed3dcb0866e277a1bef1a6916" datatype="html">
<source>✅ Yes</source> <source>✅ Yes</source>
<target state="new">✅ Yes</target> <target state="translated">✅ Sí</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">109</context> <context context-type="linenumber">109</context>
@ -7296,7 +7296,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ecdfd0aa6379102d20ffcf1e9e762edc54f148f4" datatype="html"> <trans-unit id="ecdfd0aa6379102d20ffcf1e9e762edc54f148f4" datatype="html">
<source>❌ No</source> <source>❌ No</source>
<target state="new">❌ No</target> <target state="translated">❌ No</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">111</context> <context context-type="linenumber">111</context>
@ -12216,7 +12216,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5afcc8902de9b8cc10cc02cdd606eb75d7786b65" datatype="html"> <trans-unit id="5afcc8902de9b8cc10cc02cdd606eb75d7786b65" datatype="html">
<source> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </source> <source> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </source>
<target state="new"> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </target> <target state="translated"> Alternativa de software libre a <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html</context>
<context context-type="linenumber">38</context> <context context-type="linenumber">38</context>
@ -12224,7 +12224,7 @@
</trans-unit> </trans-unit>
<trans-unit id="824385315623644802" datatype="html"> <trans-unit id="824385315623644802" datatype="html">
<source>Open Source Alternative to <x id="PH" equiv-text="name"/></source> <source>Open Source Alternative to <x id="PH" equiv-text="name"/></source>
<target state="new">Open Source Alternative to <x id="PH" equiv-text="name"/></target> <target state="translated">Alternativa de software libre a <x id="PH" equiv-text="name"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context>
<context context-type="linenumber">26</context> <context context-type="linenumber">26</context>
@ -12232,7 +12232,7 @@
</trans-unit> </trans-unit>
<trans-unit id="59aece48b4cff51f656b88e8f6c4061bb03410dc" datatype="html"> <trans-unit id="59aece48b4cff51f656b88e8f6c4061bb03410dc" datatype="html">
<source>The Open Source Alternative to</source> <source>The Open Source Alternative to</source>
<target state="new">The Open Source Alternative to</target> <target state="translated">La alternativa de software libre a</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">8</context> <context context-type="linenumber">8</context>
@ -13144,7 +13144,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5827613432388799534" datatype="html"> <trans-unit id="5827613432388799534" datatype="html">
<source>open-source-alternative-to</source> <source>open-source-alternative-to</source>
<target state="new">open-source-alternative-to</target> <target state="translated">alternativa-de-software-libre-a</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context>
<context context-type="linenumber">23</context> <context context-type="linenumber">23</context>

102
apps/client/src/locales/messages.fr.xlf

@ -3,7 +3,7 @@
<body> <body>
<trans-unit id="2ca05295d27e46c262b233252d1b19c27d95d07f" datatype="html"> <trans-unit id="2ca05295d27e46c262b233252d1b19c27d95d07f" datatype="html">
<source>The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term.</source> <source>The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term.</source>
<target state="translated">Le risque de perte en investissant peut être important. Il est déconseillé d&apos;investir de l&apos;argent dont vous pourriez avoir besoin à court terme.</target> <target state="translated">Le risque de perte en investissant peut être important. Il est déconseillé d’investir de l’argent dont vous pourriez avoir besoin à court terme.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/app.component.html</context> <context context-type="sourcefile">apps/client/src/app/app.component.html</context>
<context context-type="linenumber">182</context> <context context-type="linenumber">182</context>
@ -459,7 +459,7 @@
</trans-unit> </trans-unit>
<trans-unit id="db287ecf48f50d8a83c1dbdcee6282723b4cd9ad" datatype="html"> <trans-unit id="db287ecf48f50d8a83c1dbdcee6282723b4cd9ad" datatype="html">
<source>Asset Profiles</source> <source>Asset Profiles</source>
<target state="new">Profil d&apos;Actifs</target> <target state="new">Profil dActifs</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/assistant/assistant.html</context> <context context-type="sourcefile">libs/ui/src/lib/assistant/assistant.html</context>
<context context-type="linenumber">67</context> <context context-type="linenumber">67</context>
@ -627,7 +627,7 @@
</trans-unit> </trans-unit>
<trans-unit id="584c9433705e9bfdd2e7a9f0192690f453d36196" datatype="html"> <trans-unit id="584c9433705e9bfdd2e7a9f0192690f453d36196" datatype="html">
<source>Asset Class</source> <source>Asset Class</source>
<target state="translated">Classe d&apos;Actifs</target> <target state="translated">Classe dActifs</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">60</context> <context context-type="linenumber">60</context>
@ -651,7 +651,7 @@
</trans-unit> </trans-unit>
<trans-unit id="27fe3d097c64eaec7ff564358f80fb7ba795f484" datatype="html"> <trans-unit id="27fe3d097c64eaec7ff564358f80fb7ba795f484" datatype="html">
<source>Asset Sub Class</source> <source>Asset Sub Class</source>
<target state="translated">Sous-classe d&apos;Actifs</target> <target state="translated">Sous-classe dActifs</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">69</context> <context context-type="linenumber">69</context>
@ -695,7 +695,7 @@
</trans-unit> </trans-unit>
<trans-unit id="064d88bead9e71bd849ecaefd8b38cca8f195a88" datatype="html"> <trans-unit id="064d88bead9e71bd849ecaefd8b38cca8f195a88" datatype="html">
<source>Activities Count</source> <source>Activities Count</source>
<target state="translated">Nombre d&apos;Activités</target> <target state="translated">Nombre dActivités</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-market-data/admin-market-data.html</context>
<context context-type="linenumber">87</context> <context context-type="linenumber">87</context>
@ -895,7 +895,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ec03f5c28b327fc7ecfc4b20a0a7cf14a75843ff" datatype="html"> <trans-unit id="ec03f5c28b327fc7ecfc4b20a0a7cf14a75843ff" datatype="html">
<source>User Count</source> <source>User Count</source>
<target state="translated">Nombre d&apos;Utilisateurs</target> <target state="translated">Nombre dUtilisateurs</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
@ -903,7 +903,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ced0954194f098201837bb03b32441e4991b5193" datatype="html"> <trans-unit id="ced0954194f098201837bb03b32441e4991b5193" datatype="html">
<source>Activity Count</source> <source>Activity Count</source>
<target state="translated">Nombre d&apos;Activités</target> <target state="translated">Nombre dActivités</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">23</context> <context context-type="linenumber">23</context>
@ -1623,7 +1623,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5499742151525073097" datatype="html"> <trans-unit id="5499742151525073097" datatype="html">
<source>Upgrade Plan</source> <source>Upgrade Plan</source>
<target state="translated">Mettre à niveau l&apos;Abonnement</target> <target state="translated">Mettre à niveau lAbonnement</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/home-summary/home-summary.component.ts</context> <context context-type="sourcefile">apps/client/src/app/components/home-summary/home-summary.component.ts</context>
<context context-type="linenumber">115</context> <context context-type="linenumber">115</context>
@ -1651,7 +1651,7 @@
</trans-unit> </trans-unit>
<trans-unit id="8192718423057883427" datatype="html"> <trans-unit id="8192718423057883427" datatype="html">
<source>Savings Rate</source> <source>Savings Rate</source>
<target state="translated">Taux d&apos;Épargne</target> <target state="translated">Taux dÉpargne</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/investment-chart/investment-chart.component.ts</context> <context context-type="sourcefile">apps/client/src/app/components/investment-chart/investment-chart.component.ts</context>
<context context-type="linenumber">214</context> <context context-type="linenumber">214</context>
@ -1807,7 +1807,7 @@
</trans-unit> </trans-unit>
<trans-unit id="2201b2004bc4997a66f6f8ea2511a4e1311f3de1" datatype="html"> <trans-unit id="2201b2004bc4997a66f6f8ea2511a4e1311f3de1" datatype="html">
<source>Emergency Fund</source> <source>Emergency Fund</source>
<target state="translated">Fonds d&apos;Urgence</target> <target state="translated">Fonds dUrgence</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">190</context> <context context-type="linenumber">190</context>
@ -1823,7 +1823,7 @@
</trans-unit> </trans-unit>
<trans-unit id="8cce9d03787606e0052d19c2ae7e7fa5ff785e94" datatype="html"> <trans-unit id="8cce9d03787606e0052d19c2ae7e7fa5ff785e94" datatype="html">
<source>Buying Power</source> <source>Buying Power</source>
<target state="translated">Pouvoir d&apos;Achat</target> <target state="translated">Pouvoir dAchat</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">237</context> <context context-type="linenumber">237</context>
@ -1831,7 +1831,7 @@
</trans-unit> </trans-unit>
<trans-unit id="98fc3013bfcbf452b9f37bbfcdb77b9b882866e3" datatype="html"> <trans-unit id="98fc3013bfcbf452b9f37bbfcdb77b9b882866e3" datatype="html">
<source>Excluded from Analysis</source> <source>Excluded from Analysis</source>
<target state="translated">Exclus de l&apos;Analyse</target> <target state="translated">Exclus de lAnalyse</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">249</context> <context context-type="linenumber">249</context>
@ -1879,7 +1879,7 @@
</trans-unit> </trans-unit>
<trans-unit id="6785405835169448749" datatype="html"> <trans-unit id="6785405835169448749" datatype="html">
<source>Please enter the amount of your emergency fund:</source> <source>Please enter the amount of your emergency fund:</source>
<target state="translated">Veuillez entrer le montant de votre fonds d&apos;urgence :</target> <target state="translated">Veuillez entrer le montant de votre fonds durgence :</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts</context>
<context context-type="linenumber">57</context> <context context-type="linenumber">57</context>
@ -1947,7 +1947,7 @@
</trans-unit> </trans-unit>
<trans-unit id="6048892649018070225" datatype="html"> <trans-unit id="6048892649018070225" datatype="html">
<source>Today</source> <source>Today</source>
<target state="translated">Aujourd&apos;hui</target> <target state="translated">Aujourdhui</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/toggle/toggle.component.ts</context> <context context-type="sourcefile">apps/client/src/app/components/toggle/toggle.component.ts</context>
<context context-type="linenumber">22</context> <context context-type="linenumber">22</context>
@ -2031,7 +2031,7 @@
</trans-unit> </trans-unit>
<trans-unit id="7224997887539831269" datatype="html"> <trans-unit id="7224997887539831269" datatype="html">
<source>Oops! Something went wrong.</source> <source>Oops! Something went wrong.</source>
<target state="translated">Oups! Quelque chose s&apos;est mal passé.</target> <target state="translated">Oups! Quelque chose sest mal passé.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/core/http-response.interceptor.ts</context> <context context-type="sourcefile">apps/client/src/app/core/http-response.interceptor.ts</context>
<context context-type="linenumber">89</context> <context context-type="linenumber">89</context>
@ -2043,7 +2043,7 @@
</trans-unit> </trans-unit>
<trans-unit id="1579692722565712588" datatype="html"> <trans-unit id="1579692722565712588" datatype="html">
<source>Okay</source> <source>Okay</source>
<target state="translated">D&apos;accord</target> <target state="translated">Daccord</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/core/http-response.interceptor.ts</context> <context context-type="sourcefile">apps/client/src/app/core/http-response.interceptor.ts</context>
<context context-type="linenumber">92</context> <context context-type="linenumber">92</context>
@ -2143,7 +2143,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4420880039966769543" datatype="html"> <trans-unit id="4420880039966769543" datatype="html">
<source>Could not redeem coupon code</source> <source>Could not redeem coupon code</source>
<target state="translated">Le code promotionnel n&apos;a pas pu être appliqué</target> <target state="translated">Le code promotionnel na pas pu être appliqué</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/user-account-membership/user-account-membership.component.ts</context> <context context-type="sourcefile">apps/client/src/app/components/user-account-membership/user-account-membership.component.ts</context>
<context context-type="linenumber">121</context> <context context-type="linenumber">121</context>
@ -2299,7 +2299,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4402006eb2c97591dd8c87a5bd8f721fe9e4dc00" datatype="html"> <trans-unit id="4402006eb2c97591dd8c87a5bd8f721fe9e4dc00" datatype="html">
<source>Date and number format</source> <source>Date and number format</source>
<target state="translated">Format de date et d&apos;heure</target> <target state="translated">Format de date et dheure</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/user-account-settings/user-account-settings.html</context> <context context-type="sourcefile">apps/client/src/app/components/user-account-settings/user-account-settings.html</context>
<context context-type="linenumber">123</context> <context context-type="linenumber">123</context>
@ -2367,7 +2367,7 @@
</trans-unit> </trans-unit>
<trans-unit id="83c4d4d764d2e2725ab8e919ec16ac400e1f290a" datatype="html"> <trans-unit id="83c4d4d764d2e2725ab8e919ec16ac400e1f290a" datatype="html">
<source>User ID</source> <source>User ID</source>
<target state="translated">ID d&apos;utilisateur</target> <target state="translated">ID dutilisateur</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html</context> <context context-type="sourcefile">apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html</context>
<context context-type="linenumber">45</context> <context context-type="linenumber">45</context>
@ -2739,7 +2739,7 @@
</trans-unit> </trans-unit>
<trans-unit id="7500216440144530775" datatype="html"> <trans-unit id="7500216440144530775" datatype="html">
<source>Import has been completed</source> <source>Import has been completed</source>
<target state="translated">L&apos;import est terminé</target> <target state="translated">Limport est terminé</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context> <context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">128</context> <context context-type="linenumber">128</context>
@ -2835,7 +2835,7 @@
</trans-unit> </trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html"> <trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
<source>By Asset Class</source> <source>By Asset Class</source>
<target state="translated">Par Classe d&apos;Actifs</target> <target state="translated">Par Classe dActifs</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">86</context> <context context-type="linenumber">86</context>
@ -3070,8 +3070,8 @@
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3d14940af7de691ac27efb67bef3e974cbe3281c" datatype="html"> <trans-unit id="3d14940af7de691ac27efb67bef3e974cbe3281c" datatype="html">
<source> Hello, <x id="INTERPOLATION" equiv-text="{{ portfolioPublicDetails?.alias ?? &apos;someone&apos; }}"/> has shared a <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="&lt;strong&gt;"/>Portfolio<x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="&lt;/strong&gt;"/> with you! </source> <source> Hello, <x id="INTERPOLATION" equiv-text="{{ portfolioPublicDetails?.alias ?? ’someone’ }}"/> has shared a <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="&lt;strong&gt;"/>Portfolio<x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="&lt;/strong&gt;"/> with you! </source>
<target state="translated"> Bonjour, <x id="INTERPOLATION" equiv-text="{{ portfolioPublicDetails?.alias ?? &apos;someone&apos; }}"/> a partagé un <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="&lt;strong&gt;"/>Portefeuille<x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="&lt;/strong&gt;"/> avec vous ! </target> <target state="translated"> Bonjour, <x id="INTERPOLATION" equiv-text="{{ portfolioPublicDetails?.alias ?? ’someone’ }}"/> a partagé un <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="&lt;strong&gt;"/>Portefeuille<x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="&lt;/strong&gt;"/> avec vous ! </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
<context context-type="linenumber">4</context> <context context-type="linenumber">4</context>
@ -3187,7 +3187,7 @@
</trans-unit> </trans-unit>
<trans-unit id="495a0574bd9a3d619a8b16dd5b893c6f617beded" datatype="html"> <trans-unit id="495a0574bd9a3d619a8b16dd5b893c6f617beded" datatype="html">
<source>Oops, authentication has failed.</source> <source>Oops, authentication has failed.</source>
<target state="translated">Oups, l&apos;identification a échoué.</target> <target state="translated">Oups, lidentification a échoué.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/webauthn/webauthn-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/webauthn/webauthn-page.html</context>
<context context-type="linenumber">19</context> <context context-type="linenumber">19</context>
@ -3203,7 +3203,7 @@
</trans-unit> </trans-unit>
<trans-unit id="52cd09f578994ef3573e434007c1f9c86d3e8fc0" datatype="html"> <trans-unit id="52cd09f578994ef3573e434007c1f9c86d3e8fc0" datatype="html">
<source>Go back to Home Page</source> <source>Go back to Home Page</source>
<target state="translated">Retour à la Page d&apos;Accueil</target> <target state="translated">Retour à la Page dAccueil</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/webauthn/webauthn-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/webauthn/webauthn-page.html</context>
<context context-type="linenumber">31</context> <context context-type="linenumber">31</context>
@ -3319,7 +3319,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ba18e93c4572bfe6d14b2a3f333468b12f890e5d" datatype="html"> <trans-unit id="ba18e93c4572bfe6d14b2a3f333468b12f890e5d" datatype="html">
<source>Annual Interest Rate</source> <source>Annual Interest Rate</source>
<target state="translated">Taux d&apos;Intérêt Annuel</target> <target state="translated">Taux dIntérêt Annuel</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.html</context> <context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.html</context>
<context context-type="linenumber">21</context> <context context-type="linenumber">21</context>
@ -3387,7 +3387,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4574987680940794089" datatype="html"> <trans-unit id="4574987680940794089" datatype="html">
<source>Asset Class</source> <source>Asset Class</source>
<target state="translated">Classe d&apos;Actifs</target> <target state="translated">Classe dActifs</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context> <context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">6</context> <context context-type="linenumber">6</context>
@ -3395,7 +3395,7 @@
</trans-unit> </trans-unit>
<trans-unit id="7608037008789240367" datatype="html"> <trans-unit id="7608037008789240367" datatype="html">
<source>Asset Sub Class</source> <source>Asset Sub Class</source>
<target state="translated">Sous-classe d&apos;Actifs</target> <target state="translated">Sous-classe dActifs</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context> <context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">7</context> <context context-type="linenumber">7</context>
@ -3403,7 +3403,7 @@
</trans-unit> </trans-unit>
<trans-unit id="6268646680388419543" datatype="html"> <trans-unit id="6268646680388419543" datatype="html">
<source>Emergency Fund</source> <source>Emergency Fund</source>
<target state="translated">Fonds d&apos;Urgence</target> <target state="translated">Fonds dUrgence</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context> <context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
@ -3583,7 +3583,7 @@
</trans-unit> </trans-unit>
<trans-unit id="c004f99bac91f7dc28e87d458f80e5035ae99884" datatype="html"> <trans-unit id="c004f99bac91f7dc28e87d458f80e5035ae99884" datatype="html">
<source>Time to add your first activity.</source> <source>Time to add your first activity.</source>
<target state="translated">Il est temps d&apos;ajouter votre première activité.</target> <target state="translated">Il est temps dajouter votre première activité.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html</context> <context context-type="sourcefile">libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">12</context>
@ -3635,7 +3635,7 @@
</trans-unit> </trans-unit>
<trans-unit id="d82473cef3cd2258eab20223ffcdd5af0c0025cc" datatype="html"> <trans-unit id="d82473cef3cd2258eab20223ffcdd5af0c0025cc" datatype="html">
<source>Valid until</source> <source>Valid until</source>
<target state="translated">Valide jusqu&apos;au</target> <target state="translated">Valide jusquau</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/membership-card/membership-card.component.html</context> <context context-type="sourcefile">libs/ui/src/lib/membership-card/membership-card.component.html</context>
<context context-type="linenumber">23</context> <context context-type="linenumber">23</context>
@ -3715,7 +3715,7 @@
</trans-unit> </trans-unit>
<trans-unit id="280c5b1f5b5b748fbbb37bf7a12c37f41539c1ff" datatype="html"> <trans-unit id="280c5b1f5b5b748fbbb37bf7a12c37f41539c1ff" datatype="html">
<source> Are you an ambitious investor who needs the full picture? </source> <source> Are you an ambitious investor who needs the full picture? </source>
<target state="translated"> Êtes-vous un investisseur ambitieux qui a besoin d&apos;une vue complète ? </target> <target state="translated"> Êtes-vous un investisseur ambitieux qui a besoin dune vue complète ? </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html</context> <context context-type="sourcefile">apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">12</context>
@ -3771,7 +3771,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ae3ddc340195a1b9564574fd757c0cd1ab5cd765" datatype="html"> <trans-unit id="ae3ddc340195a1b9564574fd757c0cd1ab5cd765" datatype="html">
<source>and more Features...</source> <source>and more Features...</source>
<target state="translated">et d&apos;autres fonctionnalités...</target> <target state="translated">et dautres fonctionnalités...</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html</context> <context context-type="sourcefile">apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html</context>
<context context-type="linenumber">42</context> <context context-type="linenumber">42</context>
@ -3795,7 +3795,7 @@
</trans-unit> </trans-unit>
<trans-unit id="6dcab4069ec74eb21b38bd9f9678dc957c99618c" datatype="html"> <trans-unit id="6dcab4069ec74eb21b38bd9f9678dc957c99618c" datatype="html">
<source>Upgrade Plan</source> <source>Upgrade Plan</source>
<target state="translated">Mettre à niveau l&apos;Abonnement</target> <target state="translated">Mettre à niveau lAbonnement</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
<context context-type="linenumber">182</context> <context context-type="linenumber">182</context>
@ -3815,7 +3815,7 @@
</trans-unit> </trans-unit>
<trans-unit id="fd30b4e3189726798f09fa0ce875486cf50dda2d" datatype="html"> <trans-unit id="fd30b4e3189726798f09fa0ce875486cf50dda2d" datatype="html">
<source> For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. </source> <source> For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. </source>
<target state="translated"> Pour les investisseurs à l&apos;aise avec la technologie qui préfèrent héberger Ghostfolio sur leur propre infrastructure. </target> <target state="translated"> Pour les investisseurs à laise avec la technologie qui préfèrent héberger Ghostfolio sur leur propre infrastructure. </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">36</context> <context context-type="linenumber">36</context>
@ -3911,7 +3911,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5afce9034d974ae1e794d437885bf17b0ebf5a0c" datatype="html"> <trans-unit id="5afce9034d974ae1e794d437885bf17b0ebf5a0c" datatype="html">
<source> For ambitious investors who need the full picture of their financial assets. </source> <source> For ambitious investors who need the full picture of their financial assets. </source>
<target state="translated"> Pour les investisseurs ambitieux qui ont besoin d&apos;une vue complète de leurs actifs financiers. </target> <target state="translated"> Pour les investisseurs ambitieux qui ont besoin dune vue complète de leurs actifs financiers. </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">180</context> <context context-type="linenumber">180</context>
@ -3935,7 +3935,7 @@
</trans-unit> </trans-unit>
<trans-unit id="9fc169f3af45f638d4b304b828b640514b1d017c" datatype="html"> <trans-unit id="9fc169f3af45f638d4b304b828b640514b1d017c" datatype="html">
<source>It’s free.</source> <source>It’s free.</source>
<target state="translated">C&apos;est gratuit.</target> <target state="translated">Cest gratuit.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">294</context> <context context-type="linenumber">294</context>
@ -3979,7 +3979,7 @@
</trans-unit> </trans-unit>
<trans-unit id="310aea3a64b9279726e047f196c097f4f3268d09" datatype="html"> <trans-unit id="310aea3a64b9279726e047f196c097f4f3268d09" datatype="html">
<source>Savings Rate per Month</source> <source>Savings Rate per Month</source>
<target state="translated">Taux d&apos;Épargne mensuel</target> <target state="translated">Taux dÉpargne mensuel</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.html</context> <context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.html</context>
<context context-type="linenumber">10</context> <context context-type="linenumber">10</context>
@ -4051,7 +4051,7 @@
</trans-unit> </trans-unit>
<trans-unit id="f15e6e0a8fb2412d0fc8c40bc2946ccac969f491" datatype="html"> <trans-unit id="f15e6e0a8fb2412d0fc8c40bc2946ccac969f491" datatype="html">
<source>Oops! Could not get the historical exchange rate from</source> <source>Oops! Could not get the historical exchange rate from</source>
<target state="translated">Oups ! Nous n&apos;avons pas pu obtenir le taux de change historique à partir de</target> <target state="translated">Oups ! Nous navons pas pu obtenir le taux de change historique à partir de</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context> <context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
<context context-type="linenumber">292</context> <context context-type="linenumber">292</context>
@ -4095,7 +4095,7 @@
</trans-unit> </trans-unit>
<trans-unit id="e5580416a35e85e0ce48cf447c45043386d1027f" datatype="html"> <trans-unit id="e5580416a35e85e0ce48cf447c45043386d1027f" datatype="html">
<source>Renew Plan</source> <source>Renew Plan</source>
<target state="translated">Renouveler l&apos;Abonnement</target> <target state="translated">Renouveler lAbonnement</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
<context context-type="linenumber">190</context> <context context-type="linenumber">190</context>
@ -4111,7 +4111,7 @@
</trans-unit> </trans-unit>
<trans-unit id="de0d77a5255f97548d2b579f78c20c911a71820f" datatype="html"> <trans-unit id="de0d77a5255f97548d2b579f78c20c911a71820f" datatype="html">
<source> Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. </source> <source> Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. </source>
<target state="new"> Notre offre Ghostfolio Premium cloud est la manière la plus simple de débuter. Grâce au temps qu&apos;elle économise, ce sera la meilleure option pour la plupart des gens. Les revenus sont utilisés pour couvrir les frais d&apos;infrastructures et financer le développement continu de Ghostfolio. </target> <target state="new"> Notre offre Ghostfolio Premium cloud est la manière la plus simple de débuter. Grâce au temps quelle économise, ce sera la meilleure option pour la plupart des gens. Les revenus sont utilisés pour couvrir les frais dinfrastructures et financer le développement continu de Ghostfolio. </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">6</context> <context context-type="linenumber">6</context>
@ -4127,7 +4127,7 @@
</trans-unit> </trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html"> <trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
<source>Delete User</source> <source>Delete User</source>
<target state="translated">Supprimer l&apos;Utilisateur</target> <target state="translated">Supprimer lUtilisateur</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">232</context> <context context-type="linenumber">232</context>
@ -4143,7 +4143,7 @@
</trans-unit> </trans-unit>
<trans-unit id="166ccc92e1aa598f9056a260be209a0bab64d37a" datatype="html"> <trans-unit id="166ccc92e1aa598f9056a260be209a0bab64d37a" datatype="html">
<source>By ETF Provider</source> <source>By ETF Provider</source>
<target state="translated">Par Émetteur d&apos;ETF</target> <target state="translated">Par Émetteur dETF</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">314</context> <context context-type="linenumber">314</context>
@ -4215,7 +4215,7 @@
</trans-unit> </trans-unit>
<trans-unit id="dff74da4ffb45a2fd54f31f9db9da66f7012a702" datatype="html"> <trans-unit id="dff74da4ffb45a2fd54f31f9db9da66f7012a702" datatype="html">
<source> Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: </source> <source> Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: </source>
<target state="translated"> Mettez à niveau vers Ghostfolio Premium aujourd&apos;hui et gagnez accès à des fonctionnalités exclusives pour améliorer votre expérience d&apos;investissement: </target> <target state="translated"> Mettez à niveau vers Ghostfolio Premium aujourd’hui et gagnez accès à des fonctionnalités exclusives pour améliorer votre expérience d’investissement: </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html</context> <context context-type="sourcefile">apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">15</context>
@ -4223,7 +4223,7 @@
</trans-unit> </trans-unit>
<trans-unit id="8b17e00983a474a52d16bd139e180303703f01ff" datatype="html"> <trans-unit id="8b17e00983a474a52d16bd139e180303703f01ff" datatype="html">
<source> Get the tools to effectively manage your finances and refine your personal investment strategy. </source> <source> Get the tools to effectively manage your finances and refine your personal investment strategy. </source>
<target state="translated"> Obtenez les outils pour gérer efficacement vos finances et affinez votre stratégie d&apos;investissement personnelle. </target> <target state="translated"> Obtenez les outils pour gérer efficacement vos finances et affinez votre stratégie dinvestissement personnelle. </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html</context> <context context-type="sourcefile">apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html</context>
<context context-type="linenumber">45</context> <context context-type="linenumber">45</context>
@ -5499,7 +5499,7 @@
</trans-unit> </trans-unit>
<trans-unit id="72aebdb25074909ed3dcb0866e277a1bef1a6916" datatype="html"> <trans-unit id="72aebdb25074909ed3dcb0866e277a1bef1a6916" datatype="html">
<source>✅ Yes</source> <source>✅ Yes</source>
<target state="new">✅ Yes</target> <target state="translated">✅ Oui</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">109</context> <context context-type="linenumber">109</context>
@ -7295,7 +7295,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ecdfd0aa6379102d20ffcf1e9e762edc54f148f4" datatype="html"> <trans-unit id="ecdfd0aa6379102d20ffcf1e9e762edc54f148f4" datatype="html">
<source>❌ No</source> <source>❌ No</source>
<target state="new">❌ No</target> <target state="translated">❌ Non</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">111</context> <context context-type="linenumber">111</context>
@ -12215,7 +12215,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5afcc8902de9b8cc10cc02cdd606eb75d7786b65" datatype="html"> <trans-unit id="5afcc8902de9b8cc10cc02cdd606eb75d7786b65" datatype="html">
<source> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </source> <source> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </source>
<target state="new"> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </target> <target state="translated"> Alternative open source à <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html</context>
<context context-type="linenumber">38</context> <context context-type="linenumber">38</context>
@ -12223,7 +12223,7 @@
</trans-unit> </trans-unit>
<trans-unit id="824385315623644802" datatype="html"> <trans-unit id="824385315623644802" datatype="html">
<source>Open Source Alternative to <x id="PH" equiv-text="name"/></source> <source>Open Source Alternative to <x id="PH" equiv-text="name"/></source>
<target state="new">Open Source Alternative to <x id="PH" equiv-text="name"/></target> <target state="translated">Alternative open source à <x id="PH" equiv-text="name"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context>
<context context-type="linenumber">26</context> <context context-type="linenumber">26</context>
@ -12231,7 +12231,7 @@
</trans-unit> </trans-unit>
<trans-unit id="59aece48b4cff51f656b88e8f6c4061bb03410dc" datatype="html"> <trans-unit id="59aece48b4cff51f656b88e8f6c4061bb03410dc" datatype="html">
<source>The Open Source Alternative to</source> <source>The Open Source Alternative to</source>
<target state="new">The Open Source Alternative to</target> <target state="translated">L’alternative open source à</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">8</context> <context context-type="linenumber">8</context>
@ -13143,7 +13143,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5827613432388799534" datatype="html"> <trans-unit id="5827613432388799534" datatype="html">
<source>open-source-alternative-to</source> <source>open-source-alternative-to</source>
<target state="new">open-source-alternative-to</target> <target state="translated">alternative-open-source-a</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context>
<context context-type="linenumber">23</context> <context context-type="linenumber">23</context>

12
apps/client/src/locales/messages.pt.xlf

@ -5499,7 +5499,7 @@
</trans-unit> </trans-unit>
<trans-unit id="72aebdb25074909ed3dcb0866e277a1bef1a6916" datatype="html"> <trans-unit id="72aebdb25074909ed3dcb0866e277a1bef1a6916" datatype="html">
<source>✅ Yes</source> <source>✅ Yes</source>
<target state="new">✅ Yes</target> <target state="translated">✅ Sim</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">109</context> <context context-type="linenumber">109</context>
@ -7295,7 +7295,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ecdfd0aa6379102d20ffcf1e9e762edc54f148f4" datatype="html"> <trans-unit id="ecdfd0aa6379102d20ffcf1e9e762edc54f148f4" datatype="html">
<source>❌ No</source> <source>❌ No</source>
<target state="new">❌ No</target> <target state="translated">❌ Não</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">111</context> <context context-type="linenumber">111</context>
@ -12215,7 +12215,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5afcc8902de9b8cc10cc02cdd606eb75d7786b65" datatype="html"> <trans-unit id="5afcc8902de9b8cc10cc02cdd606eb75d7786b65" datatype="html">
<source> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </source> <source> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </source>
<target state="new"> Open Source Alternative to <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </target> <target state="translated"> Alternativa de software livre ao <x id="INTERPOLATION" equiv-text="{{ product.name }}"/> </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html</context>
<context context-type="linenumber">38</context> <context context-type="linenumber">38</context>
@ -12223,7 +12223,7 @@
</trans-unit> </trans-unit>
<trans-unit id="824385315623644802" datatype="html"> <trans-unit id="824385315623644802" datatype="html">
<source>Open Source Alternative to <x id="PH" equiv-text="name"/></source> <source>Open Source Alternative to <x id="PH" equiv-text="name"/></source>
<target state="new">Open Source Alternative to <x id="PH" equiv-text="name"/></target> <target state="translated">Alternativa de software livre ao <x id="PH" equiv-text="name"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context>
<context context-type="linenumber">26</context> <context context-type="linenumber">26</context>
@ -12231,7 +12231,7 @@
</trans-unit> </trans-unit>
<trans-unit id="59aece48b4cff51f656b88e8f6c4061bb03410dc" datatype="html"> <trans-unit id="59aece48b4cff51f656b88e8f6c4061bb03410dc" datatype="html">
<source>The Open Source Alternative to</source> <source>The Open Source Alternative to</source>
<target state="new">The Open Source Alternative to</target> <target state="translated">A alternativa de software livre ao</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page-template.html</context>
<context context-type="linenumber">8</context> <context context-type="linenumber">8</context>
@ -13143,7 +13143,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5827613432388799534" datatype="html"> <trans-unit id="5827613432388799534" datatype="html">
<source>open-source-alternative-to</source> <source>open-source-alternative-to</source>
<target state="new">open-source-alternative-to</target> <target state="translated">alternativa-de-software-livre-ao</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context> <context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts</context>
<context context-type="linenumber">23</context> <context context-type="linenumber">23</context>

1
libs/common/src/lib/interfaces/product.ts

@ -1,6 +1,5 @@
export interface Product { export interface Product {
alias?: string; alias?: string;
component: any;
founded?: number; founded?: number;
hasFreePlan?: boolean; hasFreePlan?: boolean;
hasSelfHostingAbility?: boolean; hasSelfHostingAbility?: boolean;

247
apps/client/src/app/pages/resources/personal-finance-tools/products.ts → libs/common/src/lib/personal-finance-tools.ts

@ -1,89 +1,7 @@
import { Product } from '@ghostfolio/common/interfaces'; import { Product } from '@ghostfolio/common/interfaces';
import { AllInvestViewPageComponent } from './products/allinvestview-page.component'; export const personalFinanceTools: Product[] = [
import { AllvueSystemsPageComponent } from './products/allvue-systems-page.component';
import { AltooPageComponent } from './products/altoo-page.component';
import { BasilFinancePageComponent } from './products/basil-finance-page.component';
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 { FinaPageComponent } from './products/fina-page.component';
import { FinaryPageComponent } from './products/finary-page.component';
import { FinWisePageComponent } from './products/finwise-page.component';
import { FolisharePageComponent } from './products/folishare-page.component';
import { GetquinPageComponent } from './products/getquin-page.component';
import { GoSpatzPageComponent } from './products/gospatz-page.component';
import { IntuitMintPageComponent } from './products/intuit-mint-page.component';
import { JustEtfPageComponent } from './products/justetf-page.component';
import { KoyfinPageComponent } from './products/koyfin-page.component';
import { KuberaPageComponent } from './products/kubera-page.component';
import { MagnifiPageComponent } from './products/magnifi-page.component';
import { MarketsShPageComponent } from './products/markets.sh-page.component';
import { MaybeFinancePageComponent } from './products/maybe-finance-page.component';
import { MonarchMoneyPageComponent } from './products/monarch-money-page.component';
import { MonsePageComponent } from './products/monse-page.component';
import { NavexaPageComponent } from './products/navexa-page.component';
import { ParqetPageComponent } from './products/parqet-page.component';
import { PlannixPageComponent } from './products/plannix-page.component';
import { PortfolioDividendTrackerPageComponent } from './products/portfolio-dividend-tracker-page.component';
import { PortfolioVisualizerPageComponent } from './products/portfolio-visualizer-page.component';
import { PortseidoPageComponent } from './products/portseido-page.component';
import { ProjectionLabPageComponent } from './products/projectionlab-page.component';
import { RocketMoneyPageComponent } from './products/rocket-money-page.component';
import { SeekingAlphaPageComponent } from './products/seeking-alpha-page.component';
import { SharesightPageComponent } from './products/sharesight-page.component';
import { SimplePortfolioPageComponent } from './products/simple-portfolio-page.component';
import { SnowballAnalyticsPageComponent } from './products/snowball-analytics-page.component';
import { StockEventsPageComponent } from './products/stock-events-page.component';
import { StocklePageComponent } from './products/stockle-page.component';
import { StockMarketEyePageComponent } from './products/stockmarketeye-page.component';
import { StonksfolioPageComponent } from './products/stonksfolio-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 { WallminePageComponent } from './products/wallmine-page.component';
import { WealthfolioPageComponent } from './products/wealthfolio-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';
export const products: Product[] = [
{
component: undefined,
founded: 2021,
hasFreePlan: true,
hasSelfHostingAbility: true,
isOpenSource: true,
key: 'ghostfolio',
languages: [
'Deutsch',
'English',
'Español',
'Français',
'Italiano',
'Nederlands',
'Português',
'Türkçe',
'简体中文'
],
name: 'Ghostfolio',
origin: $localize`Switzerland`,
region: $localize`Global`,
slogan: 'Open Source Wealth Management',
useAnonymously: true
},
{ {
component: AllInvestViewPageComponent,
founded: 2023, founded: 2023,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'allinvestview', key: 'allinvestview',
@ -92,26 +10,23 @@ export const products: Product[] = [
slogan: 'All your Investments in One View' slogan: 'All your Investments in One View'
}, },
{ {
component: AllvueSystemsPageComponent,
founded: 2019, founded: 2019,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'allvue-systems', key: 'allvue-systems',
name: 'Allvue Systems', name: 'Allvue Systems',
origin: $localize`United States`, origin: `United States`,
slogan: 'Investment Software Suite' slogan: 'Investment Software Suite'
}, },
{ {
component: AltooPageComponent,
founded: 2017, founded: 2017,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'altoo', key: 'altoo',
name: 'Altoo Wealth Platform', name: 'Altoo Wealth Platform',
origin: $localize`Switzerland`, origin: `Switzerland`,
slogan: 'Simplicity for Complex Wealth' slogan: 'Simplicity for Complex Wealth'
}, },
{ {
component: BasilFinancePageComponent,
founded: 2022, founded: 2022,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
@ -120,56 +35,50 @@ export const products: Product[] = [
slogan: 'The ultimate solution for tracking and managing your investments' slogan: 'The ultimate solution for tracking and managing your investments'
}, },
{ {
component: BeanvestPageComponent,
founded: 2020, founded: 2020,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'beanvest', key: 'beanvest',
name: 'Beanvest', name: 'Beanvest',
origin: $localize`France`, origin: `France`,
pricingPerYear: '$100', pricingPerYear: '$100',
slogan: 'Stock Portfolio Tracker for Smart Investors' slogan: 'Stock Portfolio Tracker for Smart Investors'
}, },
{ {
component: CapitallyPageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'capitally', key: 'capitally',
name: 'Capitally', name: 'Capitally',
origin: $localize`Poland`, origin: `Poland`,
pricingPerYear: '€50', pricingPerYear: '€50',
slogan: 'Optimize your investments performance' slogan: 'Optimize your investments performance'
}, },
{ {
component: CapMonPageComponent,
founded: 2022, founded: 2022,
key: 'capmon', key: 'capmon',
name: 'CapMon.org', name: 'CapMon.org',
origin: $localize`Germany`, origin: `Germany`,
note: 'CapMon.org has discontinued in 2023', note: 'CapMon.org has discontinued in 2023',
slogan: 'Next Generation Assets Tracking' slogan: 'Next Generation Assets Tracking'
}, },
{ {
component: CompoundPlanningPageComponent,
founded: 2019, founded: 2019,
key: 'compound-planning', key: 'compound-planning',
name: 'Compound Planning', name: 'Compound Planning',
origin: $localize`United States`, origin: `United States`,
slogan: 'Modern Wealth & Investment Management' slogan: 'Modern Wealth & Investment Management'
}, },
{ {
component: CopilotMoneyPageComponent,
founded: 2019, founded: 2019,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'copilot-money', key: 'copilot-money',
name: 'Copilot Money', name: 'Copilot Money',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$70', pricingPerYear: '$70',
slogan: 'Do money better with Copilot' slogan: 'Do money better with Copilot'
}, },
{ {
component: DeFiPageComponent,
founded: 2020, founded: 2020,
key: 'de.fi', key: 'de.fi',
languages: ['English'], languages: ['English'],
@ -177,215 +86,195 @@ export const products: Product[] = [
slogan: 'DeFi Portfolio Tracker' slogan: 'DeFi Portfolio Tracker'
}, },
{ {
component: DeltaPageComponent,
founded: 2017, founded: 2017,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'delta', key: 'delta',
name: 'Delta Investment Tracker', name: 'Delta Investment Tracker',
note: 'Acquired by eToro', note: 'Acquired by eToro',
origin: $localize`Belgium`, origin: `Belgium`,
slogan: 'The app to track all your investments. Make smart moves only.' slogan: 'The app to track all your investments. Make smart moves only.'
}, },
{ {
component: DivvyDiaryPageComponent,
founded: 2019, founded: 2019,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'divvydiary', key: 'divvydiary',
languages: ['Deutsch', 'English'], languages: ['Deutsch', 'English'],
name: 'DivvyDiary', name: 'DivvyDiary',
origin: $localize`Germany`, origin: `Germany`,
pricingPerYear: '€65', pricingPerYear: '€65',
slogan: 'Your personal Dividend Calendar' slogan: 'Your personal Dividend Calendar'
}, },
{ {
component: EmpowerPageComponent,
founded: 2009, founded: 2009,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'empower', key: 'empower',
name: 'Empower', name: 'Empower',
note: 'Originally named as Personal Capital', note: 'Originally named as Personal Capital',
origin: $localize`United States`, origin: `United States`,
slogan: 'Get answers to your money questions' slogan: 'Get answers to your money questions'
}, },
{ {
alias: '8figures', alias: '8figures',
component: EightFiguresPageComponent,
founded: 2022, founded: 2022,
key: 'eightfigures', key: 'eightfigures',
name: '8FIGURES', name: '8FIGURES',
origin: $localize`United States`, origin: `United States`,
slogan: 'Portfolio Tracker Designed by Professional Investors' slogan: 'Portfolio Tracker Designed by Professional Investors'
}, },
{ {
component: ExirioPageComponent,
founded: 2020, founded: 2020,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'exirio', key: 'exirio',
name: 'Exirio', name: 'Exirio',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$100', pricingPerYear: '$100',
slogan: 'All your wealth, in one place.' slogan: 'All your wealth, in one place.'
}, },
{ {
component: FinaPageComponent,
founded: 2023, founded: 2023,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'fina', key: 'fina',
languages: ['English'], languages: ['English'],
name: 'Fina', name: 'Fina',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$115', pricingPerYear: '$115',
slogan: 'Flexible Financial Management' slogan: 'Flexible Financial Management'
}, },
{ {
component: FinaryPageComponent,
founded: 2020, founded: 2020,
key: 'finary', key: 'finary',
languages: ['Deutsch', 'English', 'Français'], languages: ['Deutsch', 'English', 'Français'],
name: 'Finary', name: 'Finary',
origin: $localize`United States`, origin: `United States`,
slogan: 'Real-Time Portfolio Tracker & Stock Tracker' slogan: 'Real-Time Portfolio Tracker & Stock Tracker'
}, },
{ {
component: FinWisePageComponent,
founded: 2023, founded: 2023,
hasFreePlan: true, hasFreePlan: true,
key: 'finwise', key: 'finwise',
name: 'FinWise', name: 'FinWise',
origin: $localize`South Africa`, origin: `South Africa`,
pricingPerYear: '€69.99', pricingPerYear: '€69.99',
slogan: 'Personal finances, simplified' slogan: 'Personal finances, simplified'
}, },
{ {
component: FolisharePageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'folishare', key: 'folishare',
languages: ['Deutsch', 'English'], languages: ['Deutsch', 'English'],
name: 'folishare', name: 'folishare',
origin: $localize`Austria`, origin: `Austria`,
pricingPerYear: '$65', pricingPerYear: '$65',
slogan: 'Take control over your investments' slogan: 'Take control over your investments'
}, },
{ {
component: GetquinPageComponent,
founded: 2020, founded: 2020,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'getquin', key: 'getquin',
languages: ['Deutsch', 'English'], languages: ['Deutsch', 'English'],
name: 'getquin', name: 'getquin',
origin: $localize`Germany`, origin: `Germany`,
pricingPerYear: '€48', pricingPerYear: '€48',
slogan: 'Portfolio Tracker, Analysis & Community' slogan: 'Portfolio Tracker, Analysis & Community'
}, },
{ {
component: GoSpatzPageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'gospatz', key: 'gospatz',
name: 'goSPATZ', name: 'goSPATZ',
origin: $localize`Germany`, origin: `Germany`,
slogan: 'Volle Kontrolle über deine Investitionen' slogan: 'Volle Kontrolle über deine Investitionen'
}, },
{ {
component: IntuitMintPageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'intuit-mint', key: 'intuit-mint',
name: 'Intuit Mint', name: 'Intuit Mint',
note: 'Intuit Mint has discontinued in 2023', note: 'Intuit Mint has discontinued in 2023',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$60', pricingPerYear: '$60',
slogan: 'Managing money, made simple' slogan: 'Managing money, made simple'
}, },
{ {
component: JustEtfPageComponent,
founded: 2011, founded: 2011,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'justetf', key: 'justetf',
name: 'justETF', name: 'justETF',
origin: $localize`Germany`, origin: `Germany`,
pricingPerYear: '€119', pricingPerYear: '€119',
slogan: 'ETF portfolios made simple' slogan: 'ETF portfolios made simple'
}, },
{ {
component: KoyfinPageComponent,
founded: 2016, founded: 2016,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'koyfin', key: 'koyfin',
name: 'Koyfin', name: 'Koyfin',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$468', pricingPerYear: '$468',
slogan: 'Comprehensive financial data analysis' slogan: 'Comprehensive financial data analysis'
}, },
{ {
component: KuberaPageComponent,
founded: 2019, founded: 2019,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'kubera', key: 'kubera',
name: 'Kubera®', name: 'Kubera®',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$150', pricingPerYear: '$150',
slogan: 'The Time Machine for your Net Worth' slogan: 'The Time Machine for your Net Worth'
}, },
{ {
component: MagnifiPageComponent,
founded: 2018, founded: 2018,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'magnifi', key: 'magnifi',
name: 'Magnifi', name: 'Magnifi',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$132', pricingPerYear: '$132',
slogan: 'AI Investing Assistant' slogan: 'AI Investing Assistant'
}, },
{ {
component: MarketsShPageComponent,
founded: 2022, founded: 2022,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'markets.sh', key: 'markets.sh',
languages: ['English'], languages: ['English'],
name: 'markets.sh', name: 'markets.sh',
origin: $localize`Germany`, origin: `Germany`,
pricingPerYear: '€168', pricingPerYear: '€168',
region: $localize`Global`, region: `Global`,
slogan: 'Track your investments' slogan: 'Track your investments'
}, },
{ {
component: MaybeFinancePageComponent,
founded: 2021, founded: 2021,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'maybe-finance', key: 'maybe-finance',
languages: ['English'], languages: ['English'],
name: 'Maybe Finance', name: 'Maybe Finance',
note: 'Maybe Finance has discontinued in 2023', note: 'Maybe Finance has discontinued in 2023',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$145', pricingPerYear: '$145',
region: $localize`United States`, region: `United States`,
slogan: 'Your financial future, in your control' slogan: 'Your financial future, in your control'
}, },
{ {
component: MonarchMoneyPageComponent,
founded: 2019, founded: 2019,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'monarch-money', key: 'monarch-money',
name: 'Monarch Money', name: 'Monarch Money',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$99.99', pricingPerYear: '$99.99',
slogan: 'The modern way to manage your money' slogan: 'The modern way to manage your money'
}, },
{ {
component: MonsePageComponent,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'monse', key: 'monse',
@ -394,51 +283,46 @@ export const products: Product[] = [
slogan: 'Gain financial control and keep your data private.' slogan: 'Gain financial control and keep your data private.'
}, },
{ {
component: NavexaPageComponent,
founded: 2017, founded: 2017,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'navexa', key: 'navexa',
name: 'Navexa', name: 'Navexa',
origin: $localize`Australia`, origin: `Australia`,
pricingPerYear: '$90', pricingPerYear: '$90',
slogan: 'The Intelligent Portfolio Tracker' slogan: 'The Intelligent Portfolio Tracker'
}, },
{ {
component: ParqetPageComponent,
founded: 2020, founded: 2020,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
hasFreePlan: true, hasFreePlan: true,
key: 'parqet', key: 'parqet',
name: 'Parqet', name: 'Parqet',
note: 'Originally named as Tresor One', note: 'Originally named as Tresor One',
origin: $localize`Germany`, origin: `Germany`,
pricingPerYear: '€88', pricingPerYear: '€88',
region: 'Austria, Germany, Switzerland', region: 'Austria, Germany, Switzerland',
slogan: 'Dein Vermögen immer im Blick' slogan: 'Dein Vermögen immer im Blick'
}, },
{ {
component: PlannixPageComponent,
founded: 2023, founded: 2023,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'plannix', key: 'plannix',
name: 'Plannix', name: 'Plannix',
origin: $localize`Italy`, origin: `Italy`,
slogan: 'Your Personal Finance Hub' slogan: 'Your Personal Finance Hub'
}, },
{ {
component: PortfolioDividendTrackerPageComponent,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'portfolio-dividend-tracker', key: 'portfolio-dividend-tracker',
languages: ['English', 'Nederlands'], languages: ['English', 'Nederlands'],
name: 'Portfolio Dividend Tracker', name: 'Portfolio Dividend Tracker',
origin: $localize`Netherlands`, origin: `Netherlands`,
pricingPerYear: '€60', pricingPerYear: '€60',
slogan: 'Manage all your portfolios' slogan: 'Manage all your portfolios'
}, },
{ {
component: PortfolioVisualizerPageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'portfolio-visualizer', key: 'portfolio-visualizer',
@ -448,172 +332,155 @@ export const products: Product[] = [
slogan: 'Tools for Better Investors' slogan: 'Tools for Better Investors'
}, },
{ {
component: PortseidoPageComponent,
founded: 2021, founded: 2021,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'portseido', key: 'portseido',
languages: ['Deutsch', 'English', 'Français', 'Nederlands'], languages: ['Deutsch', 'English', 'Français', 'Nederlands'],
name: 'Portseido', name: 'Portseido',
origin: $localize`Thailand`, origin: `Thailand`,
pricingPerYear: '$96', pricingPerYear: '$96',
slogan: 'Portfolio Performance and Dividend Tracker' slogan: 'Portfolio Performance and Dividend Tracker'
}, },
{ {
component: ProjectionLabPageComponent,
founded: 2021, founded: 2021,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: true, hasSelfHostingAbility: true,
key: 'projectionlab', key: 'projectionlab',
name: 'ProjectionLab', name: 'ProjectionLab',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$108', pricingPerYear: '$108',
slogan: 'Build Financial Plans You Love.' slogan: 'Build Financial Plans You Love.'
}, },
{ {
component: RocketMoneyPageComponent,
founded: 2015, founded: 2015,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'rocket-money', key: 'rocket-money',
name: 'Rocket Money', name: 'Rocket Money',
origin: $localize`United States`, origin: `United States`,
slogan: 'Track your net worth' slogan: 'Track your net worth'
}, },
{ {
component: SeekingAlphaPageComponent,
founded: 2004, founded: 2004,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'seeking-alpha', key: 'seeking-alpha',
name: 'Seeking Alpha', name: 'Seeking Alpha',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$239', pricingPerYear: '$239',
slogan: 'Stock Market Analysis & Tools for Investors' slogan: 'Stock Market Analysis & Tools for Investors'
}, },
{ {
component: SharesightPageComponent,
founded: 2007, founded: 2007,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'sharesight', key: 'sharesight',
name: 'Sharesight', name: 'Sharesight',
origin: $localize`New Zealand`, origin: `New Zealand`,
pricingPerYear: '$135', pricingPerYear: '$135',
region: $localize`Global`, region: `Global`,
slogan: 'Stock Portfolio Tracker' slogan: 'Stock Portfolio Tracker'
}, },
{ {
component: SimplePortfolioPageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'simple-portfolio', key: 'simple-portfolio',
name: 'Simple Portfolio', name: 'Simple Portfolio',
origin: $localize`Czech Republic`, origin: `Czech Republic`,
pricingPerYear: '€80', pricingPerYear: '€80',
slogan: 'Stock Portfolio Tracker' slogan: 'Stock Portfolio Tracker'
}, },
{ {
component: SnowballAnalyticsPageComponent,
founded: 2021, founded: 2021,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'snowball-analytics', key: 'snowball-analytics',
name: 'Snowball Analytics', name: 'Snowball Analytics',
origin: $localize`France`, origin: `France`,
pricingPerYear: '$80', pricingPerYear: '$80',
slogan: 'Simple and powerful portfolio tracker' slogan: 'Simple and powerful portfolio tracker'
}, },
{ {
component: StockEventsPageComponent,
founded: 2019, founded: 2019,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'stock-events', key: 'stock-events',
name: 'Stock Events', name: 'Stock Events',
origin: $localize`Germany`, origin: `Germany`,
slogan: 'Track all your Investments' slogan: 'Track all your Investments'
}, },
{ {
component: StocklePageComponent,
key: 'stockle', key: 'stockle',
name: 'Stockle', name: 'Stockle',
origin: $localize`Finland`, origin: `Finland`,
slogan: 'Supercharge your investments tracking experience' slogan: 'Supercharge your investments tracking experience'
}, },
{ {
component: StockMarketEyePageComponent,
founded: 2008, founded: 2008,
key: 'stockmarketeye', key: 'stockmarketeye',
name: 'StockMarketEye', name: 'StockMarketEye',
origin: $localize`France`, origin: `France`,
note: 'StockMarketEye has discontinued in 2023', note: 'StockMarketEye has discontinued in 2023',
slogan: 'A Powerful Portfolio & Investment Tracking App' slogan: 'A Powerful Portfolio & Investment Tracking App'
}, },
{ {
component: StonksfolioPageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'stonksfolio', key: 'stonksfolio',
languages: ['English'], languages: ['English'],
name: 'Stonksfolio', name: 'Stonksfolio',
origin: $localize`Bulgaria`, origin: `Bulgaria`,
pricingPerYear: '€49.90', pricingPerYear: '€49.90',
slogan: 'Visualize all of your portfolios' slogan: 'Visualize all of your portfolios'
}, },
{ {
component: SumioPageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'sumio', key: 'sumio',
name: 'Sumio', name: 'Sumio',
origin: $localize`Czech Republic`, origin: `Czech Republic`,
pricingPerYear: '$20', pricingPerYear: '$20',
slogan: 'Sum up and build your wealth.' slogan: 'Sum up and build your wealth.'
}, },
{ {
component: TillerPageComponent,
founded: 2016, founded: 2016,
hasFreePlan: false, hasFreePlan: false,
key: 'tiller', key: 'tiller',
name: 'Tiller', name: 'Tiller',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$79', pricingPerYear: '$79',
slogan: slogan:
'Your financial life in a spreadsheet, automatically updated each day' 'Your financial life in a spreadsheet, automatically updated each day'
}, },
{ {
component: UtlunaPageComponent,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'utluna', key: 'utluna',
languages: ['Deutsch', 'English', 'Français'], languages: ['Deutsch', 'English', 'Français'],
name: 'Utluna', name: 'Utluna',
origin: $localize`Switzerland`, origin: `Switzerland`,
pricingPerYear: '$300', pricingPerYear: '$300',
slogan: 'Your Portfolio. Revealed.', slogan: 'Your Portfolio. Revealed.',
useAnonymously: true useAnonymously: true
}, },
{ {
component: VyzerPageComponent,
founded: 2020, founded: 2020,
hasFreePlan: true, hasFreePlan: true,
key: 'vyzer', key: 'vyzer',
name: 'Vyzer', name: 'Vyzer',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$348', pricingPerYear: '$348',
slogan: 'Virtual Family Office for Smart Wealth Management' slogan: 'Virtual Family Office for Smart Wealth Management'
}, },
{ {
component: WallminePageComponent,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'wallmine', key: 'wallmine',
languages: ['English'], languages: ['English'],
name: 'wallmine', name: 'wallmine',
origin: $localize`Czech Republic`, origin: `Czech Republic`,
pricingPerYear: '$600', pricingPerYear: '$600',
slogan: 'Make Smarter Investments' slogan: 'Make Smarter Investments'
}, },
{ {
component: WealthfolioPageComponent,
hasSelfHostingAbility: true, hasSelfHostingAbility: true,
key: 'wealthfolio', key: 'wealthfolio',
languages: ['English'], languages: ['English'],
@ -621,44 +488,40 @@ export const products: Product[] = [
slogan: 'Desktop Investment Tracker' slogan: 'Desktop Investment Tracker'
}, },
{ {
component: WealthicaPageComponent,
founded: 2015, founded: 2015,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'wealthica', key: 'wealthica',
languages: ['English', 'Français'], languages: ['English', 'Français'],
name: 'Wealthica', name: 'Wealthica',
origin: $localize`Canada`, origin: `Canada`,
pricingPerYear: '$50', pricingPerYear: '$50',
slogan: 'See all your investments in one place' slogan: 'See all your investments in one place'
}, },
{ {
component: WhalPageComponent,
key: 'whal', key: 'whal',
name: 'Whal', name: 'Whal',
origin: $localize`United States`, origin: `United States`,
slogan: 'Manage your investments in one place' slogan: 'Manage your investments in one place'
}, },
{ {
component: YeekateePageComponent,
founded: 2021, founded: 2021,
hasFreePlan: true, hasFreePlan: true,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'yeekatee', key: 'yeekatee',
languages: ['Deutsch', 'English', 'Español', 'Français', 'Italiano'], languages: ['Deutsch', 'English', 'Español', 'Français', 'Italiano'],
name: 'yeekatee', name: 'yeekatee',
origin: $localize`Switzerland`, origin: `Switzerland`,
region: $localize`Global`, region: `Global`,
slogan: 'Connect. Share. Invest.' slogan: 'Connect. Share. Invest.'
}, },
{ {
component: YnabPageComponent,
founded: 2004, founded: 2004,
hasFreePlan: false, hasFreePlan: false,
hasSelfHostingAbility: false, hasSelfHostingAbility: false,
key: 'ynab', key: 'ynab',
name: 'YNAB (You Need a Budget)', name: 'YNAB (You Need a Budget)',
origin: $localize`United States`, origin: `United States`,
pricingPerYear: '$99', pricingPerYear: '$99',
slogan: 'Change Your Relationship With Money' slogan: 'Change Your Relationship With Money'
} }
Loading…
Cancel
Save