diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.html b/apps/client/src/app/pages/about/overview/about-overview-page.html
index 2fb3ef812..cab1caa23 100644
--- a/apps/client/src/app/pages/about/overview/about-overview-page.html
+++ b/apps/client/src/app/pages/about/overview/about-overview-page.html
@@ -209,7 +209,7 @@
Browser testing via
@@ -217,9 +217,9 @@
alt="TestMu AI Logo"
height="32"
[src]="
- user?.settings?.colorScheme === 'LIGHT'
- ? '../assets/images/sponsors/logo-testmu-dark.svg'
- : '../assets/images/sponsors/logo-testmu-light.svg'
+ user?.settings?.colorScheme === 'DARK'
+ ? '../assets/images/sponsors/logo-testmu-light.svg'
+ : '../assets/images/sponsors/logo-testmu-dark.svg'
"
/>
diff --git a/apps/client/src/app/pages/accounts/accounts-page.component.ts b/apps/client/src/app/pages/accounts/accounts-page.component.ts
index 6c8146f77..f7e6541b5 100644
--- a/apps/client/src/app/pages/accounts/accounts-page.component.ts
+++ b/apps/client/src/app/pages/accounts/accounts-page.component.ts
@@ -38,6 +38,7 @@ import { GfTransferBalanceDialogComponent } from './transfer-balance/transfer-ba
})
export class GfAccountsPageComponent implements OnDestroy, OnInit {
public accounts: AccountModel[];
+ public activitiesCount = 0;
public deviceType: string;
public hasImpersonationId: boolean;
public hasPermissionToCreateAccount: boolean;
@@ -45,7 +46,6 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit {
public routeQueryParams: Subscription;
public totalBalanceInBaseCurrency = 0;
public totalValueInBaseCurrency = 0;
- public transactionCount = 0;
public user: User;
private unsubscribeSubject = new Subject
();
@@ -128,14 +128,14 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit {
.subscribe(
({
accounts,
+ activitiesCount,
totalBalanceInBaseCurrency,
- totalValueInBaseCurrency,
- transactionCount
+ totalValueInBaseCurrency
}) => {
this.accounts = accounts;
+ this.activitiesCount = activitiesCount;
this.totalBalanceInBaseCurrency = totalBalanceInBaseCurrency;
this.totalValueInBaseCurrency = totalValueInBaseCurrency;
- this.transactionCount = transactionCount;
if (this.accounts?.length <= 0) {
this.router.navigate([], { queryParams: { createDialog: true } });
@@ -358,8 +358,8 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit {
private reset() {
this.accounts = undefined;
+ this.activitiesCount = 0;
this.totalBalanceInBaseCurrency = 0;
this.totalValueInBaseCurrency = 0;
- this.transactionCount = 0;
}
}
diff --git a/apps/client/src/app/pages/accounts/accounts-page.html b/apps/client/src/app/pages/accounts/accounts-page.html
index 6f29a4f7c..3d9d7ee5c 100644
--- a/apps/client/src/app/pages/accounts/accounts-page.html
+++ b/apps/client/src/app/pages/accounts/accounts-page.html
@@ -4,8 +4,8 @@
Accounts
({
colorScheme,
currency = '',
groupBy,
@@ -45,35 +48,43 @@ export function getTooltipOptions({
groupBy?: GroupBy;
locale?: string;
unit?: string;
-}) {
+}): Partial> {
return {
backgroundColor: getBackgroundColor(colorScheme),
bodyColor: `rgb(${getTextColor(colorScheme)})`,
borderWidth: 1,
borderColor: `rgba(${getTextColor(colorScheme)}, 0.1)`,
+ // @ts-expect-error: no need to set all attributes in callbacks
callbacks: {
label: (context) => {
- let label = context.dataset.label ?? '';
+ let label = (context.dataset as ControllerDatasetOptions).label ?? '';
+
if (label) {
label += ': ';
}
- if (context.parsed.y !== null) {
+
+ const yPoint = (context.parsed as Point).y;
+
+ if (yPoint !== null) {
if (currency) {
- label += `${context.parsed.y.toLocaleString(locale, {
+ label += `${yPoint.toLocaleString(locale, {
maximumFractionDigits: 2,
minimumFractionDigits: 2
})} ${currency}`;
} else if (unit) {
- label += `${context.parsed.y.toFixed(2)} ${unit}`;
+ label += `${yPoint.toFixed(2)} ${unit}`;
} else {
- label += context.parsed.y.toFixed(2);
+ label += yPoint.toFixed(2);
}
}
+
return label;
},
title: (contexts) => {
- if (groupBy) {
- return formatGroupedDate({ groupBy, date: contexts[0].parsed.x });
+ const xPoint = (contexts[0].parsed as Point).x;
+
+ if (groupBy && xPoint !== null) {
+ return formatGroupedDate({ groupBy, date: xPoint });
}
return contexts[0].label;
@@ -98,16 +109,17 @@ export function getTooltipPositionerMapTop(
if (!position || !chart?.chartArea) {
return false;
}
+
return {
x: position.x,
y: chart.chartArea.top
};
}
-export function getVerticalHoverLinePlugin(
- chartCanvas: ElementRef,
+export function getVerticalHoverLinePlugin(
+ chartCanvas: ElementRef,
colorScheme: ColorScheme
-): Plugin {
+): Plugin {
return {
afterDatasetsDraw: (chart, _, options) => {
const active = chart.getActiveElements();
@@ -125,13 +137,16 @@ export function getVerticalHoverLinePlugin(
const xValue = active[0].element.x;
const context = chartCanvas.nativeElement.getContext('2d');
- context.lineWidth = width;
- context.strokeStyle = color;
- context.beginPath();
- context.moveTo(xValue, top);
- context.lineTo(xValue, bottom);
- context.stroke();
+ if (context) {
+ context.lineWidth = width;
+ context.strokeStyle = color;
+
+ context.beginPath();
+ context.moveTo(xValue, top);
+ context.lineTo(xValue, bottom);
+ context.stroke();
+ }
},
id: 'verticalHoverLine'
};
diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts
index a10a828e1..b558ccc42 100644
--- a/libs/common/src/lib/config.ts
+++ b/libs/common/src/lib/config.ts
@@ -78,6 +78,58 @@ export const DEFAULT_PROCESSOR_GATHER_HISTORICAL_MARKET_DATA_CONCURRENCY = 1;
export const DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_CONCURRENCY = 1;
export const DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_TIMEOUT = 30000;
+export const DEFAULT_REDACTED_PATHS = [
+ 'accounts[*].balance',
+ 'accounts[*].valueInBaseCurrency',
+ 'activities[*].account.balance',
+ 'activities[*].account.comment',
+ 'activities[*].comment',
+ 'activities[*].fee',
+ 'activities[*].feeInAssetProfileCurrency',
+ 'activities[*].feeInBaseCurrency',
+ 'activities[*].quantity',
+ 'activities[*].SymbolProfile.symbolMapping',
+ 'activities[*].SymbolProfile.watchedByCount',
+ 'activities[*].value',
+ 'activities[*].valueInBaseCurrency',
+ 'balance',
+ 'balanceInBaseCurrency',
+ 'balances[*].account.balance',
+ 'balances[*].account.comment',
+ 'balances[*].value',
+ 'balances[*].valueInBaseCurrency',
+ 'comment',
+ 'dividendInBaseCurrency',
+ 'feeInBaseCurrency',
+ 'grossPerformance',
+ 'grossPerformanceWithCurrencyEffect',
+ 'historicalData[*].quantity',
+ 'holdings[*].dividend',
+ 'holdings[*].grossPerformance',
+ 'holdings[*].grossPerformanceWithCurrencyEffect',
+ 'holdings[*].holdings[*].valueInBaseCurrency',
+ 'holdings[*].investment',
+ 'holdings[*].netPerformance',
+ 'holdings[*].netPerformanceWithCurrencyEffect',
+ 'holdings[*].quantity',
+ 'holdings[*].valueInBaseCurrency',
+ 'interestInBaseCurrency',
+ 'investmentInBaseCurrencyWithCurrencyEffect',
+ 'netPerformance',
+ 'netPerformanceWithCurrencyEffect',
+ 'platforms[*].balance',
+ 'platforms[*].valueInBaseCurrency',
+ 'quantity',
+ 'SymbolProfile.symbolMapping',
+ 'SymbolProfile.watchedByCount',
+ 'totalBalanceInBaseCurrency',
+ 'totalDividendInBaseCurrency',
+ 'totalInterestInBaseCurrency',
+ 'totalValueInBaseCurrency',
+ 'value',
+ 'valueInBaseCurrency'
+];
+
// USX is handled separately
export const DERIVED_CURRENCIES = [
{
diff --git a/libs/common/src/lib/interfaces/activities.interface.ts b/libs/common/src/lib/interfaces/activities.interface.ts
index 8c88cc2cf..b9e64984b 100644
--- a/libs/common/src/lib/interfaces/activities.interface.ts
+++ b/libs/common/src/lib/interfaces/activities.interface.ts
@@ -8,7 +8,7 @@ export interface Activity extends Order {
error?: ActivityError;
feeInAssetProfileCurrency: number;
feeInBaseCurrency: number;
- SymbolProfile?: EnhancedSymbolProfile;
+ SymbolProfile: EnhancedSymbolProfile;
tagIds?: string[];
tags?: Tag[];
unitPriceInAssetProfileCurrency: number;
diff --git a/libs/common/src/lib/interfaces/admin-data.interface.ts b/libs/common/src/lib/interfaces/admin-data.interface.ts
index 63588300c..dd25b516d 100644
--- a/libs/common/src/lib/interfaces/admin-data.interface.ts
+++ b/libs/common/src/lib/interfaces/admin-data.interface.ts
@@ -7,10 +7,6 @@ export interface AdminData {
useForExchangeRates: boolean;
})[];
settings: { [key: string]: boolean | object | string | string[] };
-
- /** @deprecated use activitiesCount instead */
- transactionCount: number;
-
userCount: number;
version: string;
}
diff --git a/libs/common/src/lib/interfaces/portfolio-position.interface.ts b/libs/common/src/lib/interfaces/portfolio-position.interface.ts
index 67a2f3e77..620cc00e9 100644
--- a/libs/common/src/lib/interfaces/portfolio-position.interface.ts
+++ b/libs/common/src/lib/interfaces/portfolio-position.interface.ts
@@ -39,10 +39,6 @@ export interface PortfolioPosition {
sectors: Sector[];
symbol: string;
tags?: Tag[];
-
- /** @deprecated use activitiesCount instead */
- transactionCount: number;
-
type?: string;
url?: string;
valueInBaseCurrency?: number;
diff --git a/libs/common/src/lib/interfaces/responses/accounts-response.interface.ts b/libs/common/src/lib/interfaces/responses/accounts-response.interface.ts
index 1891b9cbb..90f1303e0 100644
--- a/libs/common/src/lib/interfaces/responses/accounts-response.interface.ts
+++ b/libs/common/src/lib/interfaces/responses/accounts-response.interface.ts
@@ -7,7 +7,4 @@ export interface AccountsResponse {
totalDividendInBaseCurrency: number;
totalInterestInBaseCurrency: number;
totalValueInBaseCurrency: number;
-
- /** @deprecated use activitiesCount instead */
- transactionCount: number;
}
diff --git a/libs/common/src/lib/interfaces/responses/create-stripe-checkout-session-response.interface.ts b/libs/common/src/lib/interfaces/responses/create-stripe-checkout-session-response.interface.ts
index 1222ac6e9..8ac1a8279 100644
--- a/libs/common/src/lib/interfaces/responses/create-stripe-checkout-session-response.interface.ts
+++ b/libs/common/src/lib/interfaces/responses/create-stripe-checkout-session-response.interface.ts
@@ -1,6 +1,3 @@
export interface CreateStripeCheckoutSessionResponse {
- /** @deprecated */
- sessionId: string;
-
sessionUrl: string;
}
diff --git a/libs/common/src/lib/models/timeline-position.ts b/libs/common/src/lib/models/timeline-position.ts
index 9cfb2df04..13f9001d5 100644
--- a/libs/common/src/lib/models/timeline-position.ts
+++ b/libs/common/src/lib/models/timeline-position.ts
@@ -93,9 +93,6 @@ export class TimelinePosition {
@Type(() => Big)
timeWeightedInvestmentWithCurrencyEffect: Big;
- /** @deprecated use activitiesCount instead */
- transactionCount: number;
-
@Transform(transformToBig, { toClassOnly: true })
@Type(() => Big)
valueInBaseCurrency: Big;
diff --git a/libs/common/src/lib/types/account-with-value.type.ts b/libs/common/src/lib/types/account-with-value.type.ts
index 7f5fe79ba..23cb14749 100644
--- a/libs/common/src/lib/types/account-with-value.type.ts
+++ b/libs/common/src/lib/types/account-with-value.type.ts
@@ -7,10 +7,6 @@ export type AccountWithValue = AccountModel & {
dividendInBaseCurrency: number;
interestInBaseCurrency: number;
platform?: Platform;
-
- /** @deprecated use activitiesCount instead */
- transactionCount: number;
-
value: number;
valueInBaseCurrency: number;
};
diff --git a/libs/ui/src/lib/accounts-table/accounts-table.component.html b/libs/ui/src/lib/accounts-table/accounts-table.component.html
index f76a5d676..15f5bb21f 100644
--- a/libs/ui/src/lib/accounts-table/accounts-table.component.html
+++ b/libs/ui/src/lib/accounts-table/accounts-table.component.html
@@ -1,4 +1,4 @@
-@if (showActions) {
+@if (showActions()) {
- {{ baseCurrency }}
+ {{ baseCurrency() }}
@@ -115,21 +115,21 @@
>
-
+
#
Activities
- {{ element.transactionCount }}
+ {{ element.activitiesCount }}
- {{ transactionCount }}
+ {{ activitiesCount() }}
@@ -150,7 +150,7 @@
@@ -162,8 +162,8 @@
@@ -185,7 +185,7 @@
@@ -197,8 +197,8 @@
@@ -220,7 +220,7 @@
@@ -232,8 +232,8 @@
@@ -255,7 +255,7 @@
@@ -323,7 +323,7 @@
0"
+ [disabled]="element.activitiesCount > 0"
(click)="onDeleteAccount(element.id)"
>
@@ -336,24 +336,24 @@
-
+
-@if (isLoading) {
+@if (isLoading()) {
();
- @Output() accountToUpdate = new EventEmitter();
- @Output() transferBalance = new EventEmitter();
-
- @ViewChild(MatSort) sort: MatSort;
-
- public dataSource = new MatTableDataSource();
- public displayedColumns = [];
- public isLoading = true;
- public routeQueryParams: Subscription;
-
- private unsubscribeSubject = new Subject();
-
- public constructor(
- private notificationService: NotificationService,
- private router: Router
- ) {
- addIcons({
- arrowRedoOutline,
- createOutline,
- documentTextOutline,
- ellipsisHorizontal,
- eyeOffOutline,
- trashOutline,
- walletOutline
- });
- }
-
- public ngOnChanges() {
- this.displayedColumns = ['status', 'account', 'platform'];
-
- if (this.showTransactions) {
- this.displayedColumns.push('transactions');
+export class GfAccountsTableComponent {
+ public readonly accounts = input.required();
+ public readonly activitiesCount = input();
+ public readonly baseCurrency = input();
+ public readonly hasPermissionToOpenDetails = input(true);
+ public readonly locale = input(getLocale());
+ public readonly showActions = input();
+ public readonly showActivitiesCount = input(true);
+ public readonly showAllocationInPercentage = input();
+ public readonly showBalance = input(true);
+ public readonly showFooter = input(true);
+ public readonly showValue = input(true);
+ public readonly showValueInBaseCurrency = input(false);
+ public readonly totalBalanceInBaseCurrency = input();
+ public readonly totalValueInBaseCurrency = input();
+
+ public readonly accountDeleted = output();
+ public readonly accountToUpdate = output();
+ public readonly transferBalance = output();
+
+ public readonly sort = viewChild.required(MatSort);
+
+ protected readonly dataSource = new MatTableDataSource([]);
+
+ protected readonly displayedColumns = computed(() => {
+ const columns = ['status', 'account', 'platform'];
+
+ if (this.showActivitiesCount()) {
+ columns.push('activitiesCount');
}
- if (this.showBalance) {
- this.displayedColumns.push('balance');
+ if (this.showBalance()) {
+ columns.push('balance');
}
- if (this.showValue) {
- this.displayedColumns.push('value');
+ if (this.showValue()) {
+ columns.push('value');
}
- this.displayedColumns.push('currency');
+ columns.push('currency');
- if (this.showValueInBaseCurrency) {
- this.displayedColumns.push('valueInBaseCurrency');
+ if (this.showValueInBaseCurrency()) {
+ columns.push('valueInBaseCurrency');
}
- if (this.showAllocationInPercentage) {
- this.displayedColumns.push('allocation');
+ if (this.showAllocationInPercentage()) {
+ columns.push('allocation');
}
- this.displayedColumns.push('comment');
+ columns.push('comment');
- if (this.showActions) {
- this.displayedColumns.push('actions');
+ if (this.showActions()) {
+ columns.push('actions');
}
- this.isLoading = true;
+ return columns;
+ });
+
+ protected readonly isLoading = computed(() => !this.accounts());
+
+ private readonly notificationService = inject(NotificationService);
+ private readonly router = inject(Router);
+
+ public constructor() {
+ addIcons({
+ arrowRedoOutline,
+ createOutline,
+ documentTextOutline,
+ ellipsisHorizontal,
+ eyeOffOutline,
+ trashOutline,
+ walletOutline
+ });
- this.dataSource = new MatTableDataSource(this.accounts);
this.dataSource.sortingDataAccessor = getLowercase;
- this.dataSource.sort = this.sort;
+ // Reactive data update
+ effect(() => {
+ this.dataSource.data = this.accounts();
+ });
- if (this.accounts) {
- this.isLoading = false;
- }
+ // Reactive view connection
+ effect(() => {
+ this.dataSource.sort = this.sort();
+ });
}
- public onDeleteAccount(aId: string) {
+ protected onDeleteAccount(aId: string) {
this.notificationService.confirm({
confirmFn: () => {
this.accountDeleted.emit(aId);
@@ -151,30 +149,25 @@ export class GfAccountsTableComponent implements OnChanges, OnDestroy {
});
}
- public onOpenAccountDetailDialog(accountId: string) {
- if (this.hasPermissionToOpenDetails) {
+ protected onOpenAccountDetailDialog(accountId: string) {
+ if (this.hasPermissionToOpenDetails()) {
this.router.navigate([], {
queryParams: { accountId, accountDetailDialog: true }
});
}
}
- public onOpenComment(aComment: string) {
+ protected onOpenComment(aComment: string) {
this.notificationService.alert({
title: aComment
});
}
- public onTransferBalance() {
+ protected onTransferBalance() {
this.transferBalance.emit();
}
- public onUpdateAccount(aAccount: Account) {
+ protected onUpdateAccount(aAccount: Account) {
this.accountToUpdate.emit(aAccount);
}
-
- public ngOnDestroy() {
- this.unsubscribeSubject.next();
- this.unsubscribeSubject.complete();
- }
}
diff --git a/libs/ui/src/lib/activities-table/activities-table.component.html b/libs/ui/src/lib/activities-table/activities-table.component.html
index b8e1882d4..bdb1e6373 100644
--- a/libs/ui/src/lib/activities-table/activities-table.component.html
+++ b/libs/ui/src/lib/activities-table/activities-table.component.html
@@ -21,7 +21,7 @@
@@ -33,7 +33,7 @@
@@ -60,7 +60,7 @@
class="align-items-center d-flex"
mat-menu-item
[disabled]="
- dataSource?.data.length === 0 || !hasPermissionToDeleteActivity
+ dataSource()?.data.length === 0 || !hasPermissionToDeleteActivity
"
(click)="onDeleteActivities()"
>
@@ -78,7 +78,7 @@
class="gf-table w-100"
mat-table
matSort
- [dataSource]="dataSource"
+ [dataSource]="dataSource()"
[matSortActive]="sortColumn"
[matSortDirection]="sortDirection"
[matSortDisabled]="sortDisabled"
@@ -177,7 +177,7 @@
[deviceType]="deviceType"
[isDate]="true"
[locale]="locale"
- [value]="isLoading ? undefined : element.date"
+ [value]="isLoading() ? undefined : element.date"
/>