From 45ef139cf8493d45c2dac094b3b53342f5db5866 Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Tue, 14 Jul 2026 23:19:01 +0700 Subject: [PATCH 1/3] Task/enable @typescript-eslint/prefer-nullish-coalescing rule in libs/ui and apps/client (#7317) * feat(ui): implement prefer-nullish-coalescing eslint check * feat(client): implement prefer-nullish-coalescing eslint check * fix(client): remove whitespace --- apps/client/eslint.config.cjs | 4 +++- apps/client/jest.config.ts | 1 - .../asset-profile-dialog.component.ts | 10 +++++----- .../create-or-update-account-dialog.component.ts | 4 ++-- .../create-or-update-activity-dialog.component.ts | 2 +- apps/client/src/app/services/user/user.service.ts | 2 +- libs/ui/eslint.config.cjs | 3 ++- .../lib/activities-table/activities-table.component.ts | 2 +- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/client/eslint.config.cjs b/apps/client/eslint.config.cjs index 96ecefd50..bcbe2c1c1 100644 --- a/apps/client/eslint.config.cjs +++ b/apps/client/eslint.config.cjs @@ -47,7 +47,9 @@ module.exports = [ { files: ['**/*.ts', '**/*.tsx'], // Override or add rules here - rules: {} + rules: { + '@typescript-eslint/prefer-nullish-coalescing': 'error' + } }, { files: ['**/*.js', '**/*.jsx'], diff --git a/apps/client/jest.config.ts b/apps/client/jest.config.ts index 04378bdbd..26d772e11 100644 --- a/apps/client/jest.config.ts +++ b/apps/client/jest.config.ts @@ -1,4 +1,3 @@ -/* eslint-disable */ export default { displayName: 'client', diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts index 967a289ef..c34e8eb78 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts @@ -550,7 +550,7 @@ export class GfAssetProfileDialogComponent implements OnInit { ) as Record, locale: this.assetProfileForm.controls.scraperConfiguration.controls.locale - ?.value || undefined, + ?.value ?? undefined, mode: this.assetProfileForm.controls.scraperConfiguration.controls.mode ?.value ?? undefined, @@ -599,7 +599,7 @@ export class GfAssetProfileDialogComponent implements OnInit { assetClass: this.assetProfileForm.controls.assetClass.value ?? undefined, assetSubClass: this.assetProfileForm.controls.assetSubClass.value ?? undefined, - comment: this.assetProfileForm.controls.comment.value || undefined, + comment: this.assetProfileForm.controls.comment.value ?? undefined, currency: this.assetProfileForm.controls.currency.value ?? undefined, dataGatheringFrequency: this.assetProfileForm.controls.dataGatheringFrequency.value ?? @@ -607,8 +607,8 @@ export class GfAssetProfileDialogComponent implements OnInit { isActive: isBoolean(this.assetProfileForm.controls.isActive.value) ? this.assetProfileForm.controls.isActive.value : undefined, - name: this.assetProfileForm.controls.name.value || undefined, - url: this.assetProfileForm.controls.url.value || undefined + name: this.assetProfileForm.controls.name.value ?? undefined, + url: this.assetProfileForm.controls.url.value ?? undefined }; try { @@ -743,7 +743,7 @@ export class GfAssetProfileDialogComponent implements OnInit { ) as Record, locale: this.assetProfileForm.controls.scraperConfiguration.controls.locale - ?.value || undefined, + ?.value ?? undefined, mode: this.assetProfileForm.controls.scraperConfiguration.controls .mode?.value, selector: diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts index ca88120ca..d27b5ceae 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts @@ -200,12 +200,12 @@ export class GfCreateOrUpdateAccountDialogComponent { protected async onSubmit() { const account: CreateAccountDto | UpdateAccountDto = { balance: this.accountForm.get('balance')?.value, - comment: this.accountForm.get('comment')?.value || null, + comment: this.accountForm.get('comment')?.value ?? null, currency: this.accountForm.get('currency')?.value, id: this.accountForm.get('accountId')?.value, isExcluded: this.accountForm.get('isExcluded')?.value, name: this.accountForm.get('name')?.value, - platformId: this.accountForm.get('platformId')?.value?.id || null, + platformId: this.accountForm.get('platformId')?.value?.id ?? null, tags: this.accountForm .get('tags') ?.value?.filter(({ id }: Tag) => { diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts index be9ac7b04..10bc7ccc8 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts @@ -493,7 +493,7 @@ export class GfCreateOrUpdateActivityDialogComponent { accountId: this.activityForm.get('accountId')?.value, assetClass: this.activityForm.get('assetClass')?.value, assetSubClass: this.activityForm.get('assetSubClass')?.value, - comment: this.activityForm.get('comment')?.value || null, + comment: this.activityForm.get('comment')?.value ?? null, currency: this.activityForm.get('currency')?.value, customCurrency: this.activityForm.get('currencyOfUnitPrice')?.value, dataSource: ['FEE', 'INTEREST', 'LIABILITY', 'VALUABLE'].includes( diff --git a/apps/client/src/app/services/user/user.service.ts b/apps/client/src/app/services/user/user.service.ts index 52f33dc5a..d58f77c3e 100644 --- a/apps/client/src/app/services/user/user.service.ts +++ b/apps/client/src/app/services/user/user.service.ts @@ -192,6 +192,6 @@ export class UserService extends ObservableStore { return throwError(errMessage); } - return throwError(error || 'Server error'); + return throwError(error ?? 'Server error'); } } diff --git a/libs/ui/eslint.config.cjs b/libs/ui/eslint.config.cjs index e21452b5f..65d17debd 100644 --- a/libs/ui/eslint.config.cjs +++ b/libs/ui/eslint.config.cjs @@ -41,7 +41,8 @@ module.exports = [ } ], '@angular-eslint/prefer-inject': 'off', - '@angular-eslint/prefer-standalone': 'off' + '@angular-eslint/prefer-standalone': 'off', + '@typescript-eslint/prefer-nullish-coalescing': 'error' }, languageOptions: { parserOptions: { diff --git a/libs/ui/src/lib/activities-table/activities-table.component.ts b/libs/ui/src/lib/activities-table/activities-table.component.ts index b1bfcf686..fba02ad30 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.ts +++ b/libs/ui/src/lib/activities-table/activities-table.component.ts @@ -267,7 +267,7 @@ export class GfActivitiesTableComponent implements AfterViewInit, OnInit { public isExcludedFromAnalysis(activity: Activity) { return ( - (activity.account && isAccountExcluded(activity.account)) || + (activity.account && isAccountExcluded(activity.account)) ?? activity.tags?.some(({ id }) => { return id === TAG_ID_EXCLUDE_FROM_ANALYSIS; }) === true From d857bc882ca84e857f2c48c4fe14c8ce7cd97536 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:22:48 +0200 Subject: [PATCH 2/3] Task/add skeleton loader to coupons table of admin control panel (#7327) Add skeleton loader --- .../admin-overview/admin-overview.component.ts | 7 +++++++ .../app/components/admin-overview/admin-overview.html | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/apps/client/src/app/components/admin-overview/admin-overview.component.ts b/apps/client/src/app/components/admin-overview/admin-overview.component.ts index 7374fb05c..62bc78df1 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.component.ts +++ b/apps/client/src/app/components/admin-overview/admin-overview.component.ts @@ -63,6 +63,7 @@ import { trashOutline } from 'ionicons/icons'; import ms, { StringValue } from 'ms'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -79,6 +80,7 @@ import ms, { StringValue } from 'ms'; MatSnackBarModule, MatSlideToggleModule, MatTableModule, + NgxSkeletonLoaderModule, ReactiveFormsModule, RouterModule ], @@ -102,6 +104,7 @@ export class GfAdminOverviewComponent implements OnInit { protected hasPermissionToToggleReadOnlyMode: boolean; protected readonly info: InfoItem; protected isDataGatheringEnabled: boolean; + protected isLoading = false; protected readonly permissions = permissions; protected systemMessage: SystemMessage; protected userCount: number; @@ -320,6 +323,8 @@ export class GfAdminOverviewComponent implements OnInit { } private fetchAdminData() { + this.isLoading = true; + this.adminService .fetchAdminData() .pipe(takeUntilDestroyed(this.destroyRef)) @@ -336,6 +341,8 @@ export class GfAdminOverviewComponent implements OnInit { this.userCount = userCount; this.version = version; + this.isLoading = false; + this.changeDetectorRef.markForCheck(); }); } diff --git a/apps/client/src/app/components/admin-overview/admin-overview.html b/apps/client/src/app/components/admin-overview/admin-overview.html index 2fde94083..7e05600a6 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.html +++ b/apps/client/src/app/components/admin-overview/admin-overview.html @@ -248,6 +248,17 @@ mat-row > + + @if (isLoading) { + + } From df5fa6a4b9ea50e81066f70d27f6130eb7d83535 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:23:47 +0200 Subject: [PATCH 3/3] Task/refactor canDeleteUser() helper (#7324) Refactor canDeleteUser() --- .../components/admin-users/admin-users.component.ts | 2 ++ .../src/app/components/admin-users/admin-users.html | 7 ++++++- .../user-detail-dialog/user-detail-dialog.component.ts | 7 ++++++- .../user-detail-dialog/user-detail-dialog.html | 7 ++++++- libs/common/src/lib/helper.ts | 10 ++++++++++ 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/apps/client/src/app/components/admin-users/admin-users.component.ts b/apps/client/src/app/components/admin-users/admin-users.component.ts index 4b9848cf8..305c48dcf 100644 --- a/apps/client/src/app/components/admin-users/admin-users.component.ts +++ b/apps/client/src/app/components/admin-users/admin-users.component.ts @@ -8,6 +8,7 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { DEFAULT_LOCALE, DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config'; import { ConfirmationDialogType } from '@ghostfolio/common/enums'; import { + canDeleteUser, getCountryName, getDateFnsLocale, getDateFormatString, @@ -91,6 +92,7 @@ export class GfAdminUsersComponent implements OnInit { >(); protected defaultDateFormat: string; protected displayedColumns: string[] = []; + protected readonly canDeleteUser = canDeleteUser; protected readonly getCountryName = getCountryName; protected readonly getEmojiFlag = getEmojiFlag; protected hasPermissionForSubscription: boolean; diff --git a/apps/client/src/app/components/admin-users/admin-users.html b/apps/client/src/app/components/admin-users/admin-users.html index 668f39557..7e7e5edeb 100644 --- a/apps/client/src/app/components/admin-users/admin-users.html +++ b/apps/client/src/app/components/admin-users/admin-users.html @@ -241,7 +241,12 @@