Browse Source

Merge branch 'main' into Task/upgrade-class-validator-to-version-0.14.3

pull/6091/head
Thomas Kaul 1 month ago
committed by GitHub
parent
commit
207f08eec5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 11
      CHANGELOG.md
  2. 2
      apps/api/src/app/app.module.ts
  3. 22
      apps/api/src/app/endpoints/platforms/platforms.controller.ts
  4. 11
      apps/api/src/app/endpoints/platforms/platforms.module.ts
  5. 1
      apps/api/src/app/portfolio/portfolio.service.ts
  6. 26
      apps/client/src/app/components/admin-users/admin-users.component.ts
  7. 6
      apps/client/src/app/components/admin-users/admin-users.html
  8. 11
      apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts
  9. 5
      apps/client/src/app/pages/admin/admin-page.routes.ts
  10. 4
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
  11. 6
      apps/client/src/app/services/data.service.ts
  12. 6
      apps/client/src/locales/messages.de.xlf
  13. 4
      apps/client/src/test-setup.ts
  14. 2
      libs/common/src/lib/interfaces/index.ts
  15. 3
      libs/common/src/lib/interfaces/info-item.interface.ts
  16. 1
      libs/common/src/lib/interfaces/portfolio-summary.interface.ts
  17. 5
      libs/common/src/lib/interfaces/responses/platforms-response.interface.ts
  18. 2
      libs/common/src/lib/permissions.ts
  19. 0
      libs/ui/.storybook/main.mjs
  20. 7
      libs/ui/project.json
  21. 4
      libs/ui/src/test-setup.ts
  22. 1
      libs/ui/tsconfig.json
  23. 39197
      package-lock.json
  24. 40
      package.json

11
CHANGELOG.md

@ -7,17 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
### Added
- Added a new endpoint to get all platforms (`GET api/v1/platforms`)
### Changed ### Changed
- Improved the routing of the user detail dialog in the users section of the admin control panel
- Lifted the asset profile identifier editing restriction for `MANUAL` data sources in the asset profile details dialog of the admin control panel - Lifted the asset profile identifier editing restriction for `MANUAL` data sources in the asset profile details dialog of the admin control panel
- Improved the language localization for German (`de`)
- Upgraded `angular` from version `20.2.4` to `20.3.9` - Upgraded `angular` from version `20.2.4` to `20.3.9`
- Upgraded `class-validator` from version `0.14.2` to `0.14.3` - Upgraded `class-validator` from version `0.14.2` to `0.14.3`
- Upgraded `Nx` from version `21.5.1` to `22.0.4` - Upgraded `ng-extract-i18n-merge` from `3.1.0` to `3.2.1`
- Upgraded `Nx` from version `21.5.1` to `22.1.3`
- Upgraded `shx` from version `0.3.4` to `0.4.0` - Upgraded `shx` from version `0.3.4` to `0.4.0`
- Upgraded `storybook` from version `9.1.5` to `10.1.10`
### Fixed ### Fixed
- Added the missing currency suffix to the cash balance field in the create or update account dialog - Added the missing currency suffix to the cash balance field in the create or update account dialog
- Fixed the time in market display of the portfolio summary tab on the home page for the impersonation mode
- Fixed the delete button in the asset profile details dialog of the admin control panel by providing the missing `watchedByCount` parameter - Fixed the delete button in the asset profile details dialog of the admin control panel by providing the missing `watchedByCount` parameter
## 2.224.2 - 2025-12-20 ## 2.224.2 - 2025-12-20

2
apps/api/src/app/app.module.ts

