Browse Source

Merge branch 'main' into feature/support-filters-in-export-endpoint

pull/2939/head
Thomas Kaul 2 years ago
committed by GitHub
parent
commit
5bd0685b28
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 11
      CHANGELOG.md
  2. 8
      apps/api/src/app/user/user.service.ts
  3. 15
      apps/api/src/services/api/api.service.ts
  4. 2
      apps/client/src/app/app.component.html
  5. 16
      apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html
  6. 18
      apps/client/src/app/components/accounts-table/accounts-table.component.html
  7. 2
      apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.html
  8. 4
      apps/client/src/app/components/admin-market-data/admin-market-data.html
  9. 6
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
  10. 11
      apps/client/src/app/components/admin-overview/admin-overview.html
  11. 2
      apps/client/src/app/components/admin-platform/admin-platform.component.html
  12. 8
      apps/client/src/app/components/admin-users/admin-users.html
  13. 4
      apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html
  14. 2
      apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html
  15. 30
      apps/client/src/app/components/header/header.component.html
  16. 2
      apps/client/src/app/components/header/header.module.ts
  17. 4
      apps/client/src/app/components/home-holdings/home-holdings.html
  18. 8
      apps/client/src/app/components/home-market/home-market.html
  19. 6
      apps/client/src/app/components/home-overview/home-overview.html
  20. 2
      apps/client/src/app/components/home-summary/home-summary.html
  21. 2
      apps/client/src/app/components/investment-chart/investment-chart.component.html
  22. 2
      apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html
  23. 6
      apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html
  24. 42
      apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html
  25. 16
      apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html
  26. 10
      apps/client/src/app/components/position/position.component.html
  27. 10
      apps/client/src/app/components/positions/positions.component.html
  28. 6
      apps/client/src/app/components/rule/rule.component.html
  29. 10
      apps/client/src/app/components/rules/rules.component.html
  30. 5
      apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html
  31. 4
      apps/client/src/app/components/user-account-access/user-account-access.html
  32. 10
      apps/client/src/app/components/user-account-membership/user-account-membership.html
  33. 2
      apps/client/src/app/components/world-map-chart/world-map-chart.component.html
  34. 2
      apps/client/src/app/pages/accounts/accounts-page.html
  35. 2
      apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html
  36. 6
      apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html
  37. 4
      apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html
  38. 4
      apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html
  39. 8
      apps/client/src/app/pages/features/features-page.html
  40. 13
      apps/client/src/app/pages/landing/landing-page.html
  41. 2
      apps/client/src/app/pages/markets/markets-page.html
  42. 4
      apps/client/src/app/pages/portfolio/activities/activities-page.html
  43. 5
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html
  44. 8
      apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html
  45. 111
      apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
  46. 60
      apps/client/src/app/pages/portfolio/allocations/allocations-page.html
  47. 42
      apps/client/src/app/pages/portfolio/analysis/analysis-page.html
  48. 34
      apps/client/src/app/pages/portfolio/fire/fire-page.html
  49. 43
      apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts
  50. 6
      apps/client/src/app/pages/portfolio/holdings/holdings-page.html
  51. 5
      apps/client/src/app/pages/pricing/pricing-page.html
  52. 12
      apps/client/src/app/pages/public/public-page.html
  53. 2
      apps/client/src/app/pages/register/register-page.html
  54. 2
      apps/client/src/app/pages/webauthn/webauthn-page.html
  55. 2
      apps/client/src/index.html
  56. 2
      libs/ui/src/lib/account-balances/account-balances.component.html
  57. 22
      libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.html
  58. 28
      libs/ui/src/lib/activities-table/activities-table.component.html
  59. 21
      libs/ui/src/lib/assistant/assistant.component.ts
  60. 50
      libs/ui/src/lib/assistant/assistant.html
  61. 2
      libs/ui/src/lib/assistant/assistant.scss
  62. 2
      libs/ui/src/lib/fire-calculator/fire-calculator.component.html
  63. 16
      libs/ui/src/lib/holdings-table/holdings-table.component.html
  64. 8
      libs/ui/src/lib/holdings-table/holdings-table.component.ts
  65. 2
      libs/ui/src/lib/line-chart/line-chart.component.html
  66. 2
      libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html
  67. 2
      libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.html
  68. 2
      libs/ui/src/lib/trend-indicator/trend-indicator.component.html
  69. 2
      libs/ui/src/lib/value/value.component.html
  70. 2
      package.json

11
CHANGELOG.md

@ -11,6 +11,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed the export in the lazy-loaded activities table on the portfolio activities page (experimental)
## 2.46.0 - 2024-01-28
### Added
- Added a button to reset the active filters in the assistant (experimental)
### Changed
- Migrated the portfolio allocations to work with the filters of the assistant (experimental)
- Migrated the portfolio holdings to work with the filters of the assistant (experimental)
## 2.45.0 - 2024-01-27
### Added

8
apps/api/src/app/user/user.service.ts

