Browse Source

Feature/move accounts table component to @ghostfolio/ui (#5278)

* Move accounts table component to @ghostfolio/ui

* Add Storybook story

* Update changelog
pull/5304/head
David Requeno 1 week ago
committed by GitHub
parent
commit
38afc839eb
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 2
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
  3. 2
      apps/client/src/app/pages/accounts/accounts-page.component.ts
  4. 0
      libs/ui/src/lib/accounts-table/accounts-table.component.html
  5. 0
      libs/ui/src/lib/accounts-table/accounts-table.component.scss
  6. 146
      libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts
  7. 10
      libs/ui/src/lib/accounts-table/accounts-table.component.ts
  8. 1
      libs/ui/src/lib/accounts-table/index.ts
  9. 2
      libs/ui/src/lib/tags-selector/tags-selector.component.stories.ts

1
CHANGELOG.md

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Added support to exclude an activity from analysis based on tags - Added support to exclude an activity from analysis based on tags
- Added a _Storybook_ story for the accounts table component
- Added a _Storybook_ story for the membership card component - Added a _Storybook_ story for the membership card component
### Changed ### Changed

2
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts

@ -1,5 +1,4 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { GfAccountsTableComponent } from '@ghostfolio/client/components/accounts-table/accounts-table.component';
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
@ -15,6 +14,7 @@ import {
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { internalRoutes } from '@ghostfolio/common/routes/routes';
import { GfAccountsTableComponent } from '@ghostfolio/ui/accounts-table';
import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table';
import { GfDataProviderCreditsComponent } from '@ghostfolio/ui/data-provider-credits'; import { GfDataProviderCreditsComponent } from '@ghostfolio/ui/data-provider-credits';
import { GfHistoricalMarketDataEditorComponent } from '@ghostfolio/ui/historical-market-data-editor'; import { GfHistoricalMarketDataEditorComponent } from '@ghostfolio/ui/historical-market-data-editor';

2
apps/client/src/app/pages/accounts/accounts-page.component.ts

@ -4,13 +4,13 @@ import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto
import { AccountDetailDialog } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.component'; import { AccountDetailDialog } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.component';
import { GfAccountDetailDialogModule } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.module'; import { GfAccountDetailDialogModule } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.module';
import { AccountDetailDialogParams } from '@ghostfolio/client/components/account-detail-dialog/interfaces/interfaces'; import { AccountDetailDialogParams } from '@ghostfolio/client/components/account-detail-dialog/interfaces/interfaces';
import { GfAccountsTableComponent } from '@ghostfolio/client/components/accounts-table/accounts-table.component';
import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service';
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UserService } from '@ghostfolio/client/services/user/user.service';
import { User } from '@ghostfolio/common/interfaces'; import { User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { GfAccountsTableComponent } from '@ghostfolio/ui/accounts-table';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';

0
apps/client/src/app/components/accounts-table/accounts-table.component.html → libs/ui/src/lib/accounts-table/accounts-table.component.html

0
apps/client/src/app/components/accounts-table/accounts-table.component.scss → libs/ui/src/lib/accounts-table/accounts-table.component.scss

146
libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts

@ -0,0 +1,146 @@
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone';
import { moduleMetadata } from '@storybook/angular';
import type { Meta, StoryObj } from '@storybook/angular';
import { NotificationService } from 'apps/client/src/app/core/notification/notification.service';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GfEntityLogoComponent } from '../entity-logo';
import { GfValueComponent } from '../value';
import { GfAccountsTableComponent } from './accounts-table.component';
const accounts = [
{
allocationInPercentage: null,
balance: 278,
balanceInBaseCurrency: 278,
comment: null,
createdAt: new Date('2025-06-01T06:52:49.063Z'),
currency: 'USD',
id: '460d7401-ca43-4ed4-b08e-349f1822e9db',
isExcluded: false,
name: 'Coinbase Account',
platform: {
id: '8dc24b88-bb92-4152-af25-fe6a31643e26',
name: 'Coinbase',
url: 'https://www.coinbase.com'
},
platformId: '8dc24b88-bb92-4152-af25-fe6a31643e26',
transactionCount: 0,
updatedAt: new Date('2025-06-01T06:52:49.063Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
value: 278,
valueInBaseCurrency: 278
},
{
allocationInPercentage: null,
balance: 12000,
balanceInBaseCurrency: 12000,
comment: null,
createdAt: new Date('2025-06-01T06:48:53.055Z'),
currency: 'USD',
id: '6d773e31-0583-4c85-a247-e69870b4f1ee',
isExcluded: false,
name: 'Private Banking Account',
platform: {
id: '43e8fcd1-5b79-4100-b678-d2229bd1660d',
name: 'J.P. Morgan',
url: 'https://www.jpmorgan.com'
},
platformId: '43e8fcd1-5b79-4100-b678-d2229bd1660d',
transactionCount: 0,
updatedAt: new Date('2025-06-01T06:48:53.055Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
value: 12000,
valueInBaseCurrency: 12000
},
{
allocationInPercentage: null,
balance: 150.2,
balanceInBaseCurrency: 150.2,
comment: null,
createdAt: new Date('2025-05-31T13:00:13.940Z'),
currency: 'USD',
id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625',
isExcluded: false,
name: 'Trading Account',
platform: {
id: '9da3a8a7-4795-43e3-a6db-ccb914189737',
name: 'Interactive Brokers',
url: 'https://interactivebrokers.com'
},
platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737',
transactionCount: 12,
valueInBaseCurrency: 95693.70321466809,
updatedAt: new Date('2025-06-01T06:53:10.569Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
value: 95693.70321466809
}
];
export default {
title: 'Accounts Table',
component: GfAccountsTableComponent,
decorators: [
moduleMetadata({
imports: [
CommonModule,
GfEntityLogoComponent,
GfValueComponent,
IonIcon,
MatButtonModule,
MatMenuModule,
MatSortModule,
MatTableModule,
NgxSkeletonLoaderModule,
RouterModule.forChild([])
],
providers: [NotificationService]
})
]
} as Meta<GfAccountsTableComponent>;
type Story = StoryObj<GfAccountsTableComponent>;
export const Default: Story = {
args: {
accounts,
baseCurrency: 'USD',
deviceType: 'desktop',
locale: 'en-US',
showActions: false,
showAllocationInPercentage: false,
showBalance: true,
showFooter: true,
showTransactions: true,
showValue: true,
showValueInBaseCurrency: true,
totalBalanceInBaseCurrency: 12428.2,
totalValueInBaseCurrency: 107971.70321466809,
transactionCount: 12
}
};
export const WithoutFooter: Story = {
args: {
accounts,
baseCurrency: 'USD',
deviceType: 'desktop',
locale: 'en-US',
showActions: false,
showAllocationInPercentage: false,
showBalance: true,
showFooter: false,
showTransactions: true,
showValue: true,
showValueInBaseCurrency: true,
totalBalanceInBaseCurrency: 12428.2,
totalValueInBaseCurrency: 107971.70321466809,
transactionCount: 12
}
};

10
apps/client/src/app/components/accounts-table/accounts-table.component.ts → libs/ui/src/lib/accounts-table/accounts-table.component.ts

@ -21,7 +21,7 @@ import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { Router, RouterModule } from '@angular/router'; import { Router, RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone'; import { IonIcon } from '@ionic/angular/standalone';
import { Account as AccountModel } from '@prisma/client'; import { Account } from '@prisma/client';
import { addIcons } from 'ionicons'; import { addIcons } from 'ionicons';
import { import {
arrowRedoOutline, arrowRedoOutline,
@ -54,7 +54,7 @@ import { Subject, Subscription } from 'rxjs';
templateUrl: './accounts-table.component.html' templateUrl: './accounts-table.component.html'
}) })
export class GfAccountsTableComponent implements OnChanges, OnDestroy { export class GfAccountsTableComponent implements OnChanges, OnDestroy {
@Input() accounts: AccountModel[]; @Input() accounts: Account[];
@Input() baseCurrency: string; @Input() baseCurrency: string;
@Input() deviceType: string; @Input() deviceType: string;
@Input() hasPermissionToOpenDetails = true; @Input() hasPermissionToOpenDetails = true;
@ -71,12 +71,12 @@ export class GfAccountsTableComponent implements OnChanges, OnDestroy {
@Input() transactionCount: number; @Input() transactionCount: number;
@Output() accountDeleted = new EventEmitter<string>(); @Output() accountDeleted = new EventEmitter<string>();
@Output() accountToUpdate = new EventEmitter<AccountModel>(); @Output() accountToUpdate = new EventEmitter<Account>();
@Output() transferBalance = new EventEmitter<void>(); @Output() transferBalance = new EventEmitter<void>();
@ViewChild(MatSort) sort: MatSort; @ViewChild(MatSort) sort: MatSort;
public dataSource = new MatTableDataSource<AccountModel>(); public dataSource = new MatTableDataSource<Account>();
public displayedColumns = []; public displayedColumns = [];
public isLoading = true; public isLoading = true;
public routeQueryParams: Subscription; public routeQueryParams: Subscription;
@ -167,7 +167,7 @@ export class GfAccountsTableComponent implements OnChanges, OnDestroy {
this.transferBalance.emit(); this.transferBalance.emit();
} }
public onUpdateAccount(aAccount: AccountModel) { public onUpdateAccount(aAccount: Account) {
this.accountToUpdate.emit(aAccount); this.accountToUpdate.emit(aAccount);
} }

1
libs/ui/src/lib/accounts-table/index.ts

@ -0,0 +1 @@
export * from './accounts-table.component';

2
libs/ui/src/lib/tags-selector/tags-selector.component.stories.ts

@ -21,7 +21,7 @@ const OPTIONS = [
{ {
id: '3ef7e6d9-4598-4eb2-b0e8-00e61cfc0ea6', id: '3ef7e6d9-4598-4eb2-b0e8-00e61cfc0ea6',
name: 'Gambling', name: 'Gambling',
userId: 'c6a71541-d0e3-4e22-ae83-b5e5611b6695' userId: '081aa387-487d-4438-83a4-3060eb2a016e'
}, },
{ {
id: 'EMERGENCY_FUND', id: 'EMERGENCY_FUND',

Loading…
Cancel
Save