@ -37,6 +37,7 @@ import { AssetsModule } from './endpoints/assets/assets.module';
import { BenchmarksModule } from './endpoints/benchmarks/benchmarks.module'; import { BenchmarksModule } from './endpoints/benchmarks/benchmarks.module';
import { GhostfolioModule } from './endpoints/data-providers/ghostfolio/ghostfolio.module'; import { GhostfolioModule } from './endpoints/data-providers/ghostfolio/ghostfolio.module';
import { MarketDataModule } from './endpoints/market-data/market-data.module'; import { MarketDataModule } from './endpoints/market-data/market-data.module';
import { PlatformsModule } from './endpoints/platforms/platforms.module';
import { PublicModule } from './endpoints/public/public.module'; import { PublicModule } from './endpoints/public/public.module';
import { SitemapModule } from './endpoints/sitemap/sitemap.module'; import { SitemapModule } from './endpoints/sitemap/sitemap.module';
import { TagsModule } from './endpoints/tags/tags.module'; import { TagsModule } from './endpoints/tags/tags.module';
@ -95,6 +96,7 @@ import { UserModule } from './user/user.module';
MarketDataModule, MarketDataModule,
OrderModule, OrderModule,
PlatformModule, PlatformModule,
PlatformsModule,
PortfolioModule, PortfolioModule,
PortfolioSnapshotQueueModule, PortfolioSnapshotQueueModule,
PrismaModule, PrismaModule,

22
apps/api/src/app/endpoints/platforms/platforms.controller.ts

@ -0,0 +1,22 @@
import { PlatformService } from '@ghostfolio/api/app/platform/platform.service';
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { PlatformsResponse } from '@ghostfolio/common/interfaces';
import { permissions } from '@ghostfolio/common/permissions';
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Controller('platforms')
export class PlatformsController {
public constructor(private readonly platformService: PlatformService) {}
@Get()
@HasPermission(permissions.readPlatforms)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async getPlatforms(): Promise<PlatformsResponse> {
const platforms = await this.platformService.getPlatforms();
return { platforms };
}
}

11
apps/api/src/app/endpoints/platforms/platforms.module.ts

@ -0,0 +1,11 @@
import { PlatformModule } from '@ghostfolio/api/app/platform/platform.module';
import { Module } from '@nestjs/common';
import { PlatformsController } from './platforms.controller';
@Module({
controllers: [PlatformsController],
imports: [PlatformModule]
})
export class PlatformsModule {}

1
apps/api/src/app/portfolio/portfolio.service.ts

@ -1954,6 +1954,7 @@ export class PortfolioService {
}).length, }).length,
committedFunds: committedFunds.toNumber(), committedFunds: committedFunds.toNumber(),
currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(), currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(),
dateOfFirstActivity: firstOrderDate,
dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), dividendInBaseCurrency: dividendInBaseCurrency.toNumber(),
emergencyFund: { emergencyFund: {
assets: emergencyFundHoldingsValueInBaseCurrency, assets: emergencyFundHoldingsValueInBaseCurrency,

26
apps/client/src/app/components/admin-users/admin-users.component.ts

@ -18,6 +18,7 @@ import {
User User
} 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 { NotificationService } from '@ghostfolio/ui/notifications'; import { NotificationService } from '@ghostfolio/ui/notifications';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { GfValueComponent } from '@ghostfolio/ui/value'; import { GfValueComponent } from '@ghostfolio/ui/value';
@ -39,7 +40,7 @@ import {
PageEvent PageEvent
} from '@angular/material/paginator'; } from '@angular/material/paginator';
import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone'; import { IonIcon } from '@ionic/angular/standalone';
import { import {
differenceInSeconds, differenceInSeconds,
@ -69,7 +70,8 @@ import { takeUntil } from 'rxjs/operators';
MatMenuModule, MatMenuModule,
MatPaginatorModule, MatPaginatorModule,
MatTableModule, MatTableModule,
NgxSkeletonLoaderModule NgxSkeletonLoaderModule,
RouterModule
], ],
selector: 'gf-admin-users', selector: 'gf-admin-users',
styleUrls: ['./admin-users.scss'], styleUrls: ['./admin-users.scss'],
@ -88,6 +90,8 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
public info: InfoItem; public info: InfoItem;
public isLoading = false; public isLoading = false;
public pageSize = DEFAULT_PAGE_SIZE; public pageSize = DEFAULT_PAGE_SIZE;
public routerLinkAdminControlUsers =
internalRoutes.adminControl.subRoutes.users.routerLink;
public totalItems = 0; public totalItems = 0;
public user: User; public user: User;
@ -136,11 +140,13 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
]; ];
} }
this.route.queryParams this.route.paramMap
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe((params) => { .subscribe((params) => {
if (params['userDetailDialog'] && params['userId']) { const userId = params.get('userId');
this.openUserDetailDialog(params['userId']);
if (userId) {
this.openUserDetailDialog(userId);
} }
}); });
@ -248,9 +254,9 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
} }
public onOpenUserDetailDialog(userId: string) { public onOpenUserDetailDialog(userId: string) {
this.router.navigate([], { this.router.navigate(
queryParams: { userId, userDetailDialog: true } internalRoutes.adminControl.subRoutes.users.routerLink.concat(userId)
}); );
} }
public ngOnDestroy() { public ngOnDestroy() {
@ -301,7 +307,9 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
.afterClosed() .afterClosed()
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => { .subscribe(() => {
this.router.navigate(['.'], { relativeTo: this.route }); this.router.navigate(
internalRoutes.adminControl.subRoutes.users.routerLink
);
}); });
} }
} }

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