@ -219,18 +219,18 @@ export class UserService {
new Date(),
user.createdAt
);
let frequency = 15;
let frequency = 10;
if (daysSinceRegistration > 365) {
frequency = 2;
} else if (daysSinceRegistration > 180) {
frequency = 3;
} else if (daysSinceRegistration > 60) {
frequency = 5;
frequency = 4;
} else if (daysSinceRegistration > 30) {
frequency = 8;
frequency = 6;
} else if (daysSinceRegistration > 15) {
frequency = 12;
frequency = 8;
}
if (Analytics?.activityCount % frequency === 1) {

15
apps/api/src/services/api/api.service.ts

@ -24,7 +24,7 @@ export class ApiService {
const searchQuery = filterBySearchQuery?.toLowerCase();
const tagIds = filterByTags?.split(',') ?? [];
return [
const filters = [
...accountIds.map((accountId) => {
return <Filter>{
id: accountId,
@ -43,10 +43,6 @@ export class ApiService {
type: 'ASSET_SUB_CLASS'
};
}),
{
id: searchQuery,
type: 'SEARCH_QUERY'
},
...tagIds.map((tagId) => {
return <Filter>{
id: tagId,
@ -54,5 +50,14 @@ export class ApiService {
};
})
];
if (searchQuery) {
filters.push({
id: searchQuery,
type: 'SEARCH_QUERY'
});
}
return filters;
}
}

2
apps/client/src/app/app.component.html

@ -38,7 +38,7 @@
[pageTitle]="pageTitle"
[user]="user"
(signOut)="onSignOut()"
></gf-header>
/>
</header>
<main role="main">

16
apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html

@ -4,7 +4,7 @@
[deviceType]="data.deviceType"
[title]="name"
(closeButtonClicked)="onClose()"
></gf-dialog-header>
/>
<div class="flex-grow-1" mat-dialog-content>
<div class="container p-0">
@ -16,7 +16,7 @@
[locale]="user?.settings?.locale"
[unit]="user?.settings?.baseCurrency"
[value]="valueInBaseCurrency"
></gf-value>
/>
</div>
</div>
@ -28,7 +28,7 @@
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
[isLoading]="isLoadingChart"
[locale]="user?.settings?.locale"
></gf-investment-chart>
/>
</div>
<div class="mb-3 row">
@ -79,7 +79,7 @@
[deviceType]="data.deviceType"
[holdings]="holdings"
[locale]="user?.settings?.locale"
></gf-holdings-table>
/>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
@ -102,7 +102,7 @@
[totalItems]="totalItems"
(export)="onExport()"
(sortChanged)="onSortChanged($event)"
></gf-activities-table-lazy>
/>
<gf-activities-table
*ngIf="user?.settings?.isExperimentalFeatures !== true"
[activities]="activities"
@ -115,7 +115,7 @@
[locale]="user?.settings?.locale"
[showActions]="false"
(export)="onExport()"
></gf-activities-table>
/>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
@ -128,7 +128,7 @@
[locale]="user?.settings?.locale"
[showActions]="!hasImpersonationId && hasPermissionToDeleteAccountBalance && !user.settings.isRestrictedView"
(accountBalanceDeleted)="onDeleteAccountBalance($event)"
></gf-account-balances>
/>
</mat-tab>
</mat-tab-group>
</div>
@ -138,4 +138,4 @@
mat-dialog-actions
[deviceType]="data.deviceType"
(closeButtonClicked)="onClose()"
></gf-dialog-footer>
/>

18
apps/client/src/app/components/accounts-table/accounts-table.component.html

@ -39,7 +39,7 @@
class="d-inline d-sm-none mr-1"
[tooltip]="element.Platform?.name"
[url]="element.Platform?.url"
></gf-symbol-icon>
/>
<span>{{ element.name }} </span>
<span
*ngIf="element.isDefault"
@ -83,7 +83,7 @@
class="mr-1"
[tooltip]="element.Platform?.name"
[url]="element.Platform?.url"
></gf-symbol-icon>
/>
<span>{{ element.Platform?.name }}</span>
</div>
</td>
@ -131,7 +131,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="element.balance"
></gf-value>
/>
</td>
<td
*matFooterCellDef
@ -143,7 +143,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="totalBalanceInBaseCurrency"
></gf-value>
/>
</td>
</ng-container>
@ -166,7 +166,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="element.value"
></gf-value>
/>
</td>
<td
*matFooterCellDef
@ -178,7 +178,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="totalValueInBaseCurrency"
></gf-value>
/>
</td>
</ng-container>
@ -201,7 +201,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="element.valueInBaseCurrency"
></gf-value>
/>
</td>
<td
*matFooterCellDef
@ -213,7 +213,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="totalValueInBaseCurrency"
></gf-value>
/>
</td>
</ng-container>
@ -296,4 +296,4 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>

2
apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.html

@ -8,7 +8,7 @@
[showXAxis]="true"
[showYAxis]="true"
[symbol]="symbol"
></gf-line-chart>
/>
<div
*ngFor="let itemByMonth of marketDataByMonth | keyvalue"
class="d-flex"

4
apps/client/src/app/components/admin-market-data/admin-market-data.html

@ -6,7 +6,7 @@
[isLoading]="isLoading"
[placeholder]="placeholder"
(valueChanged)="filters$.next($event)"
></gf-activities-filter>
/>
</div>
</div>
<div class="row">
@ -213,7 +213,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
</div>
</div>

6
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

@ -50,7 +50,7 @@
[marketData]="marketDataDetails"
[symbol]="data.symbol"
(marketDataChanged)="onMarketDataChanged($event)"
></gf-admin-market-data-detail>
/>
<div class="mt-3" formGroupName="historicalData">
<mat-form-field appearance="outline" class="w-100 without-hint">
@ -162,7 +162,7 @@
[keys]="['name']"
[maxItems]="10"
[positions]="sectors"
></gf-portfolio-proportion-chart>
/>
</div>
<div class="col-md-6 mb-3">
<div class="h5" i18n>Countries</div>
@ -172,7 +172,7 @@
[keys]="['name']"
[maxItems]="10"
[positions]="countries"
></gf-portfolio-proportion-chart>
/>
</div>
</ng-template>
</ng-container>

11
apps/client/src/app/components/admin-overview/admin-overview.html

@ -16,7 +16,7 @@
[locale]="user?.settings?.locale"
[precision]="0"
[value]="userCount"
></gf-value>
/>
</div>
</div>
<div class="d-flex my-3">
@ -26,7 +26,7 @@
[locale]="user?.settings?.locale"
[precision]="0"
[value]="transactionCount"
></gf-value>
/>
<div *ngIf="transactionCount && userCount">
{{ transactionCount / userCount | number : '1.2-2' }}
<span i18n>per User</span>
@ -39,10 +39,7 @@
<table>
<tr *ngFor="let exchangeRate of exchangeRates">
<td>
<gf-value
[locale]="user?.settings?.locale"
[value]="1"
></gf-value>
<gf-value [locale]="user?.settings?.locale" [value]="1" />
</td>
<td class="pl-1">{{ exchangeRate.label1 }}</td>
<td class="px-1">=</td>
@ -52,7 +49,7 @@
[locale]="user?.settings?.locale"
[precision]="4"
[value]="exchangeRate.value"
></gf-value>
/>
</td>
<td class="pl-1">{{ exchangeRate.label2 }}</td>
<td>

2
apps/client/src/app/components/admin-platform/admin-platform.component.html

@ -35,7 +35,7 @@
class="d-inline mr-1"
[tooltip]="element.name"
[url]="element.url"
></gf-symbol-icon>
/>
<span>{{ element.name }}</span>
</td></ng-container
>

8
apps/client/src/app/components/admin-users/admin-users.html

@ -46,7 +46,7 @@
class="ml-1"
[enableLink]="false"
[title]="'Expires ' + formatDistanceToNow(element.subscription.expiresAt) + ' (' + (element.subscription.expiresAt | date: defaultDateFormat) + ')'"
></gf-premium-indicator>
/>
</div>
</td>
</ng-container>
@ -107,7 +107,7 @@
class="d-inline-block justify-content-end"
[locale]="user?.settings?.locale"
[value]="element.accountCount"
></gf-value>
/>
</td>
</ng-container>
@ -128,7 +128,7 @@
class="d-inline-block justify-content-end"
[locale]="user?.settings?.locale"
[value]="element.transactionCount"
></gf-value>
/>
</td>
</ng-container>
@ -153,7 +153,7 @@
[locale]="user?.settings?.locale"
[precision]="0"
[value]="element.engagement"
></gf-value>
/>
</td>
</ng-container>

4
apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html

@ -7,7 +7,7 @@
<gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</div>
</div>
<div class="col-md-6 col-xs-12 d-flex justify-content-end">
@ -50,7 +50,7 @@
height: '100%',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<canvas
#chartCanvas
class="h-100"

2
apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html

@ -19,5 +19,5 @@
[theme]="{
height: '100%'
}"
></ngx-skeleton-loader>
/>
</div>

30
apps/client/src/app/components/header/header.component.html

@ -7,7 +7,7 @@
[ngClass]="{ 'w-100': hasTabs }"
[routerLink]="['/']"
>
<gf-logo class="px-2" [label]="pageTitle"></gf-logo>
<gf-logo class="px-2" [label]="pageTitle" />
</a>
</div>
<span class="spacer"></span>
@ -165,6 +165,32 @@
/>
</button>
<mat-menu #accountMenu="matMenu" xPosition="before">
<ng-container
*ngIf="
hasPermissionForSubscription &&
user?.subscription?.type === 'Basic'
"
>
<a class="d-flex" mat-menu-item [routerLink]="routerLinkPricing"
><span class="align-items-center d-flex"
><span
><ng-container
*ngIf="user.subscription.offer === 'default'"
i18n
>Upgrade Plan</ng-container
>
<ng-container
*ngIf="user.subscription.offer === 'renewal'"
i18n
>Renew Plan</ng-container
></span
>
<gf-premium-indicator
class="d-inline-block ml-1"
[enableLink]="false" /></span
></a>
<hr class="m-0" />
</ng-container>
<ng-container *ngIf="user?.access?.length > 0">
<button mat-menu-item (click)="impersonateAccount(null)">
<span class="align-items-center d-flex">
@ -295,7 +321,7 @@
class="px-2"
[label]="pageTitle"
[showLabel]="currentRoute !== 'register'"
></gf-logo>
/>
</a>
</div>
<span class="spacer"></span>

2
apps/client/src/app/components/header/header.module.ts

@ -7,6 +7,7 @@ import { RouterModule } from '@angular/router';
import { LoginWithAccessTokenDialogModule } from '@ghostfolio/client/components/login-with-access-token-dialog/login-with-access-token-dialog.module';
import { GfAssistantModule } from '@ghostfolio/ui/assistant';
import { GfLogoModule } from '@ghostfolio/ui/logo';
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
import { HeaderComponent } from './header.component';
@ -17,6 +18,7 @@ import { HeaderComponent } from './header.component';
CommonModule,
GfAssistantModule,
GfLogoModule,
GfPremiumIndicatorModule,
LoginWithAccessTokenDialogModule,
MatButtonModule,
MatMenuModule,

4
apps/client/src/app/components/home-holdings/home-holdings.html

@ -5,7 +5,7 @@
[isLoading]="positions === undefined"
[options]="dateRangeOptions"
(change)="onChangeDateRange($event.value)"
></gf-toggle>
/>
</div>
<div class="row">
<div class="align-items-center col-xs-12 col-md-8 offset-md-2">
@ -18,7 +18,7 @@
[locale]="user?.settings?.locale"
[positions]="positions"
[range]="user?.settings?.dateRange"
></gf-positions>
/>
</mat-card-content>
</mat-card>
<div *ngIf="hasPermissionToCreateOrder" class="text-center">

8
apps/client/src/app/components/home-market/home-market.html

@ -18,11 +18,11 @@
[yMaxLabel]="greedLabel"
[yMin]="0"
[yMinLabel]="fearLabel"
></gf-line-chart>
/>
<gf-fear-and-greed-index
class="d-flex justify-content-center"
[fearAndGreedIndex]="fearAndGreedIndex"
></gf-fear-and-greed-index>
/>
</div>
</div>
@ -32,7 +32,7 @@
[benchmarks]="benchmarks"
[locale]="user?.settings?.locale"
[user]="user"
></gf-benchmark>
/>
<ngx-skeleton-loader
*ngIf="isLoading"
animation="pulse"
@ -41,7 +41,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
</div>
</div>
</div>

6
apps/client/src/app/components/home-overview/home-overview.html

@ -78,7 +78,7 @@
[showLoader]="false"
[showXAxis]="false"
[showYAxis]="false"
></gf-line-chart>
/>
</div>
</div>
</div>
@ -95,7 +95,7 @@
[performance]="performance"
[showDetails]="showDetails"
[unit]="unit"
></gf-portfolio-performance>
/>
<div
*ngIf="showDetails && !user?.settings?.isExperimentalFeatures"
class="text-center"
@ -105,7 +105,7 @@
[isLoading]="isLoadingPerformance"
[options]="dateRangeOptions"
(change)="onChangeDateRange($event.value)"
></gf-toggle>
/>
</div>
</div>
</div>

2
apps/client/src/app/components/home-summary/home-summary.html

@ -12,7 +12,7 @@
[locale]="user?.settings?.locale"
[summary]="summary"
(emergencyFundChanged)="onChangeEmergencyFund($event)"
></gf-portfolio-summary>
/>
</mat-card-content>
</mat-card>
</div>

2
apps/client/src/app/components/investment-chart/investment-chart.component.html

@ -5,7 +5,7 @@
height: '100%',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<canvas
#chartCanvas
class="h-100"

2
apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html

@ -2,7 +2,7 @@
mat-dialog-title
[title]="data.title"
(closeButtonClicked)="onClose()"
></gf-dialog-header>
/>
<div class="py-3" mat-dialog-content>
<div class="align-items-center d-flex flex-column">

6
apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html

@ -18,7 +18,7 @@
height: '4rem',
width: '15rem'
}"
></ngx-skeleton-loader>
/>
</div>
<div
class="display-4 font-weight-bold m-0 text-center value-container"
@ -41,7 +41,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : performance?.currentNetPerformance"
></gf-value>
/>
</div>
<div class="col">
<gf-value
@ -51,7 +51,7 @@
[value]="
isLoading ? undefined : performance?.currentNetPerformancePercent
"
></gf-value>
/>
</div>
</div>
</div>

42
apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html

@ -2,7 +2,7 @@
<div class="flex-nowrap px-3 py-1 row">
<div class="flex-grow-1 text-truncate" i18n>Time in Market</div>
<div class="justify-content-end">
<gf-value class="justify-content-end" [value]="timeInMarket"></gf-value>
<gf-value class="justify-content-end" [value]="timeInMarket" />
</div>
</div>
<div
@ -26,7 +26,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.totalBuy"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -38,7 +38,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.totalSell"
></gf-value>
/>
</div>
</div>
<div class="row">
@ -53,7 +53,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.committedFunds"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -65,7 +65,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.currentGrossPerformance"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -87,7 +87,7 @@
[value]="
isLoading ? undefined : summary?.currentGrossPerformancePercent
"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -100,7 +100,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.fees"
></gf-value>
/>
</div>
</div>
<div class="row">
@ -115,7 +115,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.currentNetPerformance"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -135,7 +135,7 @@
[isPercent]="true"
[locale]="locale"
[value]="isLoading ? undefined : summary?.currentNetPerformancePercent"
></gf-value>
/>
</div>
</div>
<div class="row">
@ -151,7 +151,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.currentValue"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -163,7 +163,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.items"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -184,7 +184,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.emergencyFund?.total"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -197,7 +197,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.emergencyFund?.cash"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -210,7 +210,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.emergencyFund?.assets"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -222,7 +222,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.cash"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -234,7 +234,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.excludedAccountsAndActivities"
></gf-value>
/>
</div>
</div>
<div class="row">
@ -254,7 +254,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.liabilities"
></gf-value>
/>
</div>
</div>
<div class="row">
@ -269,7 +269,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.netWorth"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -284,7 +284,7 @@
[isPercent]="true"
[locale]="locale"
[value]="isLoading ? undefined : summary?.annualizedPerformancePercent"
></gf-value>
/>
</div>
</div>
<div class="row">
@ -299,7 +299,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.interest"
></gf-value>
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
@ -311,7 +311,7 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.dividend"
></gf-value>
/>
</div>
</div>
</div>

16
apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html

@ -4,7 +4,7 @@
[deviceType]="data.deviceType"
[title]="SymbolProfile?.name ?? SymbolProfile?.symbol"
(closeButtonClicked)="onClose()"
></gf-dialog-header>
/>
<div class="flex-grow-1" mat-dialog-content>
<div class="container p-0">
@ -16,7 +16,7 @@
[locale]="data.locale"
[unit]="data.baseCurrency"
[value]="value"
></gf-value>
/>
</div>
</div>
@ -33,7 +33,7 @@
[showXAxis]="true"
[showYAxis]="true"
[symbol]="data.symbol"
></gf-line-chart>
/>
<div class="row">
<div class="col-6 mb-3">
@ -222,7 +222,7 @@
[locale]="data.locale"
[maxItems]="10"
[positions]="sectors"
></gf-portfolio-proportion-chart>
/>
</div>
<div class="col-md-6 mb-3">
<div class="h5" i18n>Countries</div>
@ -234,7 +234,7 @@
[locale]="data.locale"
[maxItems]="10"
[positions]="countries"
></gf-portfolio-proportion-chart>
/>
</div>
</ng-template>
</ng-container>
@ -266,7 +266,7 @@
[sortDisabled]="true"
[totalItems]="totalItems"
(export)="onExport()"
></gf-activities-table-lazy>
/>
<gf-activities-table
*ngIf="user?.settings?.isExperimentalFeatures !== true"
[activities]="activities"
@ -280,7 +280,7 @@
[showActions]="false"
[showNameColumn]="false"
(export)="onExport()"
></gf-activities-table>
/>
</div>
</div>
@ -314,4 +314,4 @@
mat-dialog-actions
[deviceType]="data.deviceType"
(closeButtonClicked)="onClose()"
></gf-dialog-footer>
/>

10
apps/client/src/app/components/position/position.component.html

@ -18,7 +18,7 @@
[marketState]="position?.marketState"
[range]="range"
[value]="position?.netPerformancePercentage"
></gf-trend-indicator>
/>
</div>
<div *ngIf="isLoading" class="flex-grow-1">
<ngx-skeleton-loader
@ -28,14 +28,14 @@
height: '1.2rem',
width: '12rem'
}"
></ngx-skeleton-loader>
/>
<ngx-skeleton-loader
animation="pulse"
[theme]="{
height: '1rem',
width: '8rem'
}"
></ngx-skeleton-loader>
/>
</div>
<div *ngIf="!isLoading" class="flex-grow-1 text-truncate">
<div class="h6 m-0 text-truncate">{{ position?.name }}</div>
@ -50,13 +50,13 @@
[locale]="locale"
[unit]="baseCurrency"
[value]="position?.netPerformance"
></gf-value>
/>
<gf-value
[colorizeSign]="true"
[isPercent]="true"
[locale]="locale"
[value]="position?.netPerformancePercentage"
></gf-value>
/>
</div>
</div>
<div class="align-items-center d-flex">

