Browse Source

Merge remote-tracking branch 'origin/main' into feature/enable-strict-null-checks-in-ui

pull/6264/head
KenTandrian 23 hours ago
parent
commit
cae6dab390
  1. 5
      CHANGELOG.md
  2. 36
      libs/ui/src/lib/activities-table/activities-table.component.html
  3. 138
      libs/ui/src/lib/activities-table/activities-table.component.ts
  4. 581
      package-lock.json
  5. 24
      package.json

5
CHANGELOG.md

@ -5,12 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
## 2.237.0 - 2026-02-08
### Changed
- Removed the `transactionCount` in the portfolio calculator and service
- Removed the deprecated `transactionCount` in the portfolio calculator and service
- Refreshed the cryptocurrencies list
- Upgraded `Nx` from version `22.4.1` to `22.4.5`
### Fixed

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

@ -21,7 +21,7 @@
<mat-menu #activitiesMenu="matMenu" class="no-max-width" xPosition="before">
<button
mat-menu-item
[disabled]="dataSource?.data.length === 0"
[disabled]="dataSource()?.data.length === 0"
(click)="onImportDividends()"
>
<span class="align-items-center d-flex">
@ -33,7 +33,7 @@
<button
class="align-items-center d-flex"
mat-menu-item
[disabled]="dataSource?.data.length === 0"
[disabled]="dataSource()?.data.length === 0"
(click)="onExport()"
>
<span class="align-items-center d-flex">
@ -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"
/>
</div>
</td>
@ -201,7 +201,7 @@
<gf-value
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.quantity"
[value]="isLoading() ? undefined : element.quantity"
/>
</div>
</td>
@ -225,7 +225,7 @@
<gf-value
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.unitPrice"
[value]="isLoading() ? undefined : element.unitPrice"
/>
</div>
</td>
@ -249,7 +249,7 @@
<gf-value
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.fee"
[value]="isLoading() ? undefined : element.fee"
/>
</div>
</td>
@ -272,7 +272,7 @@
<gf-value
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.value"
[value]="isLoading() ? undefined : element.value"
/>
</div>
</td>
@ -304,7 +304,7 @@
<gf-value
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.valueInBaseCurrency"
[value]="isLoading() ? undefined : element.valueInBaseCurrency"
/>
</div>
</td>
@ -388,7 +388,7 @@
@if (hasPermissionToCreateActivity) {
<button
mat-menu-item
[disabled]="dataSource?.data.length === 0"
[disabled]="dataSource()?.data.length === 0"
(click)="onImportDividends()"
>
<span class="align-items-center d-flex">
@ -403,7 +403,7 @@
<button
class="align-items-center d-flex"
mat-menu-item
[disabled]="dataSource?.data.length === 0"
[disabled]="dataSource()?.data.length === 0"
(click)="onExport()"
>
<span class="align-items-center d-flex">
@ -488,9 +488,9 @@
</td>
</ng-container>
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
<tr *matHeaderRowDef="displayedColumns()" mat-header-row></tr>
<tr
*matRowDef="let row; columns: displayedColumns"
*matRowDef="let row; columns: displayedColumns()"
mat-row
[ngClass]="{
'cursor-pointer': canClickActivity(row)
@ -500,7 +500,7 @@
</table>
</div>
@if (isLoading) {
@if (isLoading()) {
<ngx-skeleton-loader
animation="pulse"
class="px-4 py-3"
@ -514,7 +514,7 @@
<mat-paginator
[length]="totalItems"
[ngClass]="{
'd-none': (isLoading && !totalItems) || totalItems <= pageSize
'd-none': (isLoading() && !totalItems) || totalItems <= pageSize
}"
[pageIndex]="pageIndex"
[pageSize]="pageSize"
@ -524,9 +524,9 @@
@if (
!hasActivities &&
dataSource?.data.length === 0 &&
dataSource()?.data.length === 0 &&
hasPermissionToCreateActivity &&
!isLoading
!isLoading()
) {
<div class="p-3 text-center">
<gf-no-transactions-info-indicator [hasBorder]="false" />

138
libs/ui/src/lib/activities-table/activities-table.component.ts

@ -21,11 +21,13 @@ import {
Component,
EventEmitter,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
ViewChild
ViewChild,
computed,
inject,
input
} from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
@ -45,7 +47,6 @@ import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatTooltipModule } from '@angular/material/tooltip';
import { IonIcon } from '@ionic/angular/standalone';
import { isUUID } from 'class-validator';
import { endOfToday, isAfter } from 'date-fns';
import { addIcons } from 'ionicons';
import {
alertCircleOutline,
@ -62,7 +63,7 @@ import {
trashOutline
} from 'ionicons/icons';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { Subject, Subscription, takeUntil } from 'rxjs';
import { Subject, takeUntil } from 'rxjs';
import { GfActivityTypeComponent } from '../activity-type/activity-type.component';
import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component';
@ -94,10 +95,9 @@ import { GfValueComponent } from '../value/value.component';
templateUrl: './activities-table.component.html'
})
export class GfActivitiesTableComponent
implements AfterViewInit, OnChanges, OnDestroy, OnInit
implements AfterViewInit, OnDestroy, OnInit
{
@Input() baseCurrency: string;
@Input() dataSource: MatTableDataSource<Activity>;
@Input() deviceType: string;
@Input() hasActivities: boolean;
@Input() hasPermissionToCreateActivity: boolean;
@ -107,10 +107,7 @@ export class GfActivitiesTableComponent
@Input() locale = getLocale();
@Input() pageIndex: number;
@Input() pageSize = DEFAULT_PAGE_SIZE;
@Input() showAccountColumn = true;
@Input() showActions = true;
@Input() showCheckbox = false;
@Input() showNameColumn = true;
@Input() sortColumn: string;
@Input() sortDirection: SortDirection;
@Input() sortDisabled = false;
@ -132,19 +129,66 @@ export class GfActivitiesTableComponent
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
public displayedColumns: string[] = [];
public endOfToday = endOfToday();
public hasDrafts = false;
public hasErrors = false;
public isAfter = isAfter;
public isLoading = true;
public isUUID = isUUID;
public routeQueryParams: Subscription;
public selectedRows = new SelectionModel<Activity>(true, []);
private unsubscribeSubject = new Subject<void>();
public readonly dataSource = input.required<
MatTableDataSource<Activity> | undefined
>();
public readonly showAccountColumn = input(true);
public readonly showCheckbox = input(false);
public readonly showNameColumn = input(true);
public constructor(private notificationService: NotificationService) {
protected readonly displayedColumns = computed(() => {
let columns = [
'select',
'importStatus',
'icon',
'nameWithSymbol',
'type',
'date',
'quantity',
'unitPrice',
'fee',
'value',
'currency',
'valueInBaseCurrency',
'account',
'comment',
'actions'
];
if (!this.showAccountColumn()) {
columns = columns.filter((column) => {
return column !== 'account';
});
}
if (!this.showCheckbox()) {
columns = columns.filter((column) => {
return column !== 'importStatus' && column !== 'select';
});
}
if (!this.showNameColumn()) {
columns = columns.filter((column) => {
return column !== 'nameWithSymbol';
});
}
return columns;
});
protected readonly isLoading = computed(() => {
return !this.dataSource();
});
private readonly notificationService = inject(NotificationService);
private readonly unsubscribeSubject = new Subject<void>();
public constructor() {
addIcons({
alertCircleOutline,
calendarClearOutline,
@ -162,7 +206,7 @@ export class GfActivitiesTableComponent
}
public ngOnInit() {
if (this.showCheckbox) {
if (this.showCheckbox()) {
this.toggleAllRows();
this.selectedRows.changed
.pipe(takeUntil(this.unsubscribeSubject))
@ -173,8 +217,10 @@ export class GfActivitiesTableComponent
}
public ngAfterViewInit() {
if (this.dataSource) {
this.dataSource.paginator = this.paginator;
const dataSource = this.dataSource();
if (dataSource) {
dataSource.paginator = this.paginator;
}
this.sort.sortChange.subscribe((value: Sort) => {
@ -182,51 +228,9 @@ export class GfActivitiesTableComponent
});
}
public ngOnChanges() {
this.displayedColumns = [
'select',
'importStatus',
'icon',
'nameWithSymbol',
'type',
'date',
'quantity',
'unitPrice',
'fee',
'value',
'currency',
'valueInBaseCurrency',
'account',
'comment',
'actions'
];
if (!this.showAccountColumn) {
this.displayedColumns = this.displayedColumns.filter((column) => {
return column !== 'account';
});
}
if (!this.showCheckbox) {
this.displayedColumns = this.displayedColumns.filter((column) => {
return column !== 'importStatus' && column !== 'select';
});
}
if (!this.showNameColumn) {
this.displayedColumns = this.displayedColumns.filter((column) => {
return column !== 'nameWithSymbol';
});
}
if (this.dataSource) {
this.isLoading = false;
}
}
public areAllRowsSelected() {
const numSelectedRows = this.selectedRows.selected.length;
const numTotalRows = this.dataSource.data.length;
const numTotalRows = this.dataSource()?.data.length;
return numSelectedRows === numTotalRows;
}
@ -241,7 +245,7 @@ export class GfActivitiesTableComponent
public isExcludedFromAnalysis(activity: Activity) {
return (
activity.account?.isExcluded ||
activity.account?.isExcluded ??
activity.tags?.some(({ id }) => {
return id === TAG_ID_EXCLUDE_FROM_ANALYSIS;
})
@ -253,7 +257,7 @@ export class GfActivitiesTableComponent
}
public onClickActivity(activity: Activity) {
if (this.showCheckbox) {
if (this.showCheckbox()) {
if (!activity.error) {
this.selectedRows.toggle(activity);
}
@ -299,8 +303,8 @@ export class GfActivitiesTableComponent
public onExportDrafts() {
this.exportDrafts.emit(
this.dataSource.filteredData
.filter((activity) => {
this.dataSource()
?.filteredData.filter((activity) => {
return activity.isDraft;
})
.map((activity) => {
@ -331,7 +335,7 @@ export class GfActivitiesTableComponent
if (this.areAllRowsSelected()) {
this.selectedRows.clear();
} else {
this.dataSource.data.forEach((row) => {
this.dataSource()?.data.forEach((row) => {
this.selectedRows.select(row);
});
}

581
package-lock.json

File diff suppressed because it is too large

24
package.json

@ -1,6 +1,6 @@
{
"name": "ghostfolio",
"version": "2.236.0",
"version": "2.237.0",
"homepage": "https://ghostfol.io",
"license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio",
@ -152,16 +152,16 @@
"@eslint/js": "9.35.0",
"@nestjs/schematics": "11.0.9",
"@nestjs/testing": "11.1.8",
"@nx/angular": "22.4.1",
"@nx/eslint-plugin": "22.4.1",
"@nx/jest": "22.4.1",
"@nx/js": "22.4.1",
"@nx/module-federation": "22.4.1",
"@nx/nest": "22.4.1",
"@nx/node": "22.4.1",
"@nx/storybook": "22.4.1",
"@nx/web": "22.4.1",
"@nx/workspace": "22.4.1",
"@nx/angular": "22.4.5",
"@nx/eslint-plugin": "22.4.5",
"@nx/jest": "22.4.5",
"@nx/js": "22.4.5",
"@nx/module-federation": "22.4.5",
"@nx/nest": "22.4.5",
"@nx/node": "22.4.5",
"@nx/storybook": "22.4.5",
"@nx/web": "22.4.5",
"@nx/workspace": "22.4.5",
"@schematics/angular": "21.1.1",
"@storybook/addon-docs": "10.1.10",
"@storybook/angular": "10.1.10",
@ -186,7 +186,7 @@
"jest": "30.2.0",
"jest-environment-jsdom": "30.2.0",
"jest-preset-angular": "16.0.0",
"nx": "22.4.1",
"nx": "22.4.5",
"prettier": "3.8.1",
"prettier-plugin-organize-attributes": "1.0.0",
"prisma": "6.19.0",

Loading…
Cancel
Save