Browse Source

Merge remote-tracking branch 'upstream/main' into feature/top-holdings-with-parents

pull/4044/head
JoryHogeveen 9 months ago
parent
commit
588f592ff3
  1. 18
      CHANGELOG.md
  2. 10
      apps/api/src/app/admin/admin.controller.ts
  3. 23
      apps/api/src/app/admin/admin.service.ts
  4. 4
      apps/api/src/assets/sitemap.xml
  5. 4
      apps/api/src/middlewares/html-template.middleware.ts
  6. 2
      apps/client/src/app/components/home-holdings/home-holdings.html
  7. 52
      apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html
  8. 3
      apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.scss
  9. 17
      apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts
  10. 180
      apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html
  11. 27
      apps/client/src/app/pages/blog/blog-page-routing.module.ts
  12. 26
      apps/client/src/app/pages/blog/blog-page.html
  13. 6
      apps/client/src/app/services/admin.service.ts
  14. BIN
      apps/client/src/assets/images/blog/black-weeks-2024.jpg
  15. 322
      apps/client/src/locales/messages.ca.xlf
  16. 326
      apps/client/src/locales/messages.de.xlf
  17. 322
      apps/client/src/locales/messages.es.xlf
  18. 322
      apps/client/src/locales/messages.fr.xlf
  19. 342
      apps/client/src/locales/messages.it.xlf
  20. 322
      apps/client/src/locales/messages.nl.xlf
  21. 322
      apps/client/src/locales/messages.pl.xlf
  22. 322
      apps/client/src/locales/messages.pt.xlf
  23. 322
      apps/client/src/locales/messages.tr.xlf
  24. 316
      apps/client/src/locales/messages.xlf
  25. 322
      apps/client/src/locales/messages.zh.xlf
  26. 704
      package-lock.json
  27. 28
      package.json

18
CHANGELOG.md

@ -7,12 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
### Added
- Added pagination parameters (`skip`, `take`) to the endpoint `GET api/v1/admin/user`
### Changed ### Changed
- Upgraded `Nx` from version `20.0.6` to `20.1.2`
## 2.123.0 - 2024-11-16
### Added
- Added a blog post: _Black Weeks 2024_
### Changed
- Moved the chart of the holdings tab on the home page from experimental to general availability
- Extended the assistant by a holding selector - Extended the assistant by a holding selector
- Separated the _FIRE_ / _X-ray_ page - Separated the _FIRE_ / _X-ray_ page
- Improved the usability to customize the rule thresholds in the _X-ray_ page by introducing range sliders (experimental)
- Improved the language localization for German (`de`)
- Improved the language localization for Italian (`it`) - Improved the language localization for Italian (`it`)
- Upgraded `ngx-skeleton-loader` from version `7.0.0` to `9.0.0` - Upgraded `ngx-skeleton-loader` from version `7.0.0` to `9.0.0`
- Upgraded `prisma` from version `5.21.1` to `5.22.0`
- Upgraded `uuid` from version `9.0.1` to `11.0.2` - Upgraded `uuid` from version `9.0.1` to `11.0.2`
## 2.122.0 - 2024-11-07 ## 2.122.0 - 2024-11-07

10
apps/api/src/app/admin/admin.controller.ts

@ -352,7 +352,13 @@ export class AdminController {
@Get('user') @Get('user')
@HasPermission(permissions.accessAdminControl) @HasPermission(permissions.accessAdminControl)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async getUsers(): Promise<AdminUsers> { public async getUsers(
return this.adminService.getUsers(); @Query('skip') skip?: number,
@Query('take') take?: number
): Promise<AdminUsers> {
return this.adminService.getUsers({
skip: isNaN(skip) ? undefined : skip,
take: isNaN(take) ? undefined : take
});
} }
} }

23
apps/api/src/app/admin/admin.service.ts

