Compare commits

...

7 Commits

Author SHA1 Message Date
f68f40fcc6 Release 1.211.0 (#1441) 2022-11-11 16:53:36 +01:00
9623a363ed Feature/convert into pwa (#1436)
* Setup @angular/pwa
2022-11-11 16:50:23 +01:00
2d42549967 Feature/improvements in pricing page (#1440)
* Improve pricing page

* Update changelog
2022-11-11 16:42:51 +01:00
c934c5088b Add ghostfolio-cli to community projects (#1437) 2022-11-11 09:02:43 +01:00
678b3cc57e Add Buy me a coffee button (#1438) 2022-11-10 19:31:00 +01:00
cd5eb64a4c Removed margin-bottom tag from the body element (#1435)
- This only changes the behaviour in Firefox
- All browsers now show the UI in a single page view
2022-11-09 20:48:13 +01:00
fc1507de4f Clean up (#1423) 2022-11-09 10:08:36 +01:00
13 changed files with 2621 additions and 2535 deletions

View File

@ -5,6 +5,14 @@ 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.211.0 - 11.11.2022
### Changed
- Converted the client into a _Progressive Web App_ (PWA) with `@angular/pwa`
- Removed the bottom margin from the body element
- Improved the pricing page
## 1.210.0 - 08.11.2022
### Added

View File

@ -53,7 +53,7 @@ Ghostfolio is for you if you are...
- ✅ Create, update and delete transactions
- ✅ Multi account management
- ✅ Portfolio performance: Time-weighted rate of return (TWR) for `Today`, `YTD`, `1Y`, `5Y`, `Max`
- ✅ Portfolio performance for `Today`, `YTD`, `1Y`, `5Y`, `Max`
- ✅ Various charts
- ✅ Static analysis to identify potential risks in your portfolio
- ✅ Import and export transactions
@ -81,6 +81,16 @@ The frontend is built with [Angular](https://angular.io) and uses [Angular Mater
We provide official container images hosted on [Docker Hub](https://hub.docker.com/r/ghostfolio/ghostfolio) for `linux/amd64` and `linux/arm64`.
<div align="center">
<a href="https://www.buymeacoffee.com/ghostfolio">
<img
alt="Buy me a coffee button"
src="./apps/client/src/assets/images/button-buy-me-a-coffee.png"
width="150"
/>
</a>
</div>
### Supported Environment Variables
| Name | Default Value | Description |
@ -256,6 +266,10 @@ You can get the _Bearer Token_ via `GET http://localhost:3333/api/v1/auth/anonym
}
```
## Community Projects
- [ghostfolio-cli](https://github.com/DerAndereJohannes/ghostfolio-cli): Command-line interface to access your portfolio
## Contributing
Ghostfolio is **100% free** and **open source**. We encourage and support an active and healthy community that accepts contributions from the public - including you.

View File

@ -917,12 +917,8 @@ export class PortfolioCalculator {
const investmentValues: { [date: string]: Big } = {};
const maxInvestmentValues: { [date: string]: Big } = {};
let lastAveragePrice = new Big(0);
// let lastTransactionInvestment = new Big(0);
// let lastValueOfInvestmentBeforeTransaction = new Big(0);
let maxTotalInvestment = new Big(0);
const netPerformanceValues: { [date: string]: Big } = {};
// let timeWeightedGrossPerformancePercentage = new Big(1);
// let timeWeightedNetPerformancePercentage = new Big(1);
let totalInvestment = new Big(0);
let totalInvestmentWithGrossPerformanceFromSell = new Big(0);
let totalUnits = new Big(0);
@ -1128,55 +1124,8 @@ export class PortfolioCalculator {
.minus(totalInvestment)
.plus(grossPerformanceFromSells);
// if (
// i > indexOfStartOrder &&
// !lastValueOfInvestmentBeforeTransaction
// .plus(lastTransactionInvestment)
// .eq(0)
// ) {
// const grossHoldingPeriodReturn = valueOfInvestmentBeforeTransaction
// .minus(
// lastValueOfInvestmentBeforeTransaction.plus(
// lastTransactionInvestment
// )
// )
// .div(
// lastValueOfInvestmentBeforeTransaction.plus(
// lastTransactionInvestment
// )
// );
// timeWeightedGrossPerformancePercentage =
// timeWeightedGrossPerformancePercentage.mul(
// new Big(1).plus(grossHoldingPeriodReturn)
// );
// const netHoldingPeriodReturn = valueOfInvestmentBeforeTransaction
// .minus(fees.minus(feesAtStartDate))
// .minus(
// lastValueOfInvestmentBeforeTransaction.plus(
// lastTransactionInvestment
// )
// )
// .div(
// lastValueOfInvestmentBeforeTransaction.plus(
// lastTransactionInvestment
// )
// );
// timeWeightedNetPerformancePercentage =
// timeWeightedNetPerformancePercentage.mul(
// new Big(1).plus(netHoldingPeriodReturn)
// );
// }
grossPerformance = newGrossPerformance;
// lastTransactionInvestment = transactionInvestment;
// lastValueOfInvestmentBeforeTransaction =
// valueOfInvestmentBeforeTransaction;
if (order.itemType === 'start') {
feesAtStartDate = fees;
grossPerformanceAtStartDate = grossPerformance;
@ -1204,12 +1153,6 @@ export class PortfolioCalculator {
}
}
// timeWeightedGrossPerformancePercentage =
// timeWeightedGrossPerformancePercentage.minus(1);
// timeWeightedNetPerformancePercentage =
// timeWeightedNetPerformancePercentage.minus(1);
const totalGrossPerformance = grossPerformance.minus(
grossPerformanceAtStartDate
);

View File

@ -0,0 +1,30 @@
{
"$schema": "../../node_modules/@angular/service-worker/config/schema.json",
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html",
"/assets/site.webmanifest",
"/*.css",
"/*.js"
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
]
}
}
]
}

View File

@ -1,4 +1,5 @@
{
"name": "client",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"generators": {
@ -43,6 +44,11 @@
"input": "apps/client/src/assets",
"output": "./../"
},
{
"glob": "site.webmanifest",
"input": "apps/client/src/assets",
"output": "./../"
},
{
"glob": "**/*",
"input": "node_modules/ionicons/dist/ionicons",
@ -66,7 +72,9 @@
"buildOptimizer": false,
"sourceMap": true,
"optimization": false,
"namedChunks": true
"namedChunks": true,
"serviceWorker": true,
"ngswConfigPath": "apps/client/ngsw-config.json"
},
"configurations": {
"development-de": {

View File

@ -26,6 +26,7 @@ import { GfHeaderModule } from './components/header/header.module';
import { authInterceptorProviders } from './core/auth.interceptor';
import { httpResponseInterceptorProviders } from './core/http-response.interceptor';
import { LanguageService } from './core/language.service';
import { ServiceWorkerModule } from '@angular/service-worker';
export function NgxStripeFactory(): string {
return environment.stripePublicKey;
@ -50,7 +51,11 @@ export function NgxStripeFactory(): string {
MatNativeDateModule,
MatSnackBarModule,
NgxSkeletonLoaderModule,
NgxStripeModule.forRoot(environment.stripePublicKey)
NgxStripeModule.forRoot(environment.stripePublicKey),
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
registrationStrategy: 'registerImmediately'
})
],
providers: [
authInterceptorProviders,

View File

@ -12,7 +12,8 @@
</p>
<p *ngIf="user?.subscription?.type === 'Basic'">
If you plan to open an account at <i>DEGIRO</i>, <i>frankly</i>,
<i>Interactive Brokers</i>, <i>Swissquote</i>, or <i>VIAC</i>, please
<i>Interactive Brokers</i>, <i>Swissquote</i>, <i>VIAC</i>, or
<i>Zak</i>, please
<a href="mailto:hi@ghostfol.io?Subject=Referral link for..."
>contact us</a
>
@ -26,7 +27,7 @@
</p>
</div>
<div class="row">
<div class="col-xs-12 col-md-4 mb-3">
<div class="col-xs-12 col-lg-4 mb-3">
<mat-card class="d-flex flex-column h-100">
<div class="flex-grow-1">
<h4>Open Source</h4>
@ -72,11 +73,20 @@
</li>
</ul>
</div>
<p>Self-hosted.</p>
<p>Self-hosted, update manually.</p>
<p class="h5 text-right">Free</p>
<div
*ngIf="user?.subscription?.type === 'Basic'"
class="d-none d-lg-block hidden mt-3 text-center"
>
<a color="primary" mat-flat-button>&nbsp;</a>
<p class="m-0 text-muted">
<small>&nbsp;</small>
</p>
</div>
</mat-card>
</div>
<div class="col-xs-12 col-md-4 mb-3">
<div class="col-xs-12 col-lg-4 mb-3">
<mat-card
class="d-flex flex-column h-100"
[ngClass]="{ 'active': user?.subscription?.type === 'Basic' }"
@ -124,9 +134,18 @@
</div>
<p>Fully managed <strong>Ghostfolio</strong> cloud offering.</p>
<p class="h5 text-right">Free</p>
<div
*ngIf="user?.subscription?.type === 'Basic'"
class="d-none d-lg-block hidden mt-3 text-center"
>
<a color="primary" mat-flat-button>&nbsp;</a>
<p class="m-0 text-muted">
<small>&nbsp;</small>
</p>
</div>
</mat-card>
</div>
<div class="col-xs-12 col-md-4 mb-3">
<div class="col-xs-12 col-lg-4 mb-3">
<mat-card
class="d-flex flex-column h-100"
[ngClass]="{ 'active': user?.subscription?.type === 'Premium' }"
@ -198,24 +217,28 @@
>&nbsp;<span>per year</span></span
>
</p>
<div
*ngIf="user?.subscription?.type === 'Basic'"
class="mt-3 text-center"
>
<a color="primary" mat-flat-button [routerLink]="['/account']">
Upgrade Plan
</a>
<p class="m-0 text-muted">
<small>One-time payment, no auto-renewal.</small>
</p>
</div>
</mat-card>
</div>
</div>
</div>
</div>
<div *ngIf="user?.subscription?.type === 'Basic'" class="row">
<div class="col mt-3 text-center">
<a color="primary" mat-flat-button [routerLink]="['/account']">
Upgrade Plan
</a>
</div>
</div>
<div *ngIf="!user" class="row">
<div class="col mt-3 text-center">
<a color="primary" mat-flat-button [routerLink]="['/register']">
Get Started
</a>
<p class="text-muted"><small>It's free</small></p>
<p class="m-0 text-muted"><small>Its free.</small></p>
</div>
</div>
</div>

View File

@ -12,6 +12,7 @@
}
.mat-card {
&:hover,
&.active {
border-color: rgba(var(--palette-primary-500), 1);
box-shadow: 0 0 0 1px rgba(var(--palette-primary-500), 1);

View File

@ -1,24 +1,25 @@
{
"background_color": "transparent",
"background_color": "#FFFFFF",
"categories": ["finance", "utilities"],
"description": "Open Source Wealth Management Software",
"display": "standalone",
"icons": [
{
"sizes": "192x192",
"src": "/en/assets/android-chrome-192x192.png",
"type": "image/png"
"src": "/assets/android-chrome-192x192.png",
"type": "image/png",
"purpose": "any maskable"
},
{
"sizes": "512x512",
"src": "/en/assets/android-chrome-512x512.png",
"src": "/assets/android-chrome-512x512.png",
"type": "image/png"
}
],
"name": "Ghostfolio",
"orientation": "portrait",
"short_name": "Ghostfolio",
"start_url": "https://www.ghostfol.io",
"start_url": "/en/",
"theme_color": "#FFFFFF",
"url": "https://www.ghostfol.io"
}

View File

@ -28,6 +28,7 @@
content="initial-scale=1, viewport-fit=cover, width=device-width"
name="viewport"
/>
<meta content="#FFFFFF" name="theme-color" />
<meta content="" property="og:description" />
<meta
content="Ghostfolio Open Source Wealth Management Software"

View File

@ -25,7 +25,6 @@ $mat-css-light-theme-selector: '.is-light-theme';
body {
font-family: var(--font-family-sans-serif);
margin: 0;
margin-bottom: 5rem;
min-height: 100%;
a {
@ -166,6 +165,10 @@ ngx-skeleton-loader {
@include gf-table;
}
.hidden {
visibility: hidden;
}
.lead {
font-weight: unset;
}

View File

@ -1,6 +1,6 @@
{
"name": "ghostfolio",
"version": "1.210.0",
"version": "1.211.0",
"homepage": "https://ghostfol.io",
"license": "AGPL-3.0",
"scripts": {
@ -63,6 +63,7 @@
"@angular/platform-browser": "14.2.0",
"@angular/platform-browser-dynamic": "14.2.0",
"@angular/router": "14.2.0",
"@angular/service-worker": "14.2.0",
"@codewithdan/observable-store": "2.2.11",
"@dfinity/agent": "0.12.1",
"@dfinity/auth-client": "0.12.1",
@ -138,6 +139,7 @@
"@angular/compiler-cli": "14.2.0",
"@angular/language-service": "14.2.0",
"@angular/localize": "14.2.0",
"@angular/pwa": "14.2.9",
"@nestjs/schematics": "9.0.3",
"@nestjs/testing": "9.1.4",
"@nrwl/cli": "15.0.0",

4957
yarn.lock

File diff suppressed because it is too large Load Diff