@ -215,9 +215,9 @@
<ion-icon name="ellipsis-horizontal" /> <ion-icon name="ellipsis-horizontal" />
</button> </button>
<mat-menu #userMenu="matMenu" xPosition="before"> <mat-menu #userMenu="matMenu" xPosition="before">
<button <a
mat-menu-item mat-menu-item
(click)="onOpenUserDetailDialog(element.id)" [routerLink]="routerLinkAdminControlUsers.concat(element.id)"
> >
<span class="align-items-center d-flex"> <span class="align-items-center d-flex">
<ion-icon class="mr-2" name="person-outline" /> <ion-icon class="mr-2" name="person-outline" />
@ -225,7 +225,7 @@
><ng-container i18n>View Details</ng-container>...</span ><ng-container i18n>View Details</ng-container>...</span
> >
</span> </span>
</button> </a>
@if (hasPermissionToImpersonateAllUsers) { @if (hasPermissionToImpersonateAllUsers) {
<button mat-menu-item (click)="onImpersonateUser(element.id)"> <button mat-menu-item (click)="onImpersonateUser(element.id)">
<span class="align-items-center d-flex"> <span class="align-items-center d-flex">

11
apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts

@ -84,10 +84,13 @@ export class GfPortfolioSummaryComponent implements OnChanges {
this.precision = 0; this.precision = 0;
} }
if (this.user.dateOfFirstActivity) { if (this.summary.dateOfFirstActivity) {
this.timeInMarket = formatDistanceToNow(this.user.dateOfFirstActivity, { this.timeInMarket = formatDistanceToNow(
locale: getDateFnsLocale(this.language) this.summary.dateOfFirstActivity,
}); {
locale: getDateFnsLocale(this.language)
}
);
} else { } else {
this.timeInMarket = '-'; this.timeInMarket = '-';
} }

5
apps/client/src/app/pages/admin/admin-page.routes.ts

@ -38,6 +38,11 @@ export const routes: Routes = [
path: internalRoutes.adminControl.subRoutes.users.path, path: internalRoutes.adminControl.subRoutes.users.path,
component: GfAdminUsersComponent, component: GfAdminUsersComponent,
title: internalRoutes.adminControl.subRoutes.users.title title: internalRoutes.adminControl.subRoutes.users.title
},
{
path: `${internalRoutes.adminControl.subRoutes.users.path}/:userId`,
component: GfAdminUsersComponent,
title: internalRoutes.adminControl.subRoutes.users.title
} }
], ],
component: AdminPageComponent, component: AdminPageComponent,

4
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts

