diff --git a/CHANGELOG.md b/CHANGELOG.md index cca96727b..3f4b13899 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the language localization in the users table of the admin control panel - Refactored the accounts pages to standalone - Refactored the portfolio pages to standalone +- Refactored the user account pages to standalone - Renamed `Settings` to `settings` in the `User` database schema - Improved the language localization for Catalan (`ca`) - Improved the language localization for Dutch (`nl`) diff --git a/apps/client/src/app/app-routing.module.ts b/apps/client/src/app/app-routing.module.ts index 9b8b32c36..4abd93b83 100644 --- a/apps/client/src/app/app-routing.module.ts +++ b/apps/client/src/app/app-routing.module.ts @@ -16,8 +16,8 @@ const routes: Routes = [ { path: internalRoutes.account.path, loadChildren: () => - import('./pages/user-account/user-account-page.module').then( - (m) => m.UserAccountPageModule + import('./pages/user-account/user-account-page.routes').then( + (m) => m.routes ) }, { diff --git a/apps/client/src/app/components/user-account-access/user-account-access.component.ts b/apps/client/src/app/components/user-account-access/user-account-access.component.ts index 11a3f57a4..960ad1310 100644 --- a/apps/client/src/app/components/user-account-access/user-account-access.component.ts +++ b/apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1,4 +1,5 @@ import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto'; +import { GfPortfolioAccessTableModule } from '@ghostfolio/client/components/access-table/access-table.module'; import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { DataService } from '@ghostfolio/client/services/data.service'; @@ -6,17 +7,24 @@ import { TokenStorageService } from '@ghostfolio/client/services/token-storage.s import { UserService } from '@ghostfolio/client/services/user/user.service'; import { Access, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + CUSTOM_ELEMENTS_SCHEMA, OnDestroy, OnInit } from '@angular/core'; -import { FormBuilder, Validators } from '@angular/forms'; -import { MatDialog } from '@angular/material/dialog'; -import { ActivatedRoute, Router } from '@angular/router'; +import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog, MatDialogModule } from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { addOutline, eyeOffOutline, eyeOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; @@ -24,16 +32,30 @@ import { EMPTY, Subject } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; import { CreateOrUpdateAccessDialog } from './create-or-update-access-dialog/create-or-update-access-dialog.component'; +import { GfCreateOrUpdateAccessDialogModule } from './create-or-update-access-dialog/create-or-update-access-dialog.module'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'has-fab' }, + imports: [ + CommonModule, + GfCreateOrUpdateAccessDialogModule, + GfPortfolioAccessTableModule, + GfPremiumIndicatorComponent, + IonIcon, + MatButtonModule, + MatDialogModule, + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-user-account-access', styleUrls: ['./user-account-access.scss'], - templateUrl: './user-account-access.html', - standalone: false + templateUrl: './user-account-access.html' }) -export class UserAccountAccessComponent implements OnDestroy, OnInit { +export class GfUserAccountAccessComponent implements OnDestroy, OnInit { public accessesGet: Access[]; public accessesGive: Access[]; public deviceType: string; diff --git a/apps/client/src/app/components/user-account-access/user-account-access.module.ts b/apps/client/src/app/components/user-account-access/user-account-access.module.ts deleted file mode 100644 index d38a4665e..000000000 --- a/apps/client/src/app/components/user-account-access/user-account-access.module.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { GfPortfolioAccessTableModule } from '@ghostfolio/client/components/access-table/access-table.module'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; - -import { GfCreateOrUpdateAccessDialogModule } from './create-or-update-access-dialog/create-or-update-access-dialog.module'; -import { UserAccountAccessComponent } from './user-account-access.component'; - -@NgModule({ - declarations: [UserAccountAccessComponent], - exports: [UserAccountAccessComponent], - imports: [ - CommonModule, - GfCreateOrUpdateAccessDialogModule, - GfPortfolioAccessTableModule, - GfPremiumIndicatorComponent, - IonIcon, - MatButtonModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfUserAccountAccessModule {} diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts index 68c8b649f..f2f63b32b 100644 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts +++ b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts @@ -6,14 +6,20 @@ import { getDateFormatString } from '@ghostfolio/common/helper'; import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { publicRoutes } from '@ghostfolio/common/routes/routes'; +import { GfMembershipCardComponent } from '@ghostfolio/ui/membership-card'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; import { MatSnackBar } from '@angular/material/snack-bar'; +import { RouterModule } from '@angular/router'; import ms, { StringValue } from 'ms'; import { StripeService } from 'ngx-stripe'; import { EMPTY, Subject } from 'rxjs'; @@ -21,12 +27,19 @@ import { catchError, switchMap, takeUntil } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + GfMembershipCardComponent, + GfPremiumIndicatorComponent, + MatButtonModule, + MatCardModule, + RouterModule + ], selector: 'gf-user-account-membership', styleUrls: ['./user-account-membership.scss'], - templateUrl: './user-account-membership.html', - standalone: false + templateUrl: './user-account-membership.html' }) -export class UserAccountMembershipComponent implements OnDestroy { +export class GfUserAccountMembershipComponent implements OnDestroy { public baseCurrency: string; public coupon: number; public couponId: string; diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts b/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts deleted file mode 100644 index 90646c09e..000000000 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { GfMembershipCardComponent } from '@ghostfolio/ui/membership-card'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; -import { RouterModule } from '@angular/router'; - -import { UserAccountMembershipComponent } from './user-account-membership.component'; - -@NgModule({ - declarations: [UserAccountMembershipComponent], - exports: [UserAccountMembershipComponent], - imports: [ - CommonModule, - GfMembershipCardComponent, - GfPremiumIndicatorComponent, - GfValueComponent, - MatButtonModule, - MatCardModule, - RouterModule - ] -}) -export class GfUserAccountMembershipModule {} diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts index d4683421d..4beebe510 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -13,16 +13,33 @@ import { downloadAsFile } from '@ghostfolio/common/helper'; import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + CUSTOM_ELEMENTS_SCHEMA, OnDestroy, OnInit } from '@angular/core'; -import { FormBuilder, Validators } from '@angular/forms'; -import { MatSlideToggleChange } from '@angular/material/slide-toggle'; +import { + FormBuilder, + FormsModule, + ReactiveFormsModule, + Validators +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectModule } from '@angular/material/select'; +import { + MatSlideToggleChange, + MatSlideToggleModule +} from '@angular/material/slide-toggle'; import { MatSnackBar } from '@angular/material/snack-bar'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { format, parseISO } from 'date-fns'; import { addIcons } from 'ionicons'; import { eyeOffOutline, eyeOutline } from 'ionicons/icons'; @@ -32,12 +49,25 @@ import { catchError, takeUntil } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + FormsModule, + IonIcon, + MatButtonModule, + MatCardModule, + MatFormFieldModule, + MatInputModule, + MatSelectModule, + MatSlideToggleModule, + ReactiveFormsModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-user-account-settings', styleUrls: ['./user-account-settings.scss'], - templateUrl: './user-account-settings.html', - standalone: false + templateUrl: './user-account-settings.html' }) -export class UserAccountSettingsComponent implements OnDestroy, OnInit { +export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { public appearancePlaceholder = $localize`Auto`; public baseCurrency: string; public currencies: string[] = []; diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts deleted file mode 100644 index 3b82dff51..000000000 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatSelectModule } from '@angular/material/select'; -import { MatSlideToggleModule } from '@angular/material/slide-toggle'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; - -import { UserAccountSettingsComponent } from './user-account-settings.component'; - -@NgModule({ - declarations: [UserAccountSettingsComponent], - exports: [UserAccountSettingsComponent], - imports: [ - CommonModule, - FormsModule, - GfValueComponent, - IonIcon, - MatButtonModule, - MatCardModule, - MatFormFieldModule, - MatInputModule, - MatSelectModule, - MatSlideToggleModule, - ReactiveFormsModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfUserAccountSettingsModule {} diff --git a/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts b/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts deleted file mode 100644 index 598381cc2..000000000 --- a/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { UserAccountAccessComponent } from '@ghostfolio/client/components/user-account-access/user-account-access.component'; -import { UserAccountMembershipComponent } from '@ghostfolio/client/components/user-account-membership/user-account-membership.component'; -import { UserAccountSettingsComponent } from '@ghostfolio/client/components/user-account-settings/user-account-settings.component'; -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; -import { internalRoutes } from '@ghostfolio/common/routes/routes'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { UserAccountPageComponent } from './user-account-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - children: [ - { - path: '', - component: UserAccountSettingsComponent, - title: internalRoutes.account.title - }, - { - path: internalRoutes.account.subRoutes.membership.path, - component: UserAccountMembershipComponent, - title: internalRoutes.account.subRoutes.membership.title - }, - { - path: internalRoutes.account.subRoutes.access.path, - component: UserAccountAccessComponent, - title: internalRoutes.account.subRoutes.access.title - } - ], - component: UserAccountPageComponent, - path: '', - title: $localize`My Ghostfolio` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class UserAccountPageRoutingModule {} diff --git a/apps/client/src/app/pages/user-account/user-account-page.component.ts b/apps/client/src/app/pages/user-account/user-account-page.component.ts index 5fc9efeae..4b76dbb9e 100644 --- a/apps/client/src/app/pages/user-account/user-account-page.component.ts +++ b/apps/client/src/app/pages/user-account/user-account-page.component.ts @@ -2,7 +2,17 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { diamondOutline, keyOutline, settingsOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; @@ -10,12 +20,13 @@ import { Subject, takeUntil } from 'rxjs'; @Component({ host: { class: 'page has-tabs' }, + imports: [CommonModule, IonIcon, MatTabsModule, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-user-account-page', styleUrls: ['./user-account-page.scss'], - templateUrl: './user-account-page.html', - standalone: false + templateUrl: './user-account-page.html' }) -export class UserAccountPageComponent implements OnDestroy, OnInit { +export class GfUserAccountPageComponent implements OnDestroy, OnInit { public deviceType: string; public tabs: TabConfiguration[] = []; public user: User; diff --git a/apps/client/src/app/pages/user-account/user-account-page.module.ts b/apps/client/src/app/pages/user-account/user-account-page.module.ts deleted file mode 100644 index 553591bbe..000000000 --- a/apps/client/src/app/pages/user-account/user-account-page.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { GfUserAccountAccessModule } from '@ghostfolio/client/components/user-account-access/user-account-access.module'; -import { GfUserAccountMembershipModule } from '@ghostfolio/client/components/user-account-membership/user-account-membership.module'; -import { GfUserAccountSettingsModule } from '@ghostfolio/client/components/user-account-settings/user-account-settings.module'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatTabsModule } from '@angular/material/tabs'; -import { IonIcon } from '@ionic/angular/standalone'; - -import { UserAccountPageRoutingModule } from './user-account-page-routing.module'; -import { UserAccountPageComponent } from './user-account-page.component'; - -@NgModule({ - declarations: [UserAccountPageComponent], - imports: [ - CommonModule, - GfUserAccountAccessModule, - GfUserAccountMembershipModule, - GfUserAccountSettingsModule, - IonIcon, - MatTabsModule, - UserAccountPageRoutingModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class UserAccountPageModule {} diff --git a/apps/client/src/app/pages/user-account/user-account-page.routes.ts b/apps/client/src/app/pages/user-account/user-account-page.routes.ts new file mode 100644 index 000000000..5d0f5b202 --- /dev/null +++ b/apps/client/src/app/pages/user-account/user-account-page.routes.ts @@ -0,0 +1,35 @@ +import { GfUserAccountAccessComponent } from '@ghostfolio/client/components/user-account-access/user-account-access.component'; +import { GfUserAccountMembershipComponent } from '@ghostfolio/client/components/user-account-membership/user-account-membership.component'; +import { GfUserAccountSettingsComponent } from '@ghostfolio/client/components/user-account-settings/user-account-settings.component'; +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfUserAccountPageComponent } from './user-account-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + children: [ + { + path: '', + component: GfUserAccountSettingsComponent, + title: internalRoutes.account.title + }, + { + path: internalRoutes.account.subRoutes.membership.path, + component: GfUserAccountMembershipComponent, + title: internalRoutes.account.subRoutes.membership.title + }, + { + path: internalRoutes.account.subRoutes.access.path, + component: GfUserAccountAccessComponent, + title: internalRoutes.account.subRoutes.access.title + } + ], + component: GfUserAccountPageComponent, + path: '', + title: $localize`My Ghostfolio` + } +];