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/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) { + + } 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 @@