@ -96,7 +96,6 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
public isLoading = false; public isLoading = false;
public isToday = isToday; public isToday = isToday;
public mode: 'create' | 'update'; public mode: 'create' | 'update';
public platforms: { id: string; name: string }[];
public tagsAvailable: Tag[] = []; public tagsAvailable: Tag[] = [];
public total = 0; public total = 0;
public typesTranslationMap = new Map<Type, string>(); public typesTranslationMap = new Map<Type, string>();
@ -127,11 +126,10 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
this.dateAdapter.setLocale(this.locale); this.dateAdapter.setLocale(this.locale);
const { currencies, platforms } = this.dataService.fetchInfo(); const { currencies } = this.dataService.fetchInfo();
this.currencies = currencies; this.currencies = currencies;
this.defaultDateFormat = getDateFormatString(this.locale); this.defaultDateFormat = getDateFormatString(this.locale);
this.platforms = platforms;
this.dataService this.dataService
.fetchPortfolioHoldings() .fetchPortfolioHoldings()

6
apps/client/src/app/services/data.service.ts

@ -564,6 +564,12 @@ export class DataService {
} }
} }
if (response.summary?.dateOfFirstActivity) {
response.summary.dateOfFirstActivity = parseISO(
response.summary.dateOfFirstActivity
);
}
return response; return response;
}) })
); );

6
apps/client/src/locales/messages.de.xlf

@ -3475,7 +3475,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5499742151525073097" datatype="html"> <trans-unit id="5499742151525073097" datatype="html">
<source>Upgrade Plan</source> <source>Upgrade Plan</source>
<target state="translated">Abonnement abschliessen</target> <target state="translated">Mitgliedschaft abschliessen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
<context context-type="linenumber">193</context> <context context-type="linenumber">193</context>
@ -3747,7 +3747,7 @@
</trans-unit> </trans-unit>
<trans-unit id="2030314101752312029" datatype="html"> <trans-unit id="2030314101752312029" datatype="html">
<source>Renew Plan</source> <source>Renew Plan</source>
<target state="translated">Abonnement erneuern</target> <target state="translated">Mitgliedschaft erneuern</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
<context context-type="linenumber">191</context> <context context-type="linenumber">191</context>
@ -6934,7 +6934,7 @@
</trans-unit> </trans-unit>
<trans-unit id="7522916136412124285" datatype="html"> <trans-unit id="7522916136412124285" datatype="html">
<source>to use our referral link and get a Ghostfolio Premium membership for one year</source> <source>to use our referral link and get a Ghostfolio Premium membership for one year</source>
<target state="translated">um unseren Empfehlungslink zu verwenden und ein Ghostfolio Premium-Abonnement für ein Jahr zu erhalten</target> <target state="translated">um unseren Empfehlungslink zu verwenden und eine Ghostfolio Premium-Mitgliedschaft für ein Jahr zu erhalten</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">343</context> <context context-type="linenumber">343</context>

4
apps/client/src/test-setup.ts

@ -1 +1,3 @@
import 'jest-preset-angular/setup-jest'; import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
setupZoneTestEnv();

2
libs/common/src/lib/interfaces/index.ts