10
apps/client/src/app/components/positions/positions.component.html

@ -2,7 +2,7 @@
<div class="row no-gutters">
<div class="col">
<ng-container *ngIf="positions === undefined">
<gf-position [isLoading]="true"></gf-position>
<gf-position [isLoading]="true" />
</ng-container>
<ng-container *ngIf="positions !== undefined">
<ng-container *ngIf="hasPositions">
@ -13,7 +13,7 @@
[locale]="locale"
[position]="position"
[range]="range"
></gf-position>
/>
<gf-position
*ngFor="let position of positionsRest"
[baseCurrency]="baseCurrency"
@ -21,15 +21,13 @@
[locale]="locale"
[position]="position"
[range]="range"
></gf-position>
/>
</ng-container>
<div
*ngIf="hasPermissionToCreateOrder && !hasPositions"
class="p-3 text-center"
>
<gf-no-transactions-info-indicator
[hasBorder]="false"
></gf-no-transactions-info-indicator>
<gf-no-transactions-info-indicator [hasBorder]="false" />
</div>
</ng-container>
</div>

6
apps/client/src/app/components/rule/rule.component.html

@ -8,7 +8,7 @@
height: '2rem',
width: '2rem'
}"
></ngx-skeleton-loader>
/>
</div>
<div
*ngIf="!isLoading"
@ -26,14 +26,14 @@
height: '1rem',
width: '10rem'
}"
></ngx-skeleton-loader>
/>
<ngx-skeleton-loader
animation="pulse"
[theme]="{
height: '1rem',
width: '15rem'
}"
></ngx-skeleton-loader>
/>
</div>
<div *ngIf="!isLoading" class="flex-grow-1">
<div class="h6 my-1">{{ rule?.name }}</div>