@ -429,8 +429,14 @@ export class AdminService {
}; };
} }
public async getUsers(): Promise<AdminUsers> { public async getUsers({
return { users: await this.getUsersWithAnalytics() }; skip,
take = Number.MAX_SAFE_INTEGER
}: {
skip?: number;
take?: number;
}): Promise<AdminUsers> {
return { users: await this.getUsersWithAnalytics({ skip, take }) };
} }
public async patchAssetProfileData({ public async patchAssetProfileData({
@ -640,7 +646,13 @@ export class AdminService {
return { marketData, count: marketData.length }; return { marketData, count: marketData.length };
} }
private async getUsersWithAnalytics(): Promise<AdminUsers['users']> { private async getUsersWithAnalytics({
skip,
take
}: {
skip?: number;
take?: number;
}): Promise<AdminUsers['users']> {
let orderBy: Prisma.UserOrderByWithRelationInput = { let orderBy: Prisma.UserOrderByWithRelationInput = {
createdAt: 'desc' createdAt: 'desc'
}; };
@ -661,6 +673,8 @@ export class AdminService {
const usersWithAnalytics = await this.prismaService.user.findMany({ const usersWithAnalytics = await this.prismaService.user.findMany({
orderBy, orderBy,
skip,
take,
where, where,
select: { select: {
_count: { _count: {
@ -677,8 +691,7 @@ export class AdminService {
id: true, id: true,
role: true, role: true,
Subscription: true Subscription: true
}, }
take: 30
}); });
return usersWithAnalytics.map( return usersWithAnalytics.map(

4
apps/api/src/assets/sitemap.xml

@ -188,6 +188,10 @@
<loc>https://ghostfol.io/en/blog/2024/09/hacktoberfest-2024</loc> <loc>https://ghostfol.io/en/blog/2024/09/hacktoberfest-2024</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url> </url>
<url>
<loc>https://ghostfol.io/en/blog/2024/11/black-weeks-2024</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod>
</url>
<url> <url>
<loc>https://ghostfol.io/en/faq</loc> <loc>https://ghostfol.io/en/faq</loc>
<lastmod>${currentDate}T00:00:00+00:00</lastmod> <lastmod>${currentDate}T00:00:00+00:00</lastmod>

4
apps/api/src/middlewares/html-template.middleware.ts

@ -87,6 +87,10 @@ const locales = {
'/en/blog/2024/09/hacktoberfest-2024': { '/en/blog/2024/09/hacktoberfest-2024': {
featureGraphicPath: 'assets/images/blog/hacktoberfest-2024.png', featureGraphicPath: 'assets/images/blog/hacktoberfest-2024.png',
title: `Hacktoberfest 2024 - ${title}` title: `Hacktoberfest 2024 - ${title}`
},
'/en/blog/2024/11/black-weeks-2024': {
featureGraphicPath: 'assets/images/blog/black-weeks-2024.jpg',
title: `Black Weeks 2024 - ${title}`
} }
}; };

2
apps/client/src/app/components/home-holdings/home-holdings.html

@ -7,7 +7,6 @@
<div class="row"> <div class="row">
<div class="col-lg"> <div class="col-lg">
<div class="d-flex"> <div class="d-flex">
@if (user?.settings?.isExperimentalFeatures) {
<div class="d-flex"> <div class="d-flex">
<div class="d-none d-lg-block"> <div class="d-none d-lg-block">
<mat-button-toggle-group <mat-button-toggle-group
@ -23,7 +22,6 @@
</mat-button-toggle-group> </mat-button-toggle-group>
</div> </div>
</div> </div>
}
<div class="align-items-center d-flex flex-grow-1 justify-content-end"> <div class="align-items-center d-flex flex-grow-1 justify-content-end">
<gf-toggle <gf-toggle
class="d-none d-lg-block" class="d-none d-lg-block"

52
apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html

@ -1,6 +1,51 @@
<div mat-dialog-title>{{ data.rule.name }}</div> <div mat-dialog-title>{{ data.rule.name }}</div>
<div class="py-3" mat-dialog-content> <div class="py-3" mat-dialog-content>
@if (
data.rule.configuration.thresholdMin && data.rule.configuration.thresholdMax
) {
<div class="w-100">
<h6 class="mb-0">
<ng-container i18n>Threshold range</ng-container>:
@if (data.rule.configuration.threshold.unit === '%') {
{{ data.settings.thresholdMin | percent: '1.2-2' }}
} @else {
{{ data.settings.thresholdMin }}
}
-
@if (data.rule.configuration.threshold.unit === '%') {
{{ data.settings.thresholdMax | percent: '1.2-2' }}
} @else {
{{ data.settings.thresholdMax }}
}
</h6>
<div class="align-items-center d-flex w-100">
@if (data.rule.configuration.threshold.unit === '%') {
<label>{{
data.rule.configuration.threshold.min | percent: '1.2-2'
}}</label>
} @else {
<label>{{ data.rule.configuration.threshold.min }}</label>
}
<mat-slider
class="flex-grow-1"
[max]="data.rule.configuration.threshold.max"
[min]="data.rule.configuration.threshold.min"
[step]="data.rule.configuration.threshold.step"
>
<input matSliderStartThumb [(ngModel)]="data.settings.thresholdMin" />
<input matSliderEndThumb [(ngModel)]="data.settings.thresholdMax" />
</mat-slider>
@if (data.rule.configuration.threshold.unit === '%') {
<label>{{
data.rule.configuration.threshold.max | percent: '1.2-2'
}}</label>
} @else {
<label>{{ data.rule.configuration.threshold.max }}</label>
}
</div>
</div>
} @else {
<div <div
class="w-100" class="w-100"
[ngClass]="{ 'd-none': !data.rule.configuration.thresholdMin }" [ngClass]="{ 'd-none': !data.rule.configuration.thresholdMin }"
@ -13,6 +58,7 @@
{{ data.settings.thresholdMin }} {{ data.settings.thresholdMin }}
} }
</h6> </h6>
<div class="align-items-center d-flex w-100">
@if (data.rule.configuration.threshold.unit === '%') { @if (data.rule.configuration.threshold.unit === '%') {
<label>{{ <label>{{
data.rule.configuration.threshold.min | percent: '1.2-2' data.rule.configuration.threshold.min | percent: '1.2-2'
@ -21,6 +67,7 @@
<label>{{ data.rule.configuration.threshold.min }}</label> <label>{{ data.rule.configuration.threshold.min }}</label>
} }
<mat-slider <mat-slider
class="flex-grow-1"
name="thresholdMin" name="thresholdMin"
[max]="data.rule.configuration.threshold.max" [max]="data.rule.configuration.threshold.max"
[min]="data.rule.configuration.threshold.min" [min]="data.rule.configuration.threshold.min"
@ -36,6 +83,7 @@
<label>{{ data.rule.configuration.threshold.max }}</label> <label>{{ data.rule.configuration.threshold.max }}</label>
} }
</div> </div>
</div>
<div <div
class="w-100" class="w-100"
[ngClass]="{ 'd-none': !data.rule.configuration.thresholdMax }" [ngClass]="{ 'd-none': !data.rule.configuration.thresholdMax }"
@ -48,6 +96,7 @@
{{ data.settings.thresholdMax }} {{ data.settings.thresholdMax }}
} }
</h6> </h6>
<div class="align-items-center d-flex w-100">
@if (data.rule.configuration.threshold.unit === '%') { @if (data.rule.configuration.threshold.unit === '%') {
<label>{{ <label>{{
data.rule.configuration.threshold.min | percent: '1.2-2' data.rule.configuration.threshold.min | percent: '1.2-2'
@ -56,6 +105,7 @@
<label>{{ data.rule.configuration.threshold.min }}</label> <label>{{ data.rule.configuration.threshold.min }}</label>
} }
<mat-slider <mat-slider
class="flex-grow-1"
name="thresholdMax" name="thresholdMax"
[max]="data.rule.configuration.threshold.max" [max]="data.rule.configuration.threshold.max"
[min]="data.rule.configuration.threshold.min" [min]="data.rule.configuration.threshold.min"
@ -71,6 +121,8 @@
<label>{{ data.rule.configuration.threshold.max }}</label> <label>{{ data.rule.configuration.threshold.max }}</label>
} }
</div> </div>
</div>
}
</div> </div>
<div align="end" mat-dialog-actions> <div align="end" mat-dialog-actions>

3
apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.scss

@ -1,2 +1,5 @@
:host { :host {
label {
margin-bottom: 0;
}
} }

17
apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts

@ -0,0 +1,17 @@
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@Component({
host: { class: 'page' },
imports: [GfPremiumIndicatorComponent, MatButtonModule, RouterModule],
selector: 'gf-black-weeks-2024-page',
standalone: true,
templateUrl: './black-weeks-2024-page.html'
})
export class BlackWeeks2024PageComponent {
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
}

180
apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html

@ -0,0 +1,180 @@
<div class="blog container">
<div class="row">
<div class="col-md-8 offset-md-2">
<article>
<div class="mb-4 text-center">
<h1 class="mb-1">Black Weeks 2024</h1>
<div class="mb-3 text-muted"><small>2024-11-16</small></div>
<img
alt="Black Week 2024 Teaser"
class="rounded w-100"
src="../assets/images/blog/black-weeks-2024.jpg"
title="Black Weeks 2024"
/>
</div>
<section class="mb-4">
<p>
Take advantage of our exclusive <strong>Black Weeks</strong> offer
and save <strong>25%</strong> on your annual
<span class="align-items-center d-inline-flex"
>Ghostfolio Premium
<gf-premium-indicator
class="d-inline-block ml-1"
[enableLink]="false"
/>
</span>
subscription, plus get <strong>3 months extra</strong> for free!
</p>
</section>
<section class="mb-4">
<p>
<a
href="https://ghostfol.io"
title="Open Source Wealth Management Software"
>Ghostfolio</a
>
is a powerful personal finance dashboard, designed to simplify your
investment journey. With this Open Source Software (OSS) platform,
you can:
</p>
<ul class="list-unstyled">
<li>
<strong>Unify your assets</strong>: Track your financial
portfolio, including stocks, ETFs, cryptocurrencies, etc.
</li>
<li>
<strong>Gain deeper insights</strong>: Access real-time analytics
and data-driven insights.
</li>
<li>
<strong>Make informed decisions</strong>: Empower yourself with
actionable information.
</li>
</ul>
</section>
<section class="mb-4">
<p>
Don’t miss this limited-time offer to optimize your financial
future.
</p>
<p class="text-center">
<a color="primary" mat-flat-button [routerLink]="routerLinkPricing"
>Get the Deal</a
>
</p>
<p class="mt-5">
For more information, visit our
<a [routerLink]="routerLinkPricing">pricing page</a>.
</p>
</section>
<section class="mb-4">
<ul class="list-inline">
<li class="list-inline-item">
<span class="badge badge-light">2024</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Black Friday</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Black Weeks</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Cryptocurrency</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Dashboard</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Deal</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">DeFi</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">ETF</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Finance</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Fintech</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Ghostfolio</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Ghostfolio Premium</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Hosting</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Investment</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Open Source</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">OSS</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Personal Finance</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Portfolio</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Portfolio Tracker</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Pricing</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Promotion</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">SaaS</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Sale</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Software</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Stock</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Subscription</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Wealth</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Wealth Management</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Web3</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Web 3.0</span>
</li>
</ul>
</section>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a i18n [routerLink]="['/blog']">Blog</a>
</li>
<li
aria-current="page"
class="active breadcrumb-item text-truncate"
>
Black Weeks 2024
</li>
</ol>
</nav>
</article>
</div>
</div>
</div>

27
apps/client/src/app/pages/blog/blog-page-routing.module.ts

@ -165,15 +165,6 @@ const routes: Routes = [
).then((c) => c.Hacktoberfest2023PageComponent), ).then((c) => c.Hacktoberfest2023PageComponent),
title: 'Hacktoberfest 2023' title: 'Hacktoberfest 2023'
}, },
{
canActivate: [AuthGuard],
path: '2023/11/hacktoberfest-2023-debriefing',
loadComponent: () =>
import(
'./2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component'
).then((c) => c.Hacktoberfest2023DebriefingPageComponent),
title: 'Hacktoberfest 2023 Debriefing'
},
{ {
canActivate: [AuthGuard], canActivate: [AuthGuard],
path: '2023/11/black-week-2023', path: '2023/11/black-week-2023',
@ -183,6 +174,15 @@ const routes: Routes = [
), ),
title: 'Black Week 2023' title: 'Black Week 2023'
}, },
{
canActivate: [AuthGuard],
path: '2023/11/hacktoberfest-2023-debriefing',
loadComponent: () =>
import(
'./2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component'
).then((c) => c.Hacktoberfest2023DebriefingPageComponent),
title: 'Hacktoberfest 2023 Debriefing'
},
{ {
canActivate: [AuthGuard], canActivate: [AuthGuard],
path: '2024/09/hacktoberfest-2024', path: '2024/09/hacktoberfest-2024',
@ -191,6 +191,15 @@ const routes: Routes = [
'./2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component' './2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component'
).then((c) => c.Hacktoberfest2024PageComponent), ).then((c) => c.Hacktoberfest2024PageComponent),
title: 'Hacktoberfest 2024' title: 'Hacktoberfest 2024'
},
{
canActivate: [AuthGuard],
path: '2024/11/black-weeks-2024',
loadComponent: () =>
import('./2024/11/black-weeks-2024/black-weeks-2024-page.component').then(
(c) => c.BlackWeeks2024PageComponent
),
title: 'Black Weeks 2024'
} }
]; ];

26
apps/client/src/app/pages/blog/blog-page.html

@ -8,6 +8,32 @@
finance</small finance</small
> >
</h1> </h1>
@if (hasPermissionForSubscription) {
<mat-card appearance="outlined" class="mb-3">
<mat-card-content class="p-0">
<div class="container p-0">
<div class="flex-nowrap no-gutters row">
<a
class="d-flex overflow-hidden p-3 w-100"
href="../en/blog/2024/11/black-weeks-2024"
>
<div class="flex-grow-1 overflow-hidden">
<div class="h6 m-0 text-truncate">Black Weeks 2024</div>
<div class="d-flex text-muted">2024-11-16</div>
</div>
<div class="align-items-center d-flex">
<ion-icon
class="chevron text-muted"
name="chevron-forward-outline"
size="small"
/>
</div>
</a>
</div>
</div>
</mat-card-content>
</mat-card>
}
<mat-card appearance="outlined" class="mb-3"> <mat-card appearance="outlined" class="mb-3">
<mat-card-content class="p-0"> <mat-card-content class="p-0">
<div class="container p-0"> <div class="container p-0">

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

@ -157,7 +157,11 @@ export class AdminService {
} }
public fetchUsers() { public fetchUsers() {
return this.http.get<AdminUsers>('/api/v1/admin/user'); let params = new HttpParams();
params = params.append('take', 100);
return this.http.get<AdminUsers>('/api/v1/admin/user', { params });
} }
public gather7Days() { public gather7Days() {

BIN
apps/client/src/assets/images/blog/black-weeks-2024.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

322
apps/client/src/locales/messages.ca.xlf

File diff suppressed because it is too large

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

File diff suppressed because it is too large

322
apps/client/src/locales/messages.es.xlf

File diff suppressed because it is too large

322
apps/client/src/locales/messages.fr.xlf

File diff suppressed because it is too large

342
apps/client/src/locales/messages.it.xlf

File diff suppressed because it is too large

322
apps/client/src/locales/messages.nl.xlf

File diff suppressed because it is too large

322
apps/client/src/locales/messages.pl.xlf

File diff suppressed because it is too large

322
apps/client/src/locales/messages.pt.xlf

File diff suppressed because it is too large

322
apps/client/src/locales/messages.tr.xlf

File diff suppressed because it is too large

316
apps/client/src/locales/messages.xlf

File diff suppressed because it is too large

322
apps/client/src/locales/messages.zh.xlf

File diff suppressed because it is too large

704
package-lock.json

File diff suppressed because it is too large

28
package.json

@ -1,6 +1,6 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.122.0", "version": "2.123.0",
"homepage": "https://ghostfol.io", "homepage": "https://ghostfol.io",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio", "repository": "https://github.com/ghostfolio/ghostfolio",
@ -86,7 +86,7 @@
"@nestjs/platform-express": "10.1.3", "@nestjs/platform-express": "10.1.3",
"@nestjs/schedule": "3.0.2", "@nestjs/schedule": "3.0.2",
"@nestjs/serve-static": "4.0.0", "@nestjs/serve-static": "4.0.0",
"@prisma/client": "5.21.1", "@prisma/client": "5.22.0",
"@simplewebauthn/browser": "9.0.1", "@simplewebauthn/browser": "9.0.1",
"@simplewebauthn/server": "9.0.3", "@simplewebauthn/server": "9.0.3",
"@stripe/stripe-js": "4.9.0", "@stripe/stripe-js": "4.9.0",
@ -153,16 +153,16 @@
"@angular/pwa": "18.2.9", "@angular/pwa": "18.2.9",
"@nestjs/schematics": "10.0.1", "@nestjs/schematics": "10.0.1",
"@nestjs/testing": "10.1.3", "@nestjs/testing": "10.1.3",
"@nx/angular": "20.0.6", "@nx/angular": "20.1.2",
"@nx/cypress": "20.0.6", "@nx/cypress": "20.1.2",
"@nx/eslint-plugin": "20.0.6", "@nx/eslint-plugin": "20.1.2",
"@nx/jest": "20.0.6", "@nx/jest": "20.1.2",
"@nx/js": "20.0.6", "@nx/js": "20.1.2",
"@nx/nest": "20.0.6", "@nx/nest": "20.1.2",
"@nx/node": "20.0.6", "@nx/node": "20.1.2",
"@nx/storybook": "20.0.6", "@nx/storybook": "20.1.2",
"@nx/web": "20.0.6", "@nx/web": "20.1.2",
"@nx/workspace": "20.0.6", "@nx/workspace": "20.1.2",
"@schematics/angular": "18.2.9", "@schematics/angular": "18.2.9",
"@simplewebauthn/types": "9.0.1", "@simplewebauthn/types": "9.0.1",
"@storybook/addon-essentials": "8.3.6", "@storybook/addon-essentials": "8.3.6",
@ -193,10 +193,10 @@
"jest": "29.7.0", "jest": "29.7.0",
"jest-environment-jsdom": "29.7.0", "jest-environment-jsdom": "29.7.0",
"jest-preset-angular": "14.1.0", "jest-preset-angular": "14.1.0",
"nx": "20.0.6", "nx": "20.1.2",
"prettier": "3.3.3", "prettier": "3.3.3",
"prettier-plugin-organize-attributes": "1.0.0", "prettier-plugin-organize-attributes": "1.0.0",
"prisma": "5.21.1", "prisma": "5.22.0",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"replace-in-file": "7.0.1", "replace-in-file": "7.0.1",

Loading…
Cancel
Save