Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
d5d14497d6 | |||
09c300661a | |||
92382e0b4d | |||
c25f532487 | |||
5d26d94586 | |||
73b6784e9f | |||
6159f48a62 | |||
7d34fba7c1 | |||
c434b730a8 | |||
2d23c566f1 | |||
ba220eaee9 | |||
09023214ce | |||
1ceabb6e6b |
20
CHANGELOG.md
20
CHANGELOG.md
@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 1.288.0 - 2023-07-12
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved the loading state during filtering on the allocations page
|
||||
- Beautified the names with ampersand (`&`) in the asset profile
|
||||
- Improved the language localization for German (`de`)
|
||||
|
||||
## 1.287.0 - 2023-07-09
|
||||
|
||||
### Changed
|
||||
|
||||
- Hid the average buy price in the position detail chart if there is no holding
|
||||
- Improved the language localization for French (`fr`)
|
||||
- Refactored the blog articles to standalone components
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the sorting by currency in the activities table
|
||||
|
||||
## 1.286.0 - 2023-07-03
|
||||
|
||||
### Fixed
|
||||
|
@ -135,6 +135,8 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface {
|
||||
let name = longName;
|
||||
|
||||
if (name) {
|
||||
name = name.replace('&', '&');
|
||||
|
||||
name = name.replace('Amundi Index Solutions - ', '');
|
||||
name = name.replace('iShares ETF (CH) - ', '');
|
||||
name = name.replace('iShares III Public Limited Company - ', '');
|
||||
|
@ -47,104 +47,6 @@ const routes: Routes = [
|
||||
loadChildren: () =>
|
||||
import('./pages/blog/blog-page.module').then((m) => m.BlogPageModule)
|
||||
})),
|
||||
{
|
||||
path: 'blog/2021/07/hallo-ghostfolio',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.module'
|
||||
).then((m) => m.HalloGhostfolioPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2021/07/hello-ghostfolio',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.module'
|
||||
).then((m) => m.HelloGhostfolioPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2022/01/ghostfolio-first-months-in-open-source',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.module'
|
||||
).then((m) => m.FirstMonthsInOpenSourcePageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2022/07/ghostfolio-meets-internet-identity',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.module'
|
||||
).then((m) => m.GhostfolioMeetsInternetIdentityPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2022/07/how-do-i-get-my-finances-in-order',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.module'
|
||||
).then((m) => m.HowDoIGetMyFinancesInOrderPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2022/08/500-stars-on-github',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.module'
|
||||
).then((m) => m.FiveHundredStarsOnGitHubPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2022/10/hacktoberfest-2022',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.module'
|
||||
).then((m) => m.Hacktoberfest2022PageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2022/11/black-friday-2022',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2022/11/black-friday-2022/black-friday-2022-page.module'
|
||||
).then((m) => m.BlackFriday2022PageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2022/12/the-importance-of-tracking-your-personal-finances',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.module'
|
||||
).then((m) => m.TheImportanceOfTrackingYourPersonalFinancesPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.module'
|
||||
).then((m) => m.GhostfolioAufSackgeldVorgestelltPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2023/02/ghostfolio-meets-umbrel',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.module'
|
||||
).then((m) => m.GhostfolioMeetsUmbrelPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2023/03/ghostfolio-reaches-1000-stars-on-github',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.module'
|
||||
).then((m) => m.ThousandStarsOnGitHubPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2023/05/unlock-your-financial-potential-with-ghostfolio',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.module'
|
||||
).then((m) => m.UnlockYourFinancialPotentialWithGhostfolioPageModule)
|
||||
},
|
||||
{
|
||||
path: 'blog/2023/07/exploring-the-path-to-fire',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.module'
|
||||
).then((m) => m.ExploringThePathToFirePageModule)
|
||||
},
|
||||
{
|
||||
path: 'demo',
|
||||
loadChildren: () =>
|
||||
|
@ -8,11 +8,13 @@ import {
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||
import { MatSort, Sort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AdminService } from '@ghostfolio/client/services/admin.service';
|
||||
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
||||
import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config';
|
||||
import { getDateFormatString } from '@ghostfolio/common/helper';
|
||||
import { Filter, UniqueAsset, User } from '@ghostfolio/common/interfaces';
|
||||
import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface';
|
||||
@ -26,8 +28,6 @@ import { AssetProfileDialog } from './asset-profile-dialog/asset-profile-dialog.
|
||||
import { AssetProfileDialogParams } from './asset-profile-dialog/interfaces/interfaces';
|
||||
import { CreateAssetProfileDialog } from './create-asset-profile-dialog/create-asset-profile-dialog.component';
|
||||
import { CreateAssetProfileDialogParams } from './create-asset-profile-dialog/interfaces/interfaces';
|
||||
import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config';
|
||||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||
|
||||
@Component({
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
@ -215,6 +215,15 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
|
||||
this.benchmarkDataItems[0].value = this.averagePrice;
|
||||
}
|
||||
|
||||
this.benchmarkDataItems = this.benchmarkDataItems.map(
|
||||
({ date, value }) => {
|
||||
return {
|
||||
date,
|
||||
value: value === 0 ? null : value
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
if (Number.isInteger(this.quantity)) {
|
||||
this.quantityPrecision = 0;
|
||||
} else if (this.SymbolProfile?.assetSubClass === 'CRYPTOCURRENCY') {
|
||||
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { HalloGhostfolioPageComponent } from './hallo-ghostfolio-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: HalloGhostfolioPageComponent,
|
||||
path: '',
|
||||
title: 'Hallo Ghostfolio'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HalloGhostfolioPageRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-hallo-ghostfolio-page',
|
||||
standalone: true,
|
||||
templateUrl: './hallo-ghostfolio-page.html'
|
||||
})
|
||||
export class HalloGhostfolioPageComponent {}
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { HalloGhostfolioPageRoutingModule } from './hallo-ghostfolio-page-routing.module';
|
||||
import { HalloGhostfolioPageComponent } from './hallo-ghostfolio-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [HalloGhostfolioPageComponent],
|
||||
imports: [CommonModule, HalloGhostfolioPageRoutingModule, RouterModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HalloGhostfolioPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { HelloGhostfolioPageComponent } from './hello-ghostfolio-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: HelloGhostfolioPageComponent,
|
||||
path: '',
|
||||
title: 'Hello Ghostfolio'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HelloGhostfolioPageRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-hello-ghostfolio-page',
|
||||
standalone: true,
|
||||
templateUrl: './hello-ghostfolio-page.html'
|
||||
})
|
||||
export class HelloGhostfolioPageComponent {}
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { HelloGhostfolioPageRoutingModule } from './hello-ghostfolio-page-routing.module';
|
||||
import { HelloGhostfolioPageComponent } from './hello-ghostfolio-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [HelloGhostfolioPageComponent],
|
||||
imports: [CommonModule, HelloGhostfolioPageRoutingModule, RouterModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HelloGhostfolioPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { FirstMonthsInOpenSourcePageComponent } from './first-months-in-open-source-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: FirstMonthsInOpenSourcePageComponent,
|
||||
path: '',
|
||||
title: 'First months in Open Source'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class FirstMonthsInOpenSourceRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-first-months-in-open-source-page',
|
||||
standalone: true,
|
||||
templateUrl: './first-months-in-open-source-page.html'
|
||||
})
|
||||
export class FirstMonthsInOpenSourcePageComponent {}
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { FirstMonthsInOpenSourceRoutingModule } from './first-months-in-open-source-page-routing.module';
|
||||
import { FirstMonthsInOpenSourcePageComponent } from './first-months-in-open-source-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [FirstMonthsInOpenSourcePageComponent],
|
||||
imports: [CommonModule, FirstMonthsInOpenSourceRoutingModule, RouterModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class FirstMonthsInOpenSourcePageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { GhostfolioMeetsInternetIdentityPageComponent } from './ghostfolio-meets-internet-identity-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: GhostfolioMeetsInternetIdentityPageComponent,
|
||||
path: '',
|
||||
title: 'Ghostfolio meets Internet Identity'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class GhostfolioMeetsInternetIdentityRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-ghostfolio-meets-internet-identity-page',
|
||||
standalone: true,
|
||||
templateUrl: './ghostfolio-meets-internet-identity-page.html'
|
||||
})
|
||||
export class GhostfolioMeetsInternetIdentityPageComponent {}
|
||||
|
@ -1,17 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { GhostfolioMeetsInternetIdentityRoutingModule } from './ghostfolio-meets-internet-identity-page-routing.module';
|
||||
import { GhostfolioMeetsInternetIdentityPageComponent } from './ghostfolio-meets-internet-identity-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [GhostfolioMeetsInternetIdentityPageComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GhostfolioMeetsInternetIdentityRoutingModule,
|
||||
RouterModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class GhostfolioMeetsInternetIdentityPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { HowDoIGetMyFinancesInOrderPageComponent } from './how-do-i-get-my-finances-in-order-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: HowDoIGetMyFinancesInOrderPageComponent,
|
||||
path: '',
|
||||
title: 'How do I get my finances in order?'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HowDoIGetMyFinancesInOrderRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-how-do-i-get-my-finances-in-order-page',
|
||||
standalone: true,
|
||||
templateUrl: './how-do-i-get-my-finances-in-order-page.html'
|
||||
})
|
||||
export class HowDoIGetMyFinancesInOrderPageComponent {}
|
||||
|
@ -1,17 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { HowDoIGetMyFinancesInOrderRoutingModule } from './how-do-i-get-my-finances-in-order-page-routing.module';
|
||||
import { HowDoIGetMyFinancesInOrderPageComponent } from './how-do-i-get-my-finances-in-order-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [HowDoIGetMyFinancesInOrderPageComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
HowDoIGetMyFinancesInOrderRoutingModule,
|
||||
RouterModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HowDoIGetMyFinancesInOrderPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { FiveHundredStarsOnGitHubPageComponent } from './500-stars-on-github-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: FiveHundredStarsOnGitHubPageComponent,
|
||||
path: '',
|
||||
title: '500 Stars on GitHub'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class FiveHundredStarsOnGitHubRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-500-stars-on-github-page',
|
||||
standalone: true,
|
||||
templateUrl: './500-stars-on-github-page.html'
|
||||
})
|
||||
export class FiveHundredStarsOnGitHubPageComponent {}
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { FiveHundredStarsOnGitHubRoutingModule } from './500-stars-on-github-page-routing.module';
|
||||
import { FiveHundredStarsOnGitHubPageComponent } from './500-stars-on-github-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [FiveHundredStarsOnGitHubPageComponent],
|
||||
imports: [CommonModule, FiveHundredStarsOnGitHubRoutingModule, RouterModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class FiveHundredStarsOnGitHubPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { Hacktoberfest2022PageComponent } from './hacktoberfest-2022-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: Hacktoberfest2022PageComponent,
|
||||
path: '',
|
||||
title: 'Hacktoberfest 2022'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class Hacktoberfest2022RoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-hacktoberfest-2022-page',
|
||||
standalone: true,
|
||||
templateUrl: './hacktoberfest-2022-page.html'
|
||||
})
|
||||
export class Hacktoberfest2022PageComponent {}
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { Hacktoberfest2022RoutingModule } from './hacktoberfest-2022-page-routing.module';
|
||||
import { Hacktoberfest2022PageComponent } from './hacktoberfest-2022-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [Hacktoberfest2022PageComponent],
|
||||
imports: [CommonModule, Hacktoberfest2022RoutingModule, RouterModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class Hacktoberfest2022PageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { BlackFriday2022PageComponent } from './black-friday-2022-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: BlackFriday2022PageComponent,
|
||||
path: '',
|
||||
title: 'Black Friday 2022'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class BlackFriday2022RoutingModule {}
|
@ -1,8 +1,13 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [GfPremiumIndicatorModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-black-friday-2022-page',
|
||||
standalone: true,
|
||||
templateUrl: './black-friday-2022-page.html'
|
||||
})
|
||||
export class BlackFriday2022PageComponent {
|
||||
|
@ -1,21 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||
|
||||
import { BlackFriday2022RoutingModule } from './black-friday-2022-page-routing.module';
|
||||
import { BlackFriday2022PageComponent } from './black-friday-2022-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [BlackFriday2022PageComponent],
|
||||
imports: [
|
||||
BlackFriday2022RoutingModule,
|
||||
CommonModule,
|
||||
GfPremiumIndicatorModule,
|
||||
MatButtonModule,
|
||||
RouterModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class BlackFriday2022PageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { TheImportanceOfTrackingYourPersonalFinancesPageComponent } from './the-importance-of-tracking-your-personal-finances-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: TheImportanceOfTrackingYourPersonalFinancesPageComponent,
|
||||
path: '',
|
||||
title: 'The importance of tracking your personal finances'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TheImportanceOfTrackingYourPersonalFinancesRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-the-importance-of-tracking-your-personal-finances-page',
|
||||
standalone: true,
|
||||
templateUrl: './the-importance-of-tracking-your-personal-finances-page.html'
|
||||
})
|
||||
export class TheImportanceOfTrackingYourPersonalFinancesPageComponent {}
|
||||
|
@ -1,19 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { TheImportanceOfTrackingYourPersonalFinancesRoutingModule } from './the-importance-of-tracking-your-personal-finances-page-routing.module';
|
||||
import { TheImportanceOfTrackingYourPersonalFinancesPageComponent } from './the-importance-of-tracking-your-personal-finances-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [TheImportanceOfTrackingYourPersonalFinancesPageComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule,
|
||||
RouterModule,
|
||||
TheImportanceOfTrackingYourPersonalFinancesRoutingModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class TheImportanceOfTrackingYourPersonalFinancesPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { GhostfolioAufSackgeldVorgestelltPageComponent } from './ghostfolio-auf-sackgeld-vorgestellt-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: GhostfolioAufSackgeldVorgestelltPageComponent,
|
||||
path: '',
|
||||
title: 'Ghostfolio auf Sackgeld.com vorgestellt'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class GhostfolioAufSackgeldVorgestelltPageRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-ghostfolio-auf-sackgeld-vorgestellt-page',
|
||||
standalone: true,
|
||||
templateUrl: './ghostfolio-auf-sackgeld-vorgestellt-page.html'
|
||||
})
|
||||
export class GhostfolioAufSackgeldVorgestelltPageComponent {}
|
||||
|
@ -1,17 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { GhostfolioAufSackgeldVorgestelltPageRoutingModule } from './ghostfolio-auf-sackgeld-vorgestellt-page-routing.module';
|
||||
import { GhostfolioAufSackgeldVorgestelltPageComponent } from './ghostfolio-auf-sackgeld-vorgestellt-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [GhostfolioAufSackgeldVorgestelltPageComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GhostfolioAufSackgeldVorgestelltPageRoutingModule,
|
||||
RouterModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class GhostfolioAufSackgeldVorgestelltPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { GhostfolioMeetsUmbrelPageComponent } from './ghostfolio-meets-umbrel-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: GhostfolioMeetsUmbrelPageComponent,
|
||||
path: '',
|
||||
title: 'Ghostfolio meets Umbrel'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class GhostfolioMeetsUmbrelPageRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-ghostfolio-meets-umbrel-page',
|
||||
standalone: true,
|
||||
templateUrl: './ghostfolio-meets-umbrel-page.html'
|
||||
})
|
||||
export class GhostfolioMeetsUmbrelPageComponent {}
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { GhostfolioMeetsUmbrelPageRoutingModule } from './ghostfolio-meets-umbrel-page-routing.module';
|
||||
import { GhostfolioMeetsUmbrelPageComponent } from './ghostfolio-meets-umbrel-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [GhostfolioMeetsUmbrelPageComponent],
|
||||
imports: [CommonModule, GhostfolioMeetsUmbrelPageRoutingModule, RouterModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class GhostfolioMeetsUmbrelPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { ThousandStarsOnGitHubPageComponent } from './1000-stars-on-github-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: ThousandStarsOnGitHubPageComponent,
|
||||
path: '',
|
||||
title: 'Ghostfolio reaches 1’000 Stars on GitHub'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ThousandStarsOnGitHubRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-1000-stars-on-github-page',
|
||||
standalone: true,
|
||||
templateUrl: './1000-stars-on-github-page.html'
|
||||
})
|
||||
export class ThousandStarsOnGitHubPageComponent {}
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ThousandStarsOnGitHubRoutingModule } from './1000-stars-on-github-page-routing.module';
|
||||
import { ThousandStarsOnGitHubPageComponent } from './1000-stars-on-github-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [ThousandStarsOnGitHubPageComponent],
|
||||
imports: [CommonModule, ThousandStarsOnGitHubRoutingModule, RouterModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class ThousandStarsOnGitHubPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { UnlockYourFinancialPotentialWithGhostfolioPageComponent } from './unlock-your-financial-potential-with-ghostfolio-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: UnlockYourFinancialPotentialWithGhostfolioPageComponent,
|
||||
path: '',
|
||||
title: 'Unlock your Financial Potential with Ghostfolio'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class UnlockYourFinancialPotentialWithGhostfolioRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-unlock-your-financial-potential-with-ghostfolio-page',
|
||||
standalone: true,
|
||||
templateUrl: './unlock-your-financial-potential-with-ghostfolio-page.html'
|
||||
})
|
||||
export class UnlockYourFinancialPotentialWithGhostfolioPageComponent {}
|
||||
|
@ -1,19 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { UnlockYourFinancialPotentialWithGhostfolioRoutingModule } from './unlock-your-financial-potential-with-ghostfolio-page-routing.module';
|
||||
import { UnlockYourFinancialPotentialWithGhostfolioPageComponent } from './unlock-your-financial-potential-with-ghostfolio-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [UnlockYourFinancialPotentialWithGhostfolioPageComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule,
|
||||
RouterModule,
|
||||
UnlockYourFinancialPotentialWithGhostfolioRoutingModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class UnlockYourFinancialPotentialWithGhostfolioPageModule {}
|
@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { ExploringThePathToFirePageComponent } from './exploring-the-path-to-fire-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: ExploringThePathToFirePageComponent,
|
||||
path: '',
|
||||
title: 'Exploring the Path to FIRE'
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ExploringThePathToFireRoutingModule {}
|
@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
selector: 'gf-exploring-the-path-to-fire-page-page',
|
||||
standalone: true,
|
||||
templateUrl: './exploring-the-path-to-fire-page.html'
|
||||
})
|
||||
export class ExploringThePathToFirePageComponent {}
|
||||
|
@ -1,19 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ExploringThePathToFireRoutingModule } from './exploring-the-path-to-fire-page-routing.module';
|
||||
import { ExploringThePathToFirePageComponent } from './exploring-the-path-to-fire-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [ExploringThePathToFirePageComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ExploringThePathToFireRoutingModule,
|
||||
MatButtonModule,
|
||||
RouterModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class ExploringThePathToFirePageModule {}
|
@ -10,6 +10,132 @@ const routes: Routes = [
|
||||
component: BlogPageComponent,
|
||||
path: '',
|
||||
title: $localize`Blog`
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2021/07/hallo-ghostfolio',
|
||||
loadComponent: () =>
|
||||
import('./2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component').then(
|
||||
(c) => c.HalloGhostfolioPageComponent
|
||||
),
|
||||
title: 'Hallo Ghostfolio'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2021/07/hello-ghostfolio',
|
||||
loadComponent: () =>
|
||||
import('./2021/07/hello-ghostfolio/hello-ghostfolio-page.component').then(
|
||||
(c) => c.HelloGhostfolioPageComponent
|
||||
),
|
||||
title: 'Hello Ghostfolio'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2022/01/ghostfolio-first-months-in-open-source',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2022/01/first-months-in-open-source/first-months-in-open-source-page.component'
|
||||
).then((c) => c.FirstMonthsInOpenSourcePageComponent),
|
||||
title: 'First months in Open Source'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2022/07/ghostfolio-meets-internet-identity',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.component'
|
||||
).then((c) => c.GhostfolioMeetsInternetIdentityPageComponent),
|
||||
title: 'Ghostfolio meets Internet Identity'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2022/07/how-do-i-get-my-finances-in-order',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component'
|
||||
).then((c) => c.HowDoIGetMyFinancesInOrderPageComponent),
|
||||
title: 'How do I get my finances in order?'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2022/08/500-stars-on-github',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2022/08/500-stars-on-github/500-stars-on-github-page.component'
|
||||
).then((c) => c.FiveHundredStarsOnGitHubPageComponent),
|
||||
title: '500 Stars on GitHub'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2022/10/hacktoberfest-2022',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2022/10/hacktoberfest-2022/hacktoberfest-2022-page.component'
|
||||
).then((c) => c.Hacktoberfest2022PageComponent),
|
||||
title: 'Hacktoberfest 2022'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2022/11/black-friday-2022',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2022/11/black-friday-2022/black-friday-2022-page.component'
|
||||
).then((c) => c.BlackFriday2022PageComponent),
|
||||
title: 'Black Friday 2022'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2022/12/the-importance-of-tracking-your-personal-finances',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.component'
|
||||
).then((c) => c.TheImportanceOfTrackingYourPersonalFinancesPageComponent),
|
||||
title: 'The importance of tracking your personal finances'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2023/01/ghostfolio-auf-sackgeld-vorgestellt',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.component'
|
||||
).then((c) => c.GhostfolioAufSackgeldVorgestelltPageComponent),
|
||||
title: 'Ghostfolio auf Sackgeld.com vorgestellt'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2023/02/ghostfolio-meets-umbrel',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.component'
|
||||
).then((c) => c.GhostfolioMeetsUmbrelPageComponent),
|
||||
title: 'Ghostfolio meets Umbrel'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2023/03/ghostfolio-reaches-1000-stars-on-github',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2023/03/1000-stars-on-github/1000-stars-on-github-page.component'
|
||||
).then((c) => c.ThousandStarsOnGitHubPageComponent),
|
||||
title: 'Ghostfolio reaches 1’000 Stars on GitHub'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2023/05/unlock-your-financial-potential-with-ghostfolio',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component'
|
||||
).then((c) => c.UnlockYourFinancialPotentialWithGhostfolioPageComponent),
|
||||
title: 'Unlock your Financial Potential with Ghostfolio'
|
||||
},
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
path: '2023/07/exploring-the-path-to-fire',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'./2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component'
|
||||
).then((c) => c.ExploringThePathToFirePageComponent),
|
||||
title: 'Exploring the Path to FIRE'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -139,6 +139,8 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
? $localize`Filter by account or tag...`
|
||||
: '';
|
||||
|
||||
this.initialize();
|
||||
|
||||
return this.dataService.fetchPortfolioDetails({
|
||||
filters: this.activeFilters
|
||||
});
|
||||
@ -146,6 +148,8 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
takeUntil(this.unsubscribeSubject)
|
||||
)
|
||||
.subscribe((portfolioDetails) => {
|
||||
this.initialize();
|
||||
|
||||
this.portfolioDetails = portfolioDetails;
|
||||
|
||||
this.initializeAnalysisData();
|
||||
@ -237,6 +241,13 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
}
|
||||
};
|
||||
this.platforms = {};
|
||||
this.portfolioDetails = {
|
||||
accounts: {},
|
||||
filteredValueInPercentage: 0,
|
||||
holdings: {},
|
||||
platforms: {},
|
||||
summary: undefined
|
||||
};
|
||||
this.positions = {};
|
||||
this.sectors = {
|
||||
[UNKNOWN_KEY]: {
|
||||
@ -254,8 +265,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
public initializeAnalysisData() {
|
||||
this.initialize();
|
||||
|
||||
for (const [
|
||||
id,
|
||||
{ name, valueInBaseCurrency, valueInPercentage }
|
||||
|
@ -0,0 +1,34 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { PersonalFinanceToolsPageComponent } from './personal-finance-tools-page.component';
|
||||
import { products } from './products';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: PersonalFinanceToolsPageComponent,
|
||||
path: '',
|
||||
title: $localize`Personal Finance Tools`
|
||||
},
|
||||
...products
|
||||
.filter(({ key }) => {
|
||||
return key !== 'ghostfolio';
|
||||
})
|
||||
.map(({ component, key, name }) => {
|
||||
return {
|
||||
canActivate: [AuthGuard],
|
||||
path: `open-source-alternative-to-${key}`,
|
||||
loadComponent: () =>
|
||||
import(`./products/${key}-page.component`).then(() => component),
|
||||
title: `Open Source Alternative to ${name}`
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PersonalFinanceToolsPageRoutingModule {}
|
@ -0,0 +1,25 @@
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { products } from './products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
selector: 'gf-personal-finance-tools-page',
|
||||
styleUrls: ['./personal-finance-tools-page.scss'],
|
||||
templateUrl: './personal-finance-tools-page.html'
|
||||
})
|
||||
export class PersonalFinanceToolsPageComponent implements OnDestroy {
|
||||
public products = products.filter(({ key }) => {
|
||||
return key !== 'ghostfolio';
|
||||
});
|
||||
|
||||
private unsubscribeSubject = new Subject<void>();
|
||||
|
||||
public constructor() {}
|
||||
|
||||
public ngOnDestroy() {
|
||||
this.unsubscribeSubject.next();
|
||||
this.unsubscribeSubject.complete();
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<div class="container">
|
||||
<div class="mb-5 row">
|
||||
<div class="col">
|
||||
<h3 class="d-none d-sm-block mb-3 text-center" i18n>
|
||||
Discover Open Source Alternatives for Personal Finance Tools
|
||||
</h3>
|
||||
<div class="introduction mb-4">
|
||||
<p>
|
||||
This overview page features a curated collection of personal finance
|
||||
tools compared to the open source alternative
|
||||
<a [routerLink]="['/about']">Ghostfolio</a>. If you value
|
||||
transparency, data privacy, and community collaboration, Ghostfolio
|
||||
provides an excellent opportunity to take control of your financial
|
||||
management.
|
||||
</p>
|
||||
<p>
|
||||
Explore the links below to compare a variety of personal finance tools
|
||||
with Ghostfolio.
|
||||
</p>
|
||||
</div>
|
||||
<mat-card
|
||||
*ngFor="let product of products"
|
||||
appearance="outlined"
|
||||
class="mb-3"
|
||||
>
|
||||
<mat-card-content>
|
||||
<div class="container p-0">
|
||||
<div class="flex-nowrap no-gutters row">
|
||||
<a
|
||||
class="d-flex overflow-hidden w-100"
|
||||
title="Compare Ghostfolio to {{ product.name }}"
|
||||
[routerLink]="['/resources', 'personal-finance-tools', 'open-source-alternative-to-' + product.key]"
|
||||
>
|
||||
<div class="flex-grow-1 overflow-hidden">
|
||||
<div class="h6 m-0 text-truncate">
|
||||
Open Source Alternative to {{ product.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="align-items-center d-flex">
|
||||
<ion-icon
|
||||
class="chevron text-muted"
|
||||
name="chevron-forward-outline"
|
||||
size="small"
|
||||
></ion-icon>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,13 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
|
||||
import { PersonalFinanceToolsPageRoutingModule } from './personal-finance-tools-page-routing.module';
|
||||
import { PersonalFinanceToolsPageComponent } from './personal-finance-tools-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [PersonalFinanceToolsPageComponent],
|
||||
imports: [CommonModule, MatCardModule, PersonalFinanceToolsPageRoutingModule],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class PersonalFinanceToolsPageModule {}
|
@ -0,0 +1,19 @@
|
||||
:host {
|
||||
color: rgb(var(--dark-primary-text));
|
||||
display: block;
|
||||
|
||||
.introduction {
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
color: rgba(var(--palette-primary-300), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:host-context(.is-dark-theme) {
|
||||
color: rgb(var(--light-primary-text));
|
||||
}
|
@ -0,0 +1,298 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 offset-md-2">
|
||||
<article>
|
||||
<div class="mb-4 text-center">
|
||||
<h1 class="mb-1">
|
||||
<strong>Ghostfolio</strong>: The Open Source Alternative to
|
||||
<strong>{{ product2.name }}</strong>
|
||||
</h1>
|
||||
</div>
|
||||
<section class="mb-4">
|
||||
<p>
|
||||
Are you looking for an open source alternative to {{ product2.name
|
||||
}}? <a [routerLink]="['/about']">Ghostfolio</a> is a powerful
|
||||
portfolio management tool that provides individuals with a
|
||||
comprehensive platform to track, analyze, and optimize their
|
||||
investments. Whether you are an experienced investor or just
|
||||
starting out, Ghostfolio offers an intuitive user interface and a
|
||||
<a [routerLink]="['/features']">wide range of functionalities</a>
|
||||
to help you make informed decisions and take control of your
|
||||
financial future.
|
||||
</p>
|
||||
<p>
|
||||
Ghostfolio is an open source software (OSS), providing a
|
||||
cost-effective alternative to {{ product2.name }} making it
|
||||
particularly suitable for individuals on a tight budget, such as
|
||||
those
|
||||
<a href="../en/blog/2023/07/exploring-the-path-to-fire"
|
||||
>pursuing Financial Independence, Retire Early (FIRE)</a
|
||||
>. By leveraging the collective efforts of a community of developers
|
||||
and personal finance enthusiasts, Ghostfolio continuously enhances
|
||||
its capabilities, security, and user experience.
|
||||
</p>
|
||||
<p>
|
||||
Let’s dive deeper into the detailed comparison table below to gain a
|
||||
thorough understanding of how Ghostfolio positions itself relative
|
||||
to {{ product2.name }}. We will explore various aspects such as
|
||||
features, data privacy, pricing, and more, allowing you to make a
|
||||
well-informed choice for your personal requirements.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<table class="gf-table w-100">
|
||||
<thead>
|
||||
<tr class="mat-mdc-header-row">
|
||||
<th class="mat-mdc-header-cell px-1 py-2"></th>
|
||||
<th class="mat-mdc-header-cell px-1 py-2">Ghostfolio</th>
|
||||
<th class="mat-mdc-header-cell px-1 py-2">
|
||||
{{ product2.name }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right"></td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product1.slogan }}</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product2.slogan }}</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Founded</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product1.founded }}</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product2.founded }}</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Origin</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product1.origin }}</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product2.origin }}</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Region</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product1.region }}</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product2.region }}</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>
|
||||
Available in
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container
|
||||
*ngFor="let language of product1.languages; last as isLast"
|
||||
>{{ language }}{{ isLast ? '' : ', ' }}</ng-container
|
||||
>
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container
|
||||
*ngFor="let language of product2.languages; last as isLast"
|
||||
>{{ language }}{{ isLast ? '' : ', ' }}</ng-container
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right">
|
||||
Open Source Software
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container *ngIf="product1.isOpenSource === true" i18n
|
||||
>✅ Yes</ng-container
|
||||
><ng-container *ngIf="product1.isOpenSource === false" i18n
|
||||
>❌ No</ng-container
|
||||
>
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container *ngIf="product2.isOpenSource === true" i18n
|
||||
>✅ Yes</ng-container
|
||||
><ng-container *ngIf="product2.isOpenSource === false" i18n
|
||||
>❌ No
|
||||
</ng-container>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>
|
||||
Self-Hosting
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container
|
||||
*ngIf="product1.hasSelfHostingAbility === true"
|
||||
i18n
|
||||
>✅ Yes</ng-container
|
||||
><ng-container
|
||||
*ngIf="product1.hasSelfHostingAbility === false"
|
||||
i18n
|
||||
>❌ No</ng-container
|
||||
>
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container
|
||||
*ngIf="product2.hasSelfHostingAbility === true"
|
||||
i18n
|
||||
>✅ Yes</ng-container
|
||||
><ng-container
|
||||
*ngIf="product2.hasSelfHostingAbility === false"
|
||||
i18n
|
||||
>❌ No</ng-container
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>
|
||||
Use anonymously
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container *ngIf="product1.useAnonymously === true" i18n
|
||||
>✅ Yes</ng-container
|
||||
><ng-container *ngIf="product1.useAnonymously === false" i18n
|
||||
>❌ No</ng-container
|
||||
>
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container *ngIf="product2.useAnonymously === true" i18n
|
||||
>✅ Yes</ng-container
|
||||
><ng-container *ngIf="product2.useAnonymously === false" i18n
|
||||
>❌ No</ng-container
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>
|
||||
Free Plan
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container *ngIf="product1.hasFreePlan === true" i18n
|
||||
>✅ Yes</ng-container
|
||||
><ng-container *ngIf="product1.hasFreePlan === false" i18n
|
||||
>❌ No</ng-container
|
||||
>
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container *ngIf="product2.hasFreePlan === true" i18n
|
||||
>✅ Yes</ng-container
|
||||
><ng-container *ngIf="product2.hasFreePlan === false" i18n
|
||||
>❌ No</ng-container
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Pricing</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
Starting from {{ product1.pricingPerYear }} / year
|
||||
</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">
|
||||
<ng-container *ngIf="product2.pricingPerYear"
|
||||
>Starting from {{ product2.pricingPerYear }} /
|
||||
year</ng-container
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
<tr *ngIf="product1.note || product2.note" class="mat-mdc-row">
|
||||
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Notes</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product1.note }}</td>
|
||||
<td class="mat-mdc-cell px-1 py-2">{{ product2.note }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<p>
|
||||
Please note that the information provided is based on our
|
||||
independent research and analysis. This website is not affiliated
|
||||
with {{ product2.name }} or any other product mentioned in the
|
||||
comparison. As the landscape of personal finance tools evolves, it
|
||||
is essential to verify any specific details or changes directly from
|
||||
the respective product page. Data needs a refresh? Help us maintain
|
||||
accurate data on
|
||||
<a href="https://github.com/ghostfolio/ghostfolio">GitHub</a>.
|
||||
</p>
|
||||
</section>
|
||||
<section class="call-to-action mb-4 py-3 rounded">
|
||||
<h2 class="h4 mb-0 text-center">
|
||||
Ready to take your <strong>investments</strong> to the
|
||||
<strong>next level</strong>?
|
||||
</h2>
|
||||
<p class="lead mb-2 text-center" i18n>
|
||||
Effortlessly track, analyze, and visualize your wealth with
|
||||
Ghostfolio.
|
||||
</p>
|
||||
<div class="text-center">
|
||||
<a color="primary" href="https://ghostfol.io" mat-flat-button>
|
||||
Get Started
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<ul class="list-inline">
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">{{ product1.name }}</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">{{ product2.name }}</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Alternative</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">App</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Community</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Fintech</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Investment</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Investor</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Open Source</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">OSS</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Personal Finance</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Privacy</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Portfolio</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Software</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Tool</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">User Experience</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Wealth</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="badge badge-light">Wealth Management</span>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a i18n [routerLink]="['/resources', 'personal-finance-tools']"
|
||||
>Personal Finance Tools</a
|
||||
>
|
||||
</li>
|
||||
<li
|
||||
aria-current="page"
|
||||
class="active breadcrumb-item text-truncate"
|
||||
>
|
||||
{{ product2.name }}
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,25 @@
|
||||
:host {
|
||||
color: rgb(var(--dark-primary-text));
|
||||
display: block;
|
||||
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
color: rgba(var(--palette-primary-300), 1);
|
||||
}
|
||||
}
|
||||
|
||||
.call-to-action {
|
||||
background-color: rgba(var(--palette-foreground-text), 0.02);
|
||||
}
|
||||
}
|
||||
|
||||
:host-context(.is-dark-theme) {
|
||||
color: rgb(var(--light-primary-text));
|
||||
|
||||
.call-to-action {
|
||||
background-color: rgba(var(--palette-foreground-text-dark), 0.02);
|
||||
}
|
||||
}
|
@ -0,0 +1,338 @@
|
||||
import { Product } from '@ghostfolio/common/interfaces';
|
||||
|
||||
import { AltooPageComponent } from './products/altoo-page.component';
|
||||
import { CopilotMoneyPageComponent } from './products/copilot-money-page.component';
|
||||
import { DeltaPageComponent } from './products/delta-page.component';
|
||||
import { DivvyDiaryPageComponent } from './products/divvydiary-page.component';
|
||||
import { ExirioPageComponent } from './products/exirio-page.component';
|
||||
import { FolisharePageComponent } from './products/folishare-page.component';
|
||||
import { GetquinPageComponent } from './products/getquin-page.component';
|
||||
import { GoSpatzPageComponent } from './products/gospatz-page.component';
|
||||
import { JustEtfPageComponent } from './products/justetf-page.component';
|
||||
import { KuberaPageComponent } from './products/kubera-page.component';
|
||||
import { MaybeFinancePageComponent } from './products/maybe-finance-page.component';
|
||||
import { MonsePageComponent } from './products/monse-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 { PortseidoPageComponent } from './products/portseido-page.component';
|
||||
import { ProjectionLabPageComponent } from './products/projectionlab-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 { SumioPageComponent } from './products/sumio-page.component';
|
||||
import { UtlunaPageComponent } from './products/utluna-page.component';
|
||||
import { YeekateePageComponent } from './products/yeekatee-page.component';
|
||||
|
||||
export const products: Product[] = [
|
||||
{
|
||||
component: undefined,
|
||||
founded: 2021,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: true,
|
||||
isOpenSource: true,
|
||||
key: 'ghostfolio',
|
||||
languages: [
|
||||
'Dutch',
|
||||
'English',
|
||||
'French',
|
||||
'German',
|
||||
'Italian',
|
||||
'Portuguese',
|
||||
'Spanish'
|
||||
],
|
||||
name: 'Ghostfolio',
|
||||
origin: 'Switzerland',
|
||||
pricingPerYear: '$19',
|
||||
region: 'Global',
|
||||
slogan: 'Open Source Wealth Management',
|
||||
useAnonymously: true
|
||||
},
|
||||
{
|
||||
component: AltooPageComponent,
|
||||
founded: 2017,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'altoo',
|
||||
name: 'Altoo Wealth Platform',
|
||||
origin: 'Switzerland',
|
||||
slogan: 'Simplicity for Complex Wealth'
|
||||
},
|
||||
{
|
||||
component: CopilotMoneyPageComponent,
|
||||
founded: 2019,
|
||||
hasFreePlan: false,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'copilot-money',
|
||||
name: 'Copilot Money',
|
||||
origin: 'United States',
|
||||
pricingPerYear: '$70',
|
||||
slogan: 'Do money better with Copilot'
|
||||
},
|
||||
{
|
||||
component: DeltaPageComponent,
|
||||
founded: 2017,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'delta',
|
||||
name: 'Delta Investment Tracker',
|
||||
note: 'Acquired by eToro',
|
||||
origin: 'Belgium',
|
||||
slogan: 'The app to track all your investments. Make smart moves only.'
|
||||
},
|
||||
{
|
||||
component: DivvyDiaryPageComponent,
|
||||
founded: 2019,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'divvydiary',
|
||||
languages: ['English', 'German'],
|
||||
name: 'DivvyDiary',
|
||||
origin: 'Germany',
|
||||
pricingPerYear: '€65',
|
||||
slogan: 'Your personal Dividend Calendar'
|
||||
},
|
||||
{
|
||||
component: ExirioPageComponent,
|
||||
founded: 2020,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'exirio',
|
||||
name: 'Exirio',
|
||||
origin: 'United States',
|
||||
pricingPerYear: '$100',
|
||||
slogan: 'All your wealth, in one place.'
|
||||
},
|
||||
{
|
||||
component: FolisharePageComponent,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'folishare',
|
||||
languages: ['English', 'German'],
|
||||
name: 'folishare',
|
||||
origin: 'Austria',
|
||||
pricingPerYear: '$65',
|
||||
slogan: 'Take control over your investments'
|
||||
},
|
||||
{
|
||||
component: GetquinPageComponent,
|
||||
founded: 2020,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'getquin',
|
||||
languages: ['English', 'German'],
|
||||
name: 'getquin',
|
||||
origin: 'Germany',
|
||||
pricingPerYear: '€48',
|
||||
slogan: 'Portfolio Tracker, Analysis & Community'
|
||||
},
|
||||
{
|
||||
component: GoSpatzPageComponent,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'gospatz',
|
||||
name: 'goSPATZ',
|
||||
origin: 'Germany',
|
||||
slogan: 'Volle Kontrolle über deine Investitionen'
|
||||
},
|
||||
{
|
||||
component: JustEtfPageComponent,
|
||||
founded: 2011,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'justetf',
|
||||
name: 'justETF',
|
||||
origin: 'Germany',
|
||||
pricingPerYear: '€119',
|
||||
slogan: 'ETF portfolios made simple'
|
||||
},
|
||||
{
|
||||
component: KuberaPageComponent,
|
||||
founded: 2019,
|
||||
hasFreePlan: false,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'kubera',
|
||||
name: 'Kubera®',
|
||||
origin: 'United States',
|
||||
pricingPerYear: '$150',
|
||||
slogan: 'The Time Machine for your Net Worth'
|
||||
},
|
||||
{
|
||||
component: MaybeFinancePageComponent,
|
||||
founded: 2021,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'maybe-finance',
|
||||
languages: ['English'],
|
||||
name: 'Maybe Finance',
|
||||
note: 'Sunset in 2023',
|
||||
origin: 'United States',
|
||||
pricingPerYear: '$145',
|
||||
region: 'United States',
|
||||
slogan: 'Your financial future, in your control'
|
||||
},
|
||||
{
|
||||
component: MonsePageComponent,
|
||||
hasFreePlan: false,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'monse',
|
||||
name: 'Monse',
|
||||
pricingPerYear: '$60',
|
||||
slogan: 'Gain financial control and keep your data private.'
|
||||
},
|
||||
{
|
||||
component: ParqetPageComponent,
|
||||
founded: 2020,
|
||||
hasSelfHostingAbility: false,
|
||||
hasFreePlan: true,
|
||||
isOpenSource: false,
|
||||
key: 'parqet',
|
||||
name: 'Parqet',
|
||||
note: 'Originally named as Tresor One',
|
||||
origin: 'Germany',
|
||||
pricingPerYear: '€88',
|
||||
region: 'Austria, Germany, Switzerland',
|
||||
slogan: 'Dein Vermögen immer im Blick'
|
||||
},
|
||||
{
|
||||
component: PlannixPageComponent,
|
||||
founded: 2023,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'plannix',
|
||||
name: 'Plannix',
|
||||
origin: 'Italy',
|
||||
slogan: 'Your Personal Finance Hub'
|
||||
},
|
||||
{
|
||||
component: PortfolioDividendTrackerPageComponent,
|
||||
hasFreePlan: false,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'portfolio-dividend-tracker',
|
||||
languages: ['English', 'Dutch'],
|
||||
name: 'Portfolio Dividend Tracker',
|
||||
origin: 'Netherlands',
|
||||
pricingPerYear: '€60',
|
||||
slogan: 'Manage all your portfolios'
|
||||
},
|
||||
{
|
||||
component: PortseidoPageComponent,
|
||||
founded: 2021,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'portseido',
|
||||
languages: ['Dutch', 'English', 'French', 'German'],
|
||||
name: 'Portseido',
|
||||
origin: 'Thailand',
|
||||
pricingPerYear: '$96',
|
||||
slogan: 'Portfolio Performance and Dividend Tracker'
|
||||
},
|
||||
{
|
||||
component: ProjectionLabPageComponent,
|
||||
founded: 2021,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: true,
|
||||
isOpenSource: false,
|
||||
key: 'projectionlab',
|
||||
name: 'ProjectionLab',
|
||||
origin: 'United States',
|
||||
pricingPerYear: '$108',
|
||||
slogan: 'Build Financial Plans You Love.'
|
||||
},
|
||||
{
|
||||
component: SeekingAlphaPageComponent,
|
||||
founded: 2004,
|
||||
hasFreePlan: false,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'seeking-alpha',
|
||||
name: 'Seeking Alpha',
|
||||
origin: 'United States',
|
||||
pricingPerYear: '$239',
|
||||
slogan: 'Stock Market Analysis & Tools for Investors'
|
||||
},
|
||||
{
|
||||
component: SharesightPageComponent,
|
||||
founded: 2007,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'sharesight',
|
||||
name: 'Sharesight',
|
||||
origin: 'New Zealand',
|
||||
pricingPerYear: '$135',
|
||||
region: 'Global',
|
||||
slogan: 'Stock Portfolio Tracker'
|
||||
},
|
||||
{
|
||||
component: SimplePortfolioPageComponent,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'simple-portfolio',
|
||||
name: 'Simple Portfolio',
|
||||
origin: 'Czech Republic',
|
||||
pricingPerYear: '€80',
|
||||
slogan: 'Stock Portfolio Tracker'
|
||||
},
|
||||
{
|
||||
component: SnowballAnalyticsPageComponent,
|
||||
founded: 2021,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'snowball-analytics',
|
||||
name: 'Snowball Analytics',
|
||||
origin: 'France',
|
||||
pricingPerYear: '$80',
|
||||
slogan: 'Simple and powerful portfolio tracker'
|
||||
},
|
||||
{
|
||||
component: SumioPageComponent,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'sumio',
|
||||
name: 'Sumio',
|
||||
origin: 'Czech Republic',
|
||||
pricingPerYear: '$20',
|
||||
slogan: 'Sum up and build your wealth.'
|
||||
},
|
||||
{
|
||||
component: UtlunaPageComponent,
|
||||
hasFreePlan: true,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'utluna',
|
||||
languages: ['English', 'French', 'German'],
|
||||
name: 'Utluna',
|
||||
origin: 'Switzerland',
|
||||
pricingPerYear: '$300',
|
||||
slogan: 'Your Portfolio. Revealed.',
|
||||
useAnonymously: true
|
||||
},
|
||||
{
|
||||
component: YeekateePageComponent,
|
||||
founded: 2021,
|
||||
hasSelfHostingAbility: false,
|
||||
isOpenSource: false,
|
||||
key: 'yeekatee',
|
||||
name: 'yeekatee',
|
||||
origin: 'Switzerland',
|
||||
region: 'Switzerland',
|
||||
slogan: 'Connect. Share. Invest.'
|
||||
}
|
||||
];
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-altoo-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class AltooPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'altoo';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-copilot-money-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class CopilotMoneyPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'copilot-money';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-delta-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class DeltaPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'delta';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-divvy-diary-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class DivvyDiaryPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'divvydiary';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-exirio-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class ExirioPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'exirio';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-folishare-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class FolisharePageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'folishare';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-getquin-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class GetquinPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'getquin';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-gospatz-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class GoSpatzPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'gospatz';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-justetf-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class JustEtfPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'justetf';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-kubera-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class KuberaPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'kubera';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-maybe-finance-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class MaybeFinancePageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'maybe-finance';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-monse-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class MonsePageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'monse';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-parqet-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class ParqetPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'parqet';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-plannix-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class PlannixPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'plannix';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-portfolio-dividend-tracker-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class PortfolioDividendTrackerPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'portfolio-dividend-tracker';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-portseido-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class PortseidoPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'portseido';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-projection-lab-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class ProjectionLabPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'projectionlab';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-seeking-alpha-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class SeekingAlphaPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'seeking-alpha';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-sharesight-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class SharesightPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'sharesight';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-simple-portfolio-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class SimplePortfolioPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'simple-portfolio';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-snowball-analytics-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class SnowballAnalyticsPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'snowball-analytics';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-sumio-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class SumioPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'sumio';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-utluna-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class UtlunaPageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'utluna';
|
||||
});
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { products } from '../products';
|
||||
|
||||
@Component({
|
||||
host: { class: 'page' },
|
||||
imports: [CommonModule, MatButtonModule, RouterModule],
|
||||
selector: 'gf-yeekatee-page',
|
||||
standalone: true,
|
||||
styleUrls: ['../product-page-template.scss'],
|
||||
templateUrl: '../product-page-template.html'
|
||||
})
|
||||
export class YeekateePageComponent {
|
||||
public product1 = products.find(({ key }) => {
|
||||
return key === 'ghostfolio';
|
||||
});
|
||||
|
||||
public product2 = products.find(({ key }) => {
|
||||
return key === 'yeekatee';
|
||||
});
|
||||
}
|
@ -10,7 +10,14 @@ const routes: Routes = [
|
||||
component: ResourcesPageComponent,
|
||||
path: '',
|
||||
title: $localize`Resources`
|
||||
}
|
||||
},
|
||||
...['personal-finance-tools'].map((path) => ({
|
||||
path,
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./personal-finance-tools/personal-finance-tools-page.module'
|
||||
).then((m) => m.PersonalFinanceToolsPageModule)
|
||||
}))
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Resources</h1>
|
||||
<h2 class="h4 mb-3">Guides</h2>
|
||||
<h2 class="h4 mb-3" i18n>Guides</h2>
|
||||
<div class="mb-5">
|
||||
<div class="mb-4 media">
|
||||
<div class="media-body">
|
||||
@ -36,7 +36,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="h4 mb-3">Market</h2>
|
||||
<h2 class="h4 mb-3" i18n>Markets</h2>
|
||||
<div class="mb-5">
|
||||
<div class="mb-4 media">
|
||||
<div class="media-body">
|
||||
@ -72,7 +72,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="h4 mb-3">Glossary</h2>
|
||||
<h2 class="h4 mb-3" i18n>Glossary</h2>
|
||||
<div>
|
||||
<div class="mb-4 media">
|
||||
<div class="media-body">
|
||||
@ -170,6 +170,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4 media">
|
||||
<div class="media-body">
|
||||
<h3 class="h5 mt-0">Personal Finance Tools</h3>
|
||||
<div class="mb-1">
|
||||
Personal finance tools are software applications that help
|
||||
individuals manage their money, track expenses, set budgets,
|
||||
monitor investments, and make informed financial decisions.
|
||||
</div>
|
||||
<div>
|
||||
<a [routerLink]="['/resources', 'personal-finance-tools']"
|
||||
>Personal Finance Tools →</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4 media">
|
||||
<div class="media-body">
|
||||
<h3 class="h5 mt-0">Stagflation</h3>
|
||||
|
@ -19,6 +19,7 @@ import { DataSource, MarketData, Platform, Prisma } from '@prisma/client';
|
||||
import { JobStatus } from 'bull';
|
||||
import { format, parseISO } from 'date-fns';
|
||||
import { Observable, map } from 'rxjs';
|
||||
|
||||
import { DataService } from './data.service';
|
||||
|
||||
@Injectable({
|
||||
|
@ -6,410 +6,510 @@
|
||||
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/blog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/blog/2021/07/hallo-ghostfolio</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/features</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/haeufig-gestellte-fragen</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/maerkte</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/open</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/preise</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/registrierung</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/ressourcen</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/ueber-uns</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/ueber-uns/changelog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/ueber-uns/datenschutzbestimmungen</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/ueber-uns/lizenz</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/about</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/about/changelog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/about/license</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2021/07/hello-ghostfolio</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2022/01/ghostfolio-first-months-in-open-source</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2022/07/ghostfolio-meets-internet-identity</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2022/07/how-do-i-get-my-finances-in-order</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2022/08/500-stars-on-github</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2022/10/hacktoberfest-2022</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2022/11/black-friday-2022</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2022/12/the-importance-of-tracking-your-personal-finances</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2023/02/ghostfolio-meets-umbrel</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2023/03/ghostfolio-reaches-1000-stars-on-github</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2023/05/unlock-your-financial-potential-with-ghostfolio</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2023/07/exploring-the-path-to-fire</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/faq</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/features</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/markets</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/open</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/pricing</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/register</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-altoo</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-copilot-money</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-delta</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-divvydiary</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-exirio</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-folishare</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-getquin</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-gospatz</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-justetf</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-kubera</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-maybe-finance</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-monse</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-parqet</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-plannix</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-portfolio-dividend-tracker</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-portseido</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-projectionlab</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-seeking-alpha</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-sharesight</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-simple-portfolio</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-snowball-analytics</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-sumio</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-utluna</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-yeekatee</loc>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/funcionalidades</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/mercados</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/open</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/precios</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/preguntas-mas-frecuentes</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/recursos</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/registro</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/sobre</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/sobre/changelog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/sobre/licencia</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/es/sobre/politica-de-privacidad</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/a-propos</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/a-propos/changelog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/a-propos/licence</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/a-propos/politique-de-confidentialite</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/enregistrement</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/fonctionnalites</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/foire-aux-questions</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/marches</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/open</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/prix</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/fr/ressources</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/domande-piu-frequenti</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/funzionalita</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/informazioni-su</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/informazioni-su/changelog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/informazioni-su/licenza</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/informazioni-su/informativa-sulla-privacy</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/iscrizione</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/mercati</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/open</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/prezzi</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/it/risorse</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/bronnen</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/kenmerken</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/markten</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/open</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/over</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/over/changelog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/over/licentie</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/over/privacybeleid</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/prijzen</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/registratie</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/nl/vaak-gestelde-vragen</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/blog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/funcionalidades</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/mercados</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/open</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/perguntas-mais-frequentes</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/precos</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/recursos</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/registo</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/sobre</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/sobre/changelog</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/sobre/licenca</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pt/sobre/politica-de-privacidade</loc>
|
||||
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
|
||||
<lastmod>2023-07-10T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
</urlset>
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -32,6 +32,7 @@ import type { PortfolioReportRule } from './portfolio-report-rule.interface';
|
||||
import type { PortfolioReport } from './portfolio-report.interface';
|
||||
import type { PortfolioSummary } from './portfolio-summary.interface';
|
||||
import type { Position } from './position.interface';
|
||||
import type { Product } from './product';
|
||||
import type { BenchmarkResponse } from './responses/benchmark-response.interface';
|
||||
import type { ResponseError } from './responses/errors.interface';
|
||||
import type { ImportResponse } from './responses/import-response.interface';
|
||||
@ -83,6 +84,7 @@ export {
|
||||
PortfolioReportRule,
|
||||
PortfolioSummary,
|
||||
Position,
|
||||
Product,
|
||||
ResponseError,
|
||||
ScraperConfiguration,
|
||||
Statistics,
|
||||
|
16
libs/common/src/lib/interfaces/product.ts
Normal file
16
libs/common/src/lib/interfaces/product.ts
Normal file
@ -0,0 +1,16 @@
|
||||
export interface Product {
|
||||
component: any;
|
||||
founded?: number;
|
||||
hasFreePlan?: boolean;
|
||||
hasSelfHostingAbility?: boolean;
|
||||
isOpenSource: boolean;
|
||||
key: string;
|
||||
languages?: string[];
|
||||
name: string;
|
||||
note?: string;
|
||||
origin?: string;
|
||||
pricingPerYear?: string;
|
||||
region?: string;
|
||||
slogan?: string;
|
||||
useAnonymously?: boolean;
|
||||
}
|
@ -223,7 +223,7 @@
|
||||
*matHeaderCellDef
|
||||
class="d-none d-lg-table-cell px-1"
|
||||
mat-header-cell
|
||||
mat-sort-header
|
||||
mat-sort-header="SymbolProfile.currency"
|
||||
>
|
||||
<ng-container i18n>Currency</ng-container>
|
||||
</th>
|
||||
|
@ -154,7 +154,8 @@ export class LineChartComponent implements AfterViewInit, OnChanges, OnDestroy {
|
||||
data: benchmarkPrices,
|
||||
fill: false,
|
||||
label: this.benchmarkLabel,
|
||||
pointRadius: 0
|
||||
pointRadius: 0,
|
||||
spanGaps: false
|
||||
},
|
||||
{
|
||||
backgroundColor: gradient,
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ghostfolio",
|
||||
"version": "1.286.0",
|
||||
"version": "1.288.0",
|
||||
"homepage": "https://ghostfol.io",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
Reference in New Issue
Block a user