10
apps/client/src/app/components/rules/rules.component.html

@ -7,15 +7,13 @@
class="my-2 text-center"
>
<mat-card-content>
<gf-no-transactions-info-indicator
[hasBorder]="false"
></gf-no-transactions-info-indicator
></mat-card-content>
<gf-no-transactions-info-indicator [hasBorder]="false" />
</mat-card-content>
</mat-card>
<gf-rule *ngIf="rules?.length === 0" [isLoading]="true"></gf-rule>
<gf-rule *ngIf="rules?.length === 0" [isLoading]="true" />
<ng-container *ngIf="rules !== null && rules !== undefined">
<gf-rule *ngFor="let rule of rules" [rule]="rule"></gf-rule>
<gf-rule *ngFor="let rule of rules" [rule]="rule" />
</ng-container>
</div>
</div>

5
apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html

@ -7,10 +7,7 @@
<div>
<h5 class="align-items-center d-flex justify-content-center mb-3">
<span>Ghostfolio Premium</span>
<gf-premium-indicator
class="ml-1"
[enableLink]="false"
></gf-premium-indicator>
<gf-premium-indicator class="ml-1" [enableLink]="false" />
</h5>
<div class="font-weight-normal h5 mb-3 text-center" i18n>
Are you an ambitious investor who needs the full picture?

4
apps/client/src/app/components/user-account-access/user-account-access.html

@ -6,13 +6,13 @@
<gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</h1>
<gf-access-table
[accesses]="accesses"
[showActions]="hasPermissionToDeleteAccess"
(accessDeleted)="onDeleteAccess($event)"
></gf-access-table>
/>
<div *ngIf="hasPermissionToCreateAccess" class="fab-container">
<a
class="align-items-center d-flex justify-content-center"

10
apps/client/src/app/components/user-account-membership/user-account-membership.html

@ -5,7 +5,7 @@
<gf-membership-card
[expiresAt]="user?.subscription?.expiresAt | date: defaultDateFormat"
[name]="user?.subscription?.type"
></gf-membership-card>
/>
<div
*ngIf="user?.subscription?.type === 'Basic'"
class="d-flex flex-column mt-5"
@ -15,10 +15,10 @@
>
<button color="primary" mat-flat-button (click)="onCheckout()">
<ng-container *ngIf="user.subscription.offer === 'default'" i18n
>Upgrade</ng-container
>Upgrade Plan</ng-container
>
<ng-container *ngIf="user.subscription.offer === 'renewal'" i18n
>Renew</ng-container
>Renew Plan</ng-container
>
</button>
<div *ngIf="price" class="mt-1 text-center">
@ -43,8 +43,8 @@
<gf-premium-indicator
class="d-inline-block ml-1"
[enableLink]="false"
></gf-premium-indicator
></a>
/>
</a>
<a
*ngIf="hasPermissionToUpdateUserSettings"
class="mx-1"

2
apps/client/src/app/components/world-map-chart/world-map-chart.component.html

@ -5,6 +5,6 @@
[theme]="{
width: '100%'
}"
></ngx-skeleton-loader>
/>
<div class="align-items-center d-flex h-100 w-100" id="svgMap"></div>

2
apps/client/src/app/pages/accounts/accounts-page.html

@ -15,7 +15,7 @@
(accountDeleted)="onDeleteAccount($event)"
(accountToUpdate)="onUpdateAccount($event)"
(transferBalance)="onTransferBalance()"
></gf-accounts-table>
/>
</div>
</div>
</div>

2
apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html

@ -61,7 +61,7 @@
class="mr-1"
[tooltip]="platformEntry.name"
[url]="platformEntry.url"
></gf-symbol-icon>
/>
<span>{{ platformEntry.name }}</span>
</span>
</mat-option>

6
apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html

@ -17,8 +17,7 @@
class="mr-1"
[tooltip]="account.Platform?.name"
[url]="account.Platform?.url"
></gf-symbol-icon
><span>{{ account.name }}</span>
/><span>{{ account.name }}</span>
</div>
</mat-option>
</mat-select>
@ -35,8 +34,7 @@
class="mr-1"
[tooltip]="account.Platform?.name"
[url]="account.Platform?.url"
></gf-symbol-icon
><span>{{ account.name }}</span>
/><span>{{ account.name }}</span>
</div>
</mat-option>
</mat-select>

4
apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html

@ -20,8 +20,8 @@
<gf-premium-indicator
class="d-inline-block ml-1"
[enableLink]="false"
></gf-premium-indicator
></span>
/>
</span>
annual plan for ambitious investors who need the full picture of
their financial assets.
</p>

4
apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html

@ -21,8 +21,8 @@
<gf-premium-indicator
class="d-inline-block ml-1"
[enableLink]="false"
></gf-premium-indicator
></span>
/>
</span>
annual plan with our exclusive Black Week deal. Elevate your
financial strategy with the power of Ghostfolio designed to give you
the full picture of your assets.

8
apps/client/src/app/pages/features/features-page.html

