Browse Source

Task/migrate app component to standalone (#5906)

* Migrate app component to standalone

* Update changelog
pull/5918/head
David Requeno 3 weeks ago
committed by GitHub
parent
commit
45b21cada9
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 18
      apps/client/src/app/app.component.ts
  3. 83
      apps/client/src/app/app.module.ts
  4. 30
      apps/client/src/app/app.routes.ts
  5. 89
      apps/client/src/main.ts

1
CHANGELOG.md

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the _Self-Hosting_ section content for the _Compare with..._ concept on the Frequently Asked Questions (FAQ) page - Improved the _Self-Hosting_ section content for the _Compare with..._ concept on the Frequently Asked Questions (FAQ) page
- Improved the _Self-Hosting_ section content for the _Markets_ concept on the Frequently Asked Questions (FAQ) page - Improved the _Self-Hosting_ section content for the _Markets_ concept on the Frequently Asked Questions (FAQ) page
- Changed the build executor of the client from `@nx/angular:webpack-browser` to `@nx/angular:browser-esbuild` - Changed the build executor of the client from `@nx/angular:webpack-browser` to `@nx/angular:browser-esbuild`
- Refactored the app component to standalone
- Improved the language localization for German (`de`) - Improved the language localization for German (`de`)
### Fixed ### Fixed

18
apps/client/src/app/app.component.ts

@ -1,5 +1,3 @@
import { GfHoldingDetailDialogComponent } from '@ghostfolio/client/components/holding-detail-dialog/holding-detail-dialog.component';
import { HoldingDetailDialogParams } from '@ghostfolio/client/components/holding-detail-dialog/interfaces/interfaces';
import { getCssVariable } from '@ghostfolio/common/helper'; import { getCssVariable } from '@ghostfolio/common/helper';
import { InfoItem, User } from '@ghostfolio/common/interfaces'; import { InfoItem, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
@ -22,7 +20,9 @@ import {
ActivatedRoute, ActivatedRoute,
NavigationEnd, NavigationEnd,
PRIMARY_OUTLET, PRIMARY_OUTLET,
Router Router,
RouterLink,
RouterOutlet
} from '@angular/router'; } from '@angular/router';
import { DataSource } from '@prisma/client'; import { DataSource } from '@prisma/client';
import { addIcons } from 'ionicons'; import { addIcons } from 'ionicons';
@ -31,6 +31,10 @@ import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators'; import { filter, takeUntil } from 'rxjs/operators';
import { GfFooterComponent } from './components/footer/footer.component';
import { GfHeaderComponent } from './components/header/header.component';
import { GfHoldingDetailDialogComponent } from './components/holding-detail-dialog/holding-detail-dialog.component';
import { HoldingDetailDialogParams } from './components/holding-detail-dialog/interfaces/interfaces';
import { NotificationService } from './core/notification/notification.service'; import { NotificationService } from './core/notification/notification.service';
import { DataService } from './services/data.service'; import { DataService } from './services/data.service';
import { ImpersonationStorageService } from './services/impersonation-storage.service'; import { ImpersonationStorageService } from './services/impersonation-storage.service';
@ -38,13 +42,13 @@ import { TokenStorageService } from './services/token-storage.service';
import { UserService } from './services/user/user.service'; import { UserService } from './services/user/user.service';
@Component({ @Component({
selector: 'gf-root',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './app.component.html', imports: [GfFooterComponent, GfHeaderComponent, RouterLink, RouterOutlet],
selector: 'gf-root',
styleUrls: ['./app.component.scss'], styleUrls: ['./app.component.scss'],
standalone: false templateUrl: './app.component.html'
}) })
export class AppComponent implements OnDestroy, OnInit { export class GfAppComponent implements OnDestroy, OnInit {
@HostBinding('class.has-info-message') get getHasMessage() { @HostBinding('class.has-info-message') get getHasMessage() {
return this.hasInfoMessage; return this.hasInfoMessage;
} }

83
apps/client/src/app/app.module.ts

@ -1,83 +0,0 @@
import { Platform } from '@angular/cdk/platform';
import {
provideHttpClient,
withInterceptorsFromDi
} from '@angular/common/http';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatChipsModule } from '@angular/material/chips';
import {
DateAdapter,
MAT_DATE_FORMATS,
MAT_DATE_LOCALE,
MatNativeDateModule
} from '@angular/material/core';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ServiceWorkerModule } from '@angular/service-worker';
import { provideIonicAngular } from '@ionic/angular/standalone';
import { provideMarkdown } from 'ngx-markdown';
import { provideNgxSkeletonLoader } from 'ngx-skeleton-loader';
import { NgxStripeModule, STRIPE_PUBLISHABLE_KEY } from 'ngx-stripe';
import { environment } from '../environments/environment';
import { CustomDateAdapter } from './adapter/custom-date-adapter';
import { DateFormats } from './adapter/date-formats';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { GfFooterComponent } from './components/footer/footer.component';
import { GfHeaderComponent } from './components/header/header.component';
import { authInterceptorProviders } from './core/auth.interceptor';
import { httpResponseInterceptorProviders } from './core/http-response.interceptor';
import { LanguageService } from './core/language.service';
import { GfNotificationModule } from './core/notification/notification.module';
export function NgxStripeFactory(): string {
return environment.stripePublicKey;
}
@NgModule({
bootstrap: [AppComponent],
declarations: [AppComponent],
imports: [
AppRoutingModule,
BrowserAnimationsModule,
BrowserModule,
GfFooterComponent,
GfHeaderComponent,
GfNotificationModule,
MatAutocompleteModule,
MatChipsModule,
MatNativeDateModule,
MatSnackBarModule,
MatTooltipModule,
NgxStripeModule.forRoot(environment.stripePublicKey),
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
registrationStrategy: 'registerImmediately'
})
],
providers: [
authInterceptorProviders,
httpResponseInterceptorProviders,
LanguageService,
provideHttpClient(withInterceptorsFromDi()),
provideIonicAngular(),
provideMarkdown(),
provideNgxSkeletonLoader(),
{
provide: DateAdapter,
useClass: CustomDateAdapter,
deps: [LanguageService, MAT_DATE_LOCALE, Platform]
},
{ provide: MAT_DATE_FORMATS, useValue: DateFormats },
{
provide: STRIPE_PUBLISHABLE_KEY,
useFactory: NgxStripeFactory
}
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {}

30
apps/client/src/app/app-routing.module.ts → apps/client/src/app/app.routes.ts

@ -1,13 +1,10 @@
import { publicRoutes, internalRoutes } from '@ghostfolio/common/routes/routes'; import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core'; import { Routes } from '@angular/router';
import { RouterModule, Routes, TitleStrategy } from '@angular/router';
import { AuthGuard } from './core/auth.guard'; import { AuthGuard } from './core/auth.guard';
import { ModulePreloadService } from './core/module-preload.service';
import { PageTitleStrategy } from './services/page-title.strategy';
const routes: Routes = [ export const routes: Routes = [
{ {
path: publicRoutes.about.path, path: publicRoutes.about.path,
loadChildren: () => loadChildren: () =>
@ -147,24 +144,3 @@ const routes: Routes = [
pathMatch: 'full' pathMatch: 'full'
} }
]; ];
@NgModule({
imports: [
RouterModule.forRoot(
routes,
// Preload all lazy loaded modules with the attribute preload === true
{
anchorScrolling: 'enabled',
// enableTracing: true, // <-- debugging purposes only
preloadingStrategy: ModulePreloadService,
scrollPositionRestoration: 'top'
}
)
],
providers: [
ModulePreloadService,
{ provide: TitleStrategy, useClass: PageTitleStrategy }
],
exports: [RouterModule]
})
export class AppRoutingModule {}

89
apps/client/src/main.ts

@ -2,11 +2,39 @@ import { locale } from '@ghostfolio/common/config';
import { InfoResponse } from '@ghostfolio/common/interfaces'; import { InfoResponse } from '@ghostfolio/common/interfaces';
import { filterGlobalPermissions } from '@ghostfolio/common/permissions'; import { filterGlobalPermissions } from '@ghostfolio/common/permissions';
import { enableProdMode } from '@angular/core'; import { Platform } from '@angular/cdk/platform';
import { LOCALE_ID } from '@angular/core'; import {
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; provideHttpClient,
withInterceptorsFromDi
} from '@angular/common/http';
import { enableProdMode, importProvidersFrom, LOCALE_ID } from '@angular/core';
import {
DateAdapter,
MAT_DATE_FORMATS,
MAT_DATE_LOCALE,
MatNativeDateModule
} from '@angular/material/core';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { bootstrapApplication } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
import { RouterModule, TitleStrategy } from '@angular/router';
import { ServiceWorkerModule } from '@angular/service-worker';
import { provideIonicAngular } from '@ionic/angular/standalone';
import { provideMarkdown } from 'ngx-markdown';
import { provideNgxSkeletonLoader } from 'ngx-skeleton-loader';
import { NgxStripeModule, STRIPE_PUBLISHABLE_KEY } from 'ngx-stripe';
import { AppModule } from './app/app.module'; import { CustomDateAdapter } from './app/adapter/custom-date-adapter';
import { DateFormats } from './app/adapter/date-formats';
import { GfAppComponent } from './app/app.component';
import { routes } from './app/app.routes';
import { authInterceptorProviders } from './app/core/auth.interceptor';
import { httpResponseInterceptorProviders } from './app/core/http-response.interceptor';
import { LanguageService } from './app/core/language.service';
import { ModulePreloadService } from './app/core/module-preload.service';
import { GfNotificationModule } from './app/core/notification/notification.module';
import { PageTitleStrategy } from './app/services/page-title.strategy';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
(async () => { (async () => {
@ -29,9 +57,54 @@ import { environment } from './environments/environment';
enableProdMode(); enableProdMode();
} }
platformBrowserDynamic() await bootstrapApplication(GfAppComponent, {
.bootstrapModule(AppModule, { providers: [
providers: [{ provide: LOCALE_ID, useValue: locale }] authInterceptorProviders,
httpResponseInterceptorProviders,
importProvidersFrom(
GfNotificationModule,
MatNativeDateModule,
MatSnackBarModule,
MatTooltipModule,
NgxStripeModule.forRoot(environment.stripePublicKey),
RouterModule.forRoot(routes, {
anchorScrolling: 'enabled',
preloadingStrategy: ModulePreloadService,
scrollPositionRestoration: 'top'
}),
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
registrationStrategy: 'registerImmediately'
}) })
.catch((error) => console.error(error)); ),
LanguageService,
ModulePreloadService,
provideAnimations(),
provideHttpClient(withInterceptorsFromDi()),
provideIonicAngular(),
provideMarkdown(),
provideNgxSkeletonLoader(),
{
deps: [LanguageService, MAT_DATE_LOCALE, Platform],
provide: DateAdapter,
useClass: CustomDateAdapter
},
{
provide: LOCALE_ID,
useValue: locale
},
{
provide: MAT_DATE_FORMATS,
useValue: DateFormats
},
{
provide: STRIPE_PUBLISHABLE_KEY,
useFactory: () => environment.stripePublicKey
},
{
provide: TitleStrategy,
useClass: PageTitleStrategy
}
]
});
})(); })();

Loading…
Cancel
Save