Browse Source

Merge remote-tracking branch 'origin/main' into task/stats-gathering-tag-service-type-safety

pull/7328/head
KenTandrian 19 hours ago
parent
commit
144be3bd43
  1. 4
      apps/client/eslint.config.cjs
  2. 1
      apps/client/jest.config.ts
  3. 10
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  4. 7
      apps/client/src/app/components/admin-overview/admin-overview.component.ts
  5. 11
      apps/client/src/app/components/admin-overview/admin-overview.html
  6. 2
      apps/client/src/app/components/admin-users/admin-users.component.ts
  7. 7
      apps/client/src/app/components/admin-users/admin-users.html
  8. 7
      apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts
  9. 7
      apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html
  10. 4
      apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts
  11. 2
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
  12. 2
      apps/client/src/app/services/user/user.service.ts
  13. 10
      libs/common/src/lib/helper.ts
  14. 3
      libs/ui/eslint.config.cjs
  15. 2
      libs/ui/src/lib/activities-table/activities-table.component.ts

4
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'],

1
apps/client/jest.config.ts

@ -1,4 +1,3 @@
/* eslint-disable */
export default {
displayName: 'client',

10
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<string, string>,
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<string, string>,
locale:
this.assetProfileForm.controls.scraperConfiguration.controls.locale
?.value || undefined,
?.value ?? undefined,
mode: this.assetProfileForm.controls.scraperConfiguration.controls
.mode?.value,
selector:

7
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();
});
}

11
apps/client/src/app/components/admin-overview/admin-overview.html

@ -248,6 +248,17 @@
mat-row
></tr>
</table>
@if (isLoading) {
<ngx-skeleton-loader
animation="pulse"
class="px-4 py-3"
[theme]="{
height: '1.5rem',
width: '100%'
}"
/>
}
</div>
</mat-card-content>
<mat-card-actions align="end">

2
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;

7
apps/client/src/app/components/admin-users/admin-users.html

@ -241,7 +241,12 @@
<hr class="m-0" />
<button
mat-menu-item
[disabled]="element.id === user?.id"
[disabled]="
!canDeleteUser({
currentUserId: user?.id,
userId: element.id
})
"
(click)="onDeleteUser(element.id)"
>
<span class="align-items-center d-flex">

7
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts

@ -1,4 +1,8 @@
import { getCountryName, getSum } from '@ghostfolio/common/helper';
import {
canDeleteUser,
getCountryName,
getSum
} from '@ghostfolio/common/helper';
import { AdminUserResponse } from '@ghostfolio/common/interfaces';
import { AdminService, DataService } from '@ghostfolio/ui/services';
import { GfValueComponent } from '@ghostfolio/ui/value';
@ -50,6 +54,7 @@ import {
})
export class GfUserDetailDialogComponent implements OnInit {
protected readonly baseCurrency: string;
protected readonly canDeleteUser = canDeleteUser;
protected readonly getCountryName = getCountryName;
protected readonly subscriptionsDataSource =
new MatTableDataSource<Subscription>();

7
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html

@ -16,7 +16,12 @@
<button
mat-menu-item
type="button"
[disabled]="this.data.currentUserId === this.data.userId"
[disabled]="
!canDeleteUser({
currentUserId: data.currentUserId,
userId: data.userId
})
"
(click)="deleteUser()"
>
<ng-container i18n>Delete</ng-container>

4
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) => {

2
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(

2
apps/client/src/app/services/user/user.service.ts

@ -192,6 +192,6 @@ export class UserService extends ObservableStore<UserStoreState> {
return throwError(errMessage);
}
return throwError(error || 'Server error');
return throwError(error ?? 'Server error');
}
}

10
libs/common/src/lib/helper.ts

@ -163,6 +163,16 @@ export function canDeleteAssetProfile({
);
}
export function canDeleteUser({
currentUserId,
userId
}: {
currentUserId: string;
userId: string;
}): boolean {
return currentUserId !== userId;
}
export function capitalize(aString: string) {
return aString.charAt(0).toUpperCase() + aString.slice(1).toLowerCase();
}

3
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: {

2
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

Loading…
Cancel
Save