@ -142,7 +142,7 @@
<gf-premium-indicator
*ngIf="hasPermissionForSubscription"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<p class="m-0">
Check the rate of return of your portfolio for
@ -162,7 +162,7 @@
<gf-premium-indicator
*ngIf="hasPermissionForSubscription"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<p class="m-0">
Check the allocations of your portfolio by account, asset
@ -207,7 +207,7 @@
<div class="flex-grow-1">
<h4 class="align-items-center d-flex">
<span i18n>Market Mood</span>
<gf-premium-indicator class="ml-1"></gf-premium-indicator>
<gf-premium-indicator class="ml-1" />
</h4>
<p class="m-0">
Check the current market mood (<a
@ -228,7 +228,7 @@
<gf-premium-indicator
*ngIf="hasPermissionForSubscription"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<p class="m-0">
Identify potential risks in your portfolio with Ghostfolio

13
apps/client/src/app/pages/landing/landing-page.html

@ -328,11 +328,7 @@
<gf-carousel [aria-label]="'Testimonials'">
<div *ngFor="let testimonial of testimonials" gf-carousel-item>
<div class="d-flex px-4">
<gf-logo
class="mr-3 mt-2 pt-1"
size="medium"
[showLabel]="false"
></gf-logo>
<gf-logo class="mr-3 mt-2 pt-1" size="medium" [showLabel]="false" />
<div>
<div>{{ testimonial.quote }}</div>
<div class="mt-2 text-muted">
@ -361,10 +357,7 @@
</h2>
</div>
<div class="col-md-8 customer-map-container offset-md-2">
<gf-world-map-chart
format="👻"
[countries]="countriesOfSubscribersMap"
></gf-world-map-chart>
<gf-world-map-chart format="👻" [countries]="countriesOfSubscribersMap" />
</div>
</div>
@ -450,7 +443,7 @@
<div
class="align-items-center d-flex flex-column justify-content-center w-100"
>
<gf-logo size="medium"></gf-logo>
<gf-logo size="medium" />
<div>Wealth Management Software</div>
</div>
</div>

2
apps/client/src/app/pages/markets/markets-page.html

@ -1,7 +1,7 @@
<div class="container">
<div class="row">
<div class="col">
<gf-home-market></gf-home-market>
<gf-home-market />
</div>
</div>
</div>

4
apps/client/src/app/pages/portfolio/activities/activities-page.html

@ -26,7 +26,7 @@
(importDividends)="onImportDividends()"
(pageChanged)="onChangePage($event)"
(sortChanged)="onSortChanged($event)"
></gf-activities-table-lazy>
/>
<gf-activities-table
*ngIf="user?.settings?.isExperimentalFeatures !== true"
[activities]="activities"
@ -44,7 +44,7 @@
(exportDrafts)="onExportDrafts($event)"
(import)="onImport()"
(importDividends)="onImportDividends()"
></gf-activities-table>
/>
</div>
</div>

5
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html

@ -82,8 +82,7 @@
class="mr-1"
[tooltip]="account.Platform?.name"
[url]="account.Platform?.url"
></gf-symbol-icon
><span>{{ account.name }}</span>
/><span>{{ account.name }}</span>
</div>
</mat-option>
</mat-select>
@ -357,7 +356,7 @@
[locale]="data.user?.settings?.locale"
[unit]="activityForm.controls['currency']?.value ?? data.user?.settings?.baseCurrency"
[value]="total"
></gf-value>
/>
<div>
<button i18n mat-button type="button" (click)="onCancel()">Cancel</button>
<button

8
apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html

@ -3,7 +3,7 @@
[deviceType]="data.deviceType"
[title]="dialogTitle"
(closeButtonClicked)="onCancel()"
></gf-dialog-header>
/>
<div class="flex-grow-1" mat-dialog-content>
<mat-stepper
@ -136,7 +136,7 @@
[sortDisabled]="true"
[totalItems]="totalItems"
(selectedActivities)="updateSelection($event)"
></gf-activities-table-lazy>
/>
<gf-activities-table
*ngIf="importStep === 1 && data?.user?.settings?.isExperimentalFeatures !== true"
[activities]="activities"
@ -153,7 +153,7 @@
[showFooter]="false"
[showSymbolColumn]="false"
(selectedActivities)="updateSelection($event)"
></gf-activities-table>
/>
<div class="d-flex justify-content-end mt-3">
<button mat-button (click)="onReset(stepper)">
<ng-container i18n>Back</ng-container>
@ -214,4 +214,4 @@
mat-dialog-actions
[deviceType]="data.deviceType"
(closeButtonClicked)="onCancel()"
></gf-dialog-footer>
/>

111
apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts

@ -148,9 +148,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
this.initialize();
return this.dataService.fetchPortfolioDetails({
filters: this.activeFilters
});
return this.fetchPortfolioDetails();
}),
takeUntil(this.unsubscribeSubject)
)
@ -159,7 +157,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
this.portfolioDetails = portfolioDetails;
this.initializeAnalysisData();
this.initializeAllocationsData();
this.isLoading = false;
@ -210,6 +208,26 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
? `{0}%`
: `{0} ${this.user?.settings?.baseCurrency}`;
if (this.user?.settings?.isExperimentalFeatures === true) {
this.isLoading = true;
this.initialize();
this.fetchPortfolioDetails()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((portfolioDetails) => {
this.initialize();
this.portfolioDetails = portfolioDetails;
this.initializeAllocationsData();
this.isLoading = false;
this.changeDetectorRef.markForCheck();
});
}
this.changeDetectorRef.markForCheck();
}
});
@ -217,7 +235,52 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
this.initialize();
}
public initialize() {
public onAccountChartClicked({ symbol }: UniqueAsset) {
if (symbol && symbol !== UNKNOWN_KEY) {
this.router.navigate([], {
queryParams: { accountId: symbol, accountDetailDialog: true }
});
}
}
public onSymbolChartClicked({ dataSource, symbol }: UniqueAsset) {
if (dataSource && symbol) {
this.router.navigate([], {
queryParams: { dataSource, symbol, positionDetailDialog: true }
});
}
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private extractEtfProvider({
assetSubClass,
name
}: {
assetSubClass: PortfolioPosition['assetSubClass'];
name: string;
}) {
if (assetSubClass === 'ETF') {
const [firstWord] = name.split(' ');
return firstWord;
}
return UNKNOWN_KEY;
}
private fetchPortfolioDetails() {
return this.dataService.fetchPortfolioDetails({
filters:
this.activeFilters.length > 0
? this.activeFilters
: this.userService.getFilters()
});
}
private initialize() {
this.accounts = {};
this.continents = {
[UNKNOWN_KEY]: {
@ -310,7 +373,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
};
}
public initializeAnalysisData() {
private initializeAllocationsData() {
for (const [
id,
{ name, valueInBaseCurrency, valueInPercentage }
@ -540,27 +603,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
this.markets[UNKNOWN_KEY].value / marketsTotal;
}
public onAccountChartClicked({ symbol }: UniqueAsset) {
if (symbol && symbol !== UNKNOWN_KEY) {
this.router.navigate([], {
queryParams: { accountId: symbol, accountDetailDialog: true }
});
}
}
public onSymbolChartClicked({ dataSource, symbol }: UniqueAsset) {
if (dataSource && symbol) {
this.router.navigate([], {
queryParams: { dataSource, symbol, positionDetailDialog: true }
});
}
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private openAccountDetailDialog(aAccountId: string) {
const dialogRef = this.dialog.open(AccountDetailDialog, {
autoFocus: false,
@ -621,19 +663,4 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
});
});
}
private extractEtfProvider({
assetSubClass,
name
}: {
assetSubClass: PortfolioPosition['assetSubClass'];
name: string;
}) {
if (assetSubClass === 'ETF') {
const [firstWord] = name.split(' ');
return firstWord;
}
return UNKNOWN_KEY;
}
}

60
apps/client/src/app/pages/portfolio/allocations/allocations-page.html

@ -2,12 +2,14 @@
<div class="row">
<div class="col">
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Allocations</h1>
@if (!user?.settings?.isExperimentalFeatures) {
<gf-activities-filter
[allFilters]="allFilters"
[isLoading]="isLoading"
[placeholder]="placeholder"
(valueChanged)="filters$.next($event)"
></gf-activities-filter>
/>
}
</div>
</div>
<div class="row">
@ -22,7 +24,7 @@
size="medium"
[isPercent]="true"
[value]="isLoading ? undefined : portfolioDetails?.filteredValueInPercentage"
></gf-value>
/>
</mat-card-header>
<mat-card-content>
<mat-progress-bar
@ -50,7 +52,7 @@
[keys]="['id']"
[locale]="user?.settings?.locale"
[positions]="platforms"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -62,8 +64,8 @@
<gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator
></mat-card-title>
/>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<gf-portfolio-proportion-chart
@ -73,7 +75,7 @@
[keys]="['currency']"
[locale]="user?.settings?.locale"
[positions]="positions"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -85,8 +87,8 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator
></mat-card-title>
/>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<gf-portfolio-proportion-chart
@ -96,7 +98,7 @@
[keys]="['assetClassLabel', 'assetSubClassLabel']"
[locale]="user?.settings?.locale"
[positions]="positions"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -119,7 +121,7 @@
[positions]="symbols"
[showLabels]="deviceType !== 'mobile'"
(proportionChartClicked)="onSymbolChartClicked($event)"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -131,8 +133,8 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator
></mat-card-title>
/>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<gf-portfolio-proportion-chart
@ -143,7 +145,7 @@
[locale]="user?.settings?.locale"
[maxItems]="10"
[positions]="sectors"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -155,8 +157,8 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator
></mat-card-title>
/>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<gf-portfolio-proportion-chart
@ -166,7 +168,7 @@
[keys]="['name']"
[locale]="user?.settings?.locale"
[positions]="continents"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -178,8 +180,8 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator
></mat-card-title>
/>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<gf-portfolio-proportion-chart
@ -188,7 +190,7 @@
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
[locale]="user?.settings?.locale"
[positions]="marketsAdvanced"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -202,8 +204,8 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator
></mat-card-title>
/>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="world-map-chart-container">
@ -212,7 +214,7 @@
[format]="worldMapChartFormat"
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
[locale]="user?.settings?.locale"
></gf-world-map-chart>
/>
</div>
<div class="row">
<div class="col-xs-12 col-md my-2">
@ -275,7 +277,7 @@
[locale]="user?.settings?.locale"
[positions]="accounts"
(proportionChartClicked)="onAccountChartClicked($event)"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -287,8 +289,8 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator
></mat-card-title>
/>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<gf-portfolio-proportion-chart
@ -298,7 +300,7 @@
[keys]="['etfProvider']"
[locale]="user?.settings?.locale"
[positions]="positions"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -310,8 +312,8 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator
></mat-card-title>
/>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<gf-portfolio-proportion-chart
@ -322,7 +324,7 @@
[locale]="user?.settings?.locale"
[maxItems]="10"
[positions]="countries"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>

42
apps/client/src/app/pages/portfolio/analysis/analysis-page.html

@ -7,14 +7,14 @@
[isLoading]="isLoadingBenchmarkComparator || isLoadingInvestmentChart"
[options]="dateRangeOptions"
(change)="onChangeDateRange($event.value)"
></gf-toggle>
/>
</div>
<gf-activities-filter
[allFilters]="allFilters"
[isLoading]="isLoadingBenchmarkComparator || isLoadingInvestmentChart"
[placeholder]="placeholder"
(valueChanged)="filters$.next($event)"
></gf-activities-filter>
/>
}
<div class="mb-5 row">
<div class="col-lg">
@ -30,7 +30,7 @@
[performanceDataItems]="performanceDataItemsInPercentage"
[user]="user"
(benchmarkChanged)="onChangeBenchmark($event)"
></gf-benchmark-comparator>
/>
</div>
</div>
@ -51,7 +51,7 @@
[locale]="user?.settings?.locale"
[unit]="user?.settings?.baseCurrency"
[value]="isLoadingInvestmentChart ? undefined : performance?.currentNetPerformance"
></gf-value>
/>
</div>
</div>
<div class="d-flex mb-3 ml-3 py-1">
@ -66,7 +66,7 @@
[isPercent]="true"
[locale]="user?.settings?.locale"
[value]="isLoadingInvestmentChart ? undefined : performance?.currentNetPerformancePercent"
></gf-value>
/>
</div>
</div>
<div class="d-flex py-1">
@ -81,7 +81,7 @@
[locale]="user?.settings?.locale"
[unit]="user?.settings?.baseCurrency"
[value]="isLoadingInvestmentChart ? undefined : (performance?.currentNetPerformanceWithCurrencyEffect === null ? null : performance?.currentNetPerformanceWithCurrencyEffect - performance?.currentNetPerformance)"
></gf-value>
/>
</div>
</div>
<div class="d-flex ml-3 py-1">
@ -96,7 +96,7 @@
[isPercent]="true"
[locale]="user?.settings?.locale"
[value]="isLoadingInvestmentChart ? undefined : performance?.currentNetPerformancePercentWithCurrencyEffect - performance?.currentNetPerformancePercent"
></gf-value>
/>
</div>
</div>
<div><hr /></div>
@ -112,7 +112,7 @@
[locale]="user?.settings?.locale"
[unit]="user?.settings?.baseCurrency"
[value]="isLoadingInvestmentChart ? undefined : performance?.currentNetPerformanceWithCurrencyEffect"
></gf-value>
/>
</div>
</div>
<div class="d-flex ml-3 py-1">
@ -127,7 +127,7 @@
[isPercent]="true"
[locale]="user?.settings?.locale"
[value]="isLoadingInvestmentChart ? undefined : performance?.currentNetPerformancePercentWithCurrencyEffect"
></gf-value>
/>
</div>
</div>
</mat-card-content>
@ -167,7 +167,7 @@
[isPercent]="true"
[locale]="user?.settings?.locale"
[value]="position.netPerformancePercentage"
></gf-value>
/>
</div>
</a>
</li>
@ -180,7 +180,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
</div>
</mat-card-content>
</mat-card>
@ -215,7 +215,7 @@
[isPercent]="true"
[locale]="user?.settings?.locale"
[value]="position.netPerformancePercentage"
></gf-value>
/>
</div>
</a>
</li>
@ -228,7 +228,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
</div>
</mat-card-content>
</mat-card>
@ -245,7 +245,7 @@
<gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</div>
</div>
<div class="chart-container">
@ -260,7 +260,7 @@
[isLoading]="isLoadingInvestmentChart"
[locale]="user?.settings?.locale"
[range]="user?.settings?.dateRange"
></gf-investment-chart>
/>
</div>
</div>
</div>
@ -275,7 +275,7 @@
<gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</div>
<gf-toggle
class="d-none d-lg-block"
@ -283,7 +283,7 @@
[isLoading]="false"
[options]="modeOptions"
(change)="onChangeGroupBy($event.value)"
></gf-toggle>
/>
</div>
<div *ngIf="streaks" class="row">
<div class="col-md-6 col-xs-12 my-2">
@ -317,7 +317,7 @@
[locale]="user?.settings?.locale"
[range]="user?.settings?.dateRange"
[savingsRate]="savingsRate"
></gf-investment-chart>
/>
</div>
</div>
</div>
@ -332,7 +332,7 @@
<gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</div>
<gf-toggle
class="d-none d-lg-block"
@ -340,7 +340,7 @@
[isLoading]="false"
[options]="modeOptions"
(change)="onChangeGroupBy($event.value)"
></gf-toggle>
/>
</div>
<div class="chart-container">
<gf-investment-chart
@ -353,7 +353,7 @@
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
[locale]="user?.settings?.locale"
[range]="user?.settings?.dateRange"
></gf-investment-chart>
/>
</div>
</div>
</div>

34
apps/client/src/app/pages/portfolio/fire/fire-page.html

@ -8,7 +8,7 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<gf-fire-calculator
[annualInterestRate]="user?.settings?.annualInterestRate"
@ -25,7 +25,7 @@
(projectedTotalAmountChanged)="onProjectedTotalAmountChange($event)"
(retirementDateChanged)="onRetirementDateChange($event)"
(savingsRateChanged)="onSavingsRateChange($event)"
></gf-fire-calculator>
/>
</div>
</div>
</div>
@ -35,7 +35,7 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<div *ngIf="isLoading">
<ngx-skeleton-loader
@ -45,14 +45,14 @@
height: '1rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<ngx-skeleton-loader
animation="pulse"
[theme]="{
height: '1rem',
width: '10rem'
}"
></ngx-skeleton-loader>
/>
</div>
<div *ngIf="!isLoading" i18n>
If you retire today, you would be able to withdraw
@ -63,7 +63,7 @@
[locale]="user?.settings?.locale"
[unit]="user?.settings?.baseCurrency"
[value]="withdrawalRatePerYear?.toNumber()"
></gf-value>
/>
per year</span
>
or
@ -74,7 +74,7 @@
[locale]="user?.settings?.locale"
[unit]="user?.settings?.baseCurrency"
[value]="withdrawalRatePerMonth?.toNumber()"
></gf-value>
/>
per month</span
>, based on your total assets of
<span class="font-weight-bold"
@ -84,8 +84,8 @@
[locale]="user?.settings?.locale"
[unit]="user?.settings?.baseCurrency"
[value]="fireWealth?.toNumber()"
></gf-value
></span>
/>
</span>
and a withdrawal rate of 4%.
</div>
</div>
@ -112,12 +112,12 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="emergencyFundRules"
></gf-rules>
/>
</div>
<div class="mb-4">
<h4 class="align-items-center d-flex m-0">
@ -125,12 +125,12 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="currencyClusterRiskRules"
></gf-rules>
/>
</div>
<div class="mb-4">
<h4 class="align-items-center d-flex m-0">
@ -138,12 +138,12 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="accountClusterRiskRules"
></gf-rules>
/>
</div>
<div>
<h4 class="align-items-center d-flex m-0">
@ -151,12 +151,12 @@
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
/>
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="feeRules"
></gf-rules>
/>
</div>
</div>
</div>

43
apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts

@ -86,16 +86,14 @@ export class HoldingsPageComponent implements OnDestroy, OnInit {
? $localize`Filter by account or tag...`
: '';
return this.dataService.fetchPortfolioDetails({
filters: this.activeFilters
});
return this.fetchPortfolioDetails();
}),
takeUntil(this.unsubscribeSubject)
)
.subscribe((portfolioDetails) => {
this.portfolioDetails = portfolioDetails;
this.initializeAnalysisData();
this.initialize();
this.isLoading = false;
@ -146,17 +144,41 @@ export class HoldingsPageComponent implements OnDestroy, OnInit {
...tagFilters
];
if (this.user?.settings?.isExperimentalFeatures === true) {
this.holdings = undefined;
this.fetchPortfolioDetails()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((portfolioDetails) => {
this.portfolioDetails = portfolioDetails;
this.initialize();
this.changeDetectorRef.markForCheck();
});
}
this.changeDetectorRef.markForCheck();
}
});
}
public initialize() {
this.holdings = [];
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
public initializeAnalysisData() {
this.initialize();
private fetchPortfolioDetails() {
return this.dataService.fetchPortfolioDetails({
filters:
this.activeFilters.length > 0
? this.activeFilters
: this.userService.getFilters()
});
}
private initialize() {
this.holdings = [];
for (const [symbol, holding] of Object.entries(
this.portfolioDetails.holdings
@ -165,11 +187,6 @@ export class HoldingsPageComponent implements OnDestroy, OnInit {
}
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private openPositionDialog({
dataSource,
symbol

6
apps/client/src/app/pages/portfolio/holdings/holdings-page.html

@ -2,12 +2,14 @@
<div class="row">
<div class="col">
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Holdings</h1>
@if (!user?.settings?.isExperimentalFeatures) {
<gf-activities-filter
[allFilters]="allFilters"
[isLoading]="isLoading"
[placeholder]="placeholder"
(valueChanged)="filters$.next($event)"
></gf-activities-filter>
/>
}
</div>
</div>
<div class="row">
@ -18,7 +20,7 @@
[hasPermissionToCreateActivity]="hasPermissionToCreateOrder"
[holdings]="holdings"
[locale]="user?.settings?.locale"
></gf-holdings-table>
/>
<div
*ngIf="hasPermissionToCreateOrder && holdings?.length > 0"
class="text-center"

5
apps/client/src/app/pages/pricing/pricing-page.html

@ -171,10 +171,7 @@
<div class="align-items-center d-flex mb-2">
<h4 class="align-items-center d-flex flex-grow-1 m-0">
<span>Premium</span>
<gf-premium-indicator
class="ml-1"
[enableLink]="false"
></gf-premium-indicator>
<gf-premium-indicator class="ml-1" [enableLink]="false" />
</h4>
<div *ngIf="user?.subscription?.type === 'Premium'">
<ion-icon class="mr-1" name="checkmark-outline" />

12
apps/client/src/app/pages/public/public-page.html

@ -20,7 +20,7 @@
[keys]="['symbol']"
[positions]="symbols"
[showLabels]="deviceType !== 'mobile'"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -35,7 +35,7 @@
[keys]="['currency']"
[maxItems]="10"
[positions]="positions"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -50,7 +50,7 @@
[keys]="['name']"
[maxItems]="10"
[positions]="sectors"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -64,7 +64,7 @@
[isInPercent]="true"
[keys]="['name']"
[positions]="continents"
></gf-portfolio-proportion-chart>
/>
</mat-card-content>
</mat-card>
</div>
@ -81,7 +81,7 @@
format="{0}%"
[countries]="countries"
[isInPercent]="true"
></gf-world-map-chart>
/>
</div>
<div class="row">
<div class="col-xs-12 col-md my-2">
@ -135,7 +135,7 @@
[hasPermissionToShowValues]="false"
[holdings]="holdings"
[pageSize]="7"
></gf-holdings-table>
/>
</div>
</div>
<div class="row my-5">

2
apps/client/src/app/pages/register/register-page.html

@ -9,7 +9,7 @@
<div
class="align-items-center d-flex flex-column justify-content-center w-100"
>
<gf-logo size="large"></gf-logo>
<gf-logo size="large" />
<p class="lead m-0">Wealth Management Software</p>
</div>
</div>

2
apps/client/src/app/pages/webauthn/webauthn-page.html

@ -4,7 +4,7 @@
<div
class="align-items-center d-flex flex-column justify-content-center mb-4 w-100"
>
<gf-logo size="medium"></gf-logo>
<gf-logo size="medium" />
</div>
<div *ngIf="!hasError" class="col d-flex justify-content-center">

2
apps/client/src/index.html

@ -48,7 +48,7 @@
<link href="../assets/site.webmanifest" rel="manifest" />
</head>
<body>
<gf-root></gf-root>
<gf-root />
<script src="../ionicons/ionicons.esm.js" type="module"></script>
<script nomodule="" src="ionicons.js"></script>

2
libs/ui/src/lib/account-balances/account-balances.component.html

@ -26,7 +26,7 @@
[locale]="locale"
[unit]="element?.Account?.currency"
[value]="element?.value"
></gf-value>
/>
</div>
</td>
</ng-container>

22
libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.html

@ -120,7 +120,7 @@
[dataSource]="element.SymbolProfile?.dataSource"
[symbol]="element.SymbolProfile?.symbol"
[tooltip]="element.SymbolProfile?.name"
></gf-symbol-icon>
/>
<div>{{ element.dataSource }}</div>
</td>
</ng-container>
@ -154,7 +154,7 @@
<ng-container i18n>Type</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
<gf-activity-type [activityType]="element.type"></gf-activity-type>
<gf-activity-type [activityType]="element.type" />
</td>
</ng-container>
@ -188,7 +188,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.quantity"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -212,7 +212,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.unitPrice"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -236,7 +236,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.fee"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -259,7 +259,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.value"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -291,7 +291,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.valueInBaseCurrency"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -307,7 +307,7 @@
class="mr-1"
[tooltip]="element.Account?.Platform?.name"
[url]="element.Account?.Platform?.url"
></gf-symbol-icon>
/>
<span class="d-none d-lg-block">{{ element.Account?.name }}</span>
</div>
</td>
@ -467,7 +467,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<mat-paginator
[length]="totalItems"
@ -486,7 +486,5 @@
"
class="p-3 text-center"
>
<gf-no-transactions-info-indicator
[hasBorder]="false"
></gf-no-transactions-info-indicator>
<gf-no-transactions-info-indicator [hasBorder]="false" />
</div>

28
libs/ui/src/lib/activities-table/activities-table.component.html

@ -4,7 +4,7 @@
[ngClass]="{ 'd-none': !hasPermissionToFilter }"
[placeholder]="placeholder"
(valueChanged)="filters$.next($event)"
></gf-activities-filter>
/>
<div *ngIf="hasPermissionToCreateActivity" class="d-flex justify-content-end">
<button
@ -164,7 +164,7 @@
<ng-container i18n>Type</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
<gf-activity-type [activityType]="element.type"></gf-activity-type>
<gf-activity-type [activityType]="element.type" />
</td>
<td *matFooterCellDef class="px-1" mat-footer-cell></td>
</ng-container>
@ -239,7 +239,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.quantity"
></gf-value>
/>
</div>
</td>
<td
@ -268,7 +268,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.unitPrice"
></gf-value>
/>
</div>
</td>
<td
@ -297,7 +297,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.fee"
></gf-value>
/>
</div>
</td>
<td *matFooterCellDef class="d-none d-lg-table-cell px-1" mat-footer-cell>
@ -306,7 +306,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : totalFees"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -330,7 +330,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.value"
></gf-value>
/>
</div>
</td>
<td *matFooterCellDef class="d-none d-lg-table-cell px-1" mat-footer-cell>
@ -341,7 +341,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : totalValue"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -361,7 +361,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.valueInBaseCurrency"
></gf-value>
/>
</div>
</td>
<td *matFooterCellDef class="d-lg-none d-xl-none px-1" mat-footer-cell>
@ -372,7 +372,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : totalValue"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -393,7 +393,7 @@
class="mr-1"
[tooltip]="element.Account?.Platform?.name"
[url]="element.Account?.Platform?.url"
></gf-symbol-icon>
/>
<span class="d-none d-lg-block">{{ element.Account?.name }}</span>
</div>
</td>
@ -579,7 +579,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<div
*ngIf="
@ -587,7 +587,5 @@
"
class="p-3 text-center"
>
<gf-no-transactions-info-indicator
[hasBorder]="false"
></gf-no-transactions-info-indicator>
<gf-no-transactions-info-indicator [hasBorder]="false" />
</div>

21
libs/ui/src/lib/assistant/assistant.component.ts

@ -216,6 +216,12 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit {
);
}
public hasFilter(aFormValue: { [key: string]: string }) {
return Object.values(aFormValue).some((value) => {
return !!value;
});
}
public async initialize() {
this.isLoading = true;
this.keyManager = new FocusKeyManager(this.assistantListItems).withWrap();
@ -249,6 +255,21 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit {
this.closed.emit();
}
public onResetFilters() {
this.filtersChanged.emit([
{
id: null,
type: 'ACCOUNT'
},
{
id: null,
type: 'TAG'
}
]);
this.onCloseAssistant();
}
public setIsOpen(aIsOpen: boolean) {
this.isOpen = aIsOpen;
}

50
libs/ui/src/lib/assistant/assistant.html

@ -59,7 +59,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<div *ngIf="!isLoading" class="px-2 py-1" i18n>No entries...</div>
</ng-container>
</div>
@ -80,7 +80,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<div *ngIf="!isLoading" class="px-2 py-1" i18n>No entries...</div>
</ng-container>
</div>
@ -91,33 +91,25 @@
*ngIf="!(isLoading || searchFormControl.value) && user?.settings?.isExperimentalFeatures"
class="filter-container"
>
<div class="p-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Date Range</mat-label>
<mat-select
[formControl]="dateRangeFormControl"
(selectionChange)="onChangeDateRange($event.value)"
>
@for (range of dateRangeOptions; track range) {
<mat-option [value]="range.value">{{ range.label }}</mat-option>
}
</mat-select>
</mat-form-field>
</div>
<mat-tab-group
animationDuration="0"
mat-align-tabs="start"
[mat-stretch-tabs]="false"
(click)="$event.stopPropagation();"
>
<mat-tab>
<ng-template mat-tab-label
><ion-icon name="calendar-clear-outline" /><span
class="d-none d-sm-block ml-2"
i18n
>Date Range</span
></ng-template
>
<div class="p-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-select
[formControl]="dateRangeFormControl"
(selectionChange)="onChangeDateRange($event.value)"
>
@for (range of dateRangeOptions; track range) {
<mat-option [value]="range.value">{{ range.label }}</mat-option>
}
</mat-select>
</mat-form-field>
</div>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label
><ion-icon name="albums-outline" /><span
@ -161,5 +153,17 @@
</div>
</mat-tab>
</mat-tab-group>
<div class="p-3">
<button
class="w-100"
color="primary"
i18n
mat-flat-button
[disabled]="!hasFilter(filterForm.value)"
(click)="onResetFilters()"
>
Reset Filters
</button>
</div>
</div>
</form>

2
libs/ui/src/lib/assistant/assistant.scss

@ -3,7 +3,7 @@
.filter-container {
.mat-mdc-tab-group {
max-height: 40vh;
max-height: 20vh;
}
::ng-deep {

2
libs/ui/src/lib/fire-calculator/fire-calculator.component.html

@ -77,7 +77,7 @@
height: '100%',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<canvas
#chartCanvas
class="h-100"

16
libs/ui/src/lib/holdings-table/holdings-table.component.html

@ -14,7 +14,7 @@
[dataSource]="element.dataSource"
[symbol]="element.symbol"
[tooltip]="element.name"
></gf-symbol-icon>
/>
</td>
</ng-container>
@ -59,7 +59,7 @@
[isDate]="element.dateOfFirstActivity ? true : false"
[locale]="locale"
[value]="element.dateOfFirstActivity ?? ''"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -83,7 +83,7 @@
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.valueInBaseCurrency"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -104,7 +104,7 @@
[isPercent]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.allocationInPercentage"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -126,7 +126,7 @@
[isPercent]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.netPerformancePercent"
></gf-value>
/>
</div>
</td>
</ng-container>
@ -162,7 +162,7 @@
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<div
*ngIf="dataSource.data.length > pageSize && !isLoading"
@ -179,7 +179,5 @@
"
class="p-3 text-center"
>
<gf-no-transactions-info-indicator
[hasBorder]="false"
></gf-no-transactions-info-indicator>
<gf-no-transactions-info-indicator [hasBorder]="false" />
</div>

8
libs/ui/src/lib/holdings-table/holdings-table.component.ts

@ -58,11 +58,11 @@ export class HoldingsTableComponent implements OnChanges, OnDestroy, OnInit {
this.isLoading = true;
if (this.holdings) {
this.dataSource = new MatTableDataSource(this.holdings);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.dataSource = new MatTableDataSource(this.holdings);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
if (this.holdings) {
this.isLoading = false;
}
}

2
libs/ui/src/lib/line-chart/line-chart.component.html

@ -5,7 +5,7 @@
height: '100%',
width: '100%'
}"
></ngx-skeleton-loader>
/>
<canvas
#chartCanvas
[ngStyle]="{ display: isLoading ? 'none' : 'block' }"

2
libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html

@ -1,6 +1,6 @@
<div class="p-3">
<div class="d-flex justify-content-center mb-1">
<gf-logo size="large" [showLabel]="false"></gf-logo>
<gf-logo size="large" [showLabel]="false" />
</div>
<a
class="align-items-center justify-content-center"

2
libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.html

@ -5,7 +5,7 @@
[theme]="{
height: '100%'
}"
></ngx-skeleton-loader>
/>
<canvas
#chartCanvas
[ngStyle]="{ display: isLoading ? 'none' : 'block' }"

2
libs/ui/src/lib/trend-indicator/trend-indicator.component.html

@ -6,7 +6,7 @@
height: '1.8rem',
width: '1.8rem'
}"
></ngx-skeleton-loader>
/>
<ng-template #other>
<ion-icon

2
libs/ui/src/lib/value/value.component.html

@ -67,7 +67,7 @@
size === 'large' ? '2rem' : size === 'medium' ? '1.8rem' : '1.5rem',
width: '5rem'
}"
></ngx-skeleton-loader>
/>
<ng-container>
<div *ngIf="size === 'large'">

2
package.json

@ -1,6 +1,6 @@
{
"name": "ghostfolio",
"version": "2.45.0",
"version": "2.46.0",
"homepage": "https://ghostfol.io",
"license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio",

Loading…
Cancel
Save