@ -68,6 +68,7 @@ import type { LookupResponse } from './responses/lookup-response.interface';
import type { MarketDataDetailsResponse } from './responses/market-data-details-response.interface'; import type { MarketDataDetailsResponse } from './responses/market-data-details-response.interface';
import type { MarketDataOfMarketsResponse } from './responses/market-data-of-markets-response.interface'; import type { MarketDataOfMarketsResponse } from './responses/market-data-of-markets-response.interface';
import type { OAuthResponse } from './responses/oauth-response.interface'; import type { OAuthResponse } from './responses/oauth-response.interface';
import type { PlatformsResponse } from './responses/platforms-response.interface';
import type { PortfolioDividendsResponse } from './responses/portfolio-dividends-response.interface'; import type { PortfolioDividendsResponse } from './responses/portfolio-dividends-response.interface';
import type { PortfolioHoldingResponse } from './responses/portfolio-holding-response.interface'; import type { PortfolioHoldingResponse } from './responses/portfolio-holding-response.interface';
import type { PortfolioHoldingsResponse } from './responses/portfolio-holdings-response.interface'; import type { PortfolioHoldingsResponse } from './responses/portfolio-holdings-response.interface';
@ -158,6 +159,7 @@ export {
MarketDataDetailsResponse, MarketDataDetailsResponse,
MarketDataOfMarketsResponse, MarketDataOfMarketsResponse,
OAuthResponse, OAuthResponse,
PlatformsResponse,
PortfolioChart, PortfolioChart,
PortfolioDetails, PortfolioDetails,
PortfolioDividendsResponse, PortfolioDividendsResponse,

3
libs/common/src/lib/interfaces/info-item.interface.ts

@ -13,7 +13,10 @@ export interface InfoItem {
globalPermissions: string[]; globalPermissions: string[];
isDataGatheringEnabled?: string; isDataGatheringEnabled?: string;
isReadOnlyMode?: boolean; isReadOnlyMode?: boolean;
/** @deprecated */
platforms: Platform[]; platforms: Platform[];
statistics: Statistics; statistics: Statistics;
stripePublicKey?: string; stripePublicKey?: string;
subscriptionOffer?: SubscriptionOffer; subscriptionOffer?: SubscriptionOffer;

1
libs/common/src/lib/interfaces/portfolio-summary.interface.ts

@ -7,6 +7,7 @@ export interface PortfolioSummary extends PortfolioPerformance {
annualizedPerformancePercentWithCurrencyEffect: number; annualizedPerformancePercentWithCurrencyEffect: number;
cash: number; cash: number;
committedFunds: number; committedFunds: number;
dateOfFirstActivity: Date;
dividendInBaseCurrency: number; dividendInBaseCurrency: number;
emergencyFund: { emergencyFund: {
assets: number; assets: number;

5
libs/common/src/lib/interfaces/responses/platforms-response.interface.ts

@ -0,0 +1,5 @@
import { Platform } from '@prisma/client';
export interface PlatformsResponse {
platforms: Platform[];
}

2
libs/common/src/lib/permissions.ts

@ -93,6 +93,7 @@ export function getPermissions(aRole: Role): string[] {
permissions.readAiPrompt, permissions.readAiPrompt,
permissions.readMarketData, permissions.readMarketData,
permissions.readMarketDataOfOwnAssetProfile, permissions.readMarketDataOfOwnAssetProfile,
permissions.readPlatforms,
permissions.readPlatformsWithAccountCount, permissions.readPlatformsWithAccountCount,
permissions.readTags, permissions.readTags,
permissions.readWatchlist, permissions.readWatchlist,
@ -136,6 +137,7 @@ export function getPermissions(aRole: Role): string[] {
permissions.deleteWatchlistItem, permissions.deleteWatchlistItem,
permissions.readAiPrompt, permissions.readAiPrompt,
permissions.readMarketDataOfOwnAssetProfile, permissions.readMarketDataOfOwnAssetProfile,
permissions.readPlatforms,
permissions.readWatchlist, permissions.readWatchlist,
permissions.updateAccount, permissions.updateAccount,
permissions.updateAccess, permissions.updateAccess,

0
libs/ui/.storybook/main.js → libs/ui/.storybook/main.mjs

7
libs/ui/project.json

@ -31,12 +31,7 @@
"browserTarget": "ui:build-storybook", "browserTarget": "ui:build-storybook",
"compodoc": false, "compodoc": false,
"configDir": "libs/ui/.storybook", "configDir": "libs/ui/.storybook",
"port": 4400, "port": 4400
"styles": [
"apps/client/src/assets/fonts/inter.css",
"apps/client/src/styles/theme.scss",
"apps/client/src/styles.scss"
]
}, },
"configurations": { "configurations": {
"ci": { "ci": {

4
libs/ui/src/test-setup.ts

@ -1 +1,3 @@
import 'jest-preset-angular/setup-jest'; import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
setupZoneTestEnv();

1
libs/ui/tsconfig.json

@ -14,6 +14,7 @@
} }
], ],
"compilerOptions": { "compilerOptions": {
"moduleResolution": "bundler",
"target": "es2020", "target": "es2020",
// TODO: Remove once solved in tsconfig.base.json // TODO: Remove once solved in tsconfig.base.json
"strict": false, "strict": false,

39197
package-lock.json

File diff suppressed because it is too large

40
package.json

@ -116,7 +116,7 @@
"lodash": "4.17.21", "lodash": "4.17.21",
"marked": "15.0.4", "marked": "15.0.4",
"ms": "3.0.0-canary.1", "ms": "3.0.0-canary.1",
"ng-extract-i18n-merge": "3.1.0", "ng-extract-i18n-merge": "3.2.1",
"ngx-device-detector": "10.1.0", "ngx-device-detector": "10.1.0",
"ngx-markdown": "20.0.0", "ngx-markdown": "20.0.0",
"ngx-skeleton-loader": "11.3.0", "ngx-skeleton-loader": "11.3.0",
@ -153,23 +153,23 @@
"@eslint/js": "9.35.0", "@eslint/js": "9.35.0",
"@nestjs/schematics": "11.0.9", "@nestjs/schematics": "11.0.9",
"@nestjs/testing": "11.1.8", "@nestjs/testing": "11.1.8",
"@nx/angular": "22.0.4", "@nx/angular": "22.1.3",
"@nx/eslint-plugin": "22.0.4", "@nx/eslint-plugin": "22.1.3",
"@nx/jest": "22.0.4", "@nx/jest": "22.1.3",
"@nx/js": "22.0.4", "@nx/js": "22.1.3",
"@nx/module-federation": "22.0.4", "@nx/module-federation": "22.1.3",
"@nx/nest": "22.0.4", "@nx/nest": "22.1.3",
"@nx/node": "22.0.4", "@nx/node": "22.1.3",
"@nx/storybook": "22.0.4", "@nx/storybook": "22.1.3",
"@nx/web": "22.0.4", "@nx/web": "22.1.3",
"@nx/workspace": "22.0.4", "@nx/workspace": "22.1.3",
"@schematics/angular": "20.3.9", "@schematics/angular": "20.3.9",
"@storybook/addon-docs": "9.1.5", "@storybook/addon-docs": "10.1.10",
"@storybook/angular": "9.1.5", "@storybook/angular": "10.1.10",
"@trivago/prettier-plugin-sort-imports": "5.2.2", "@trivago/prettier-plugin-sort-imports": "5.2.2",
"@types/big.js": "6.2.2", "@types/big.js": "6.2.2",
"@types/google-spreadsheet": "3.1.5", "@types/google-spreadsheet": "3.1.5",
"@types/jest": "29.5.13", "@types/jest": "30.0.0",
"@types/lodash": "4.17.20", "@types/lodash": "4.17.20",
"@types/node": "22.15.17", "@types/node": "22.15.17",
"@types/papaparse": "5.3.7", "@types/papaparse": "5.3.7",
@ -180,12 +180,12 @@
"eslint": "9.35.0", "eslint": "9.35.0",
"eslint-config-prettier": "10.1.8", "eslint-config-prettier": "10.1.8",
"eslint-plugin-import": "2.32.0", "eslint-plugin-import": "2.32.0",
"eslint-plugin-storybook": "9.1.5", "eslint-plugin-storybook": "10.1.10",
"husky": "9.1.7", "husky": "9.1.7",
"jest": "29.7.0", "jest": "30.2.0",
"jest-environment-jsdom": "29.7.0", "jest-environment-jsdom": "30.2.0",
"jest-preset-angular": "14.6.0", "jest-preset-angular": "16.0.0",
"nx": "22.0.4", "nx": "22.1.3",
"prettier": "3.7.4", "prettier": "3.7.4",
"prettier-plugin-organize-attributes": "1.0.0", "prettier-plugin-organize-attributes": "1.0.0",
"prisma": "6.19.0", "prisma": "6.19.0",
@ -193,7 +193,7 @@
"react-dom": "18.2.0", "react-dom": "18.2.0",
"replace-in-file": "8.3.0", "replace-in-file": "8.3.0",
"shx": "0.4.0", "shx": "0.4.0",
"storybook": "9.1.5", "storybook": "10.1.10",
"ts-jest": "29.4.0", "ts-jest": "29.4.0",
"ts-node": "10.9.2", "ts-node": "10.9.2",
"tslib": "2.8.1", "tslib": "2.8.1",

Loading…
Cancel
Save