Compare commits

...

2 Commits

Author SHA1 Message Date
Thomas Kaul b2867b1955
Feature/randomize minutes of hourly data gathering cron job (#5403) 4 days ago
Thomas Kaul 34e09626cc
Task/refactor pricing page to standalone (#5402) 4 days ago
  1. 2
      CHANGELOG.md
  2. 5
      apps/api/src/services/cron/cron.service.ts
  3. 4
      apps/client/src/app/app-routing.module.ts
  4. 21
      apps/client/src/app/pages/pricing/pricing-page-routing.module.ts
  5. 42
      apps/client/src/app/pages/pricing/pricing-page.component.ts
  6. 28
      apps/client/src/app/pages/pricing/pricing-page.module.ts
  7. 14
      apps/client/src/app/pages/pricing/pricing-page.routes.ts

2
CHANGELOG.md

@ -9,9 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Randomized the minutes of the hourly data gathering cron job
- Refactored the dialog footer component to standalone - Refactored the dialog footer component to standalone
- Refactored the dialog header component to standalone - Refactored the dialog header component to standalone
- Refactored the landing page to standalone - Refactored the landing page to standalone
- Refactored the pricing page to standalone
- Refactored the register page to standalone - Refactored the register page to standalone
- Migrated the login with access token dialog from `ngModel` to form control - Migrated the login with access token dialog from `ngModel` to form control
- Upgraded `@ionic/angular` from version `8.6.3` to `8.7.3` - Upgraded `@ionic/angular` from version `8.6.3` to `8.7.3`

5
apps/api/src/services/cron/cron.service.ts

@ -17,6 +17,7 @@ import { Cron, CronExpression } from '@nestjs/schedule';
@Injectable() @Injectable()
export class CronService { export class CronService {
private static readonly EVERY_HOUR_AT_RANDOM_MINUTE = `${new Date().getMinutes()} * * * *`;
private static readonly EVERY_SUNDAY_AT_LUNCH_TIME = '0 12 * * 0'; private static readonly EVERY_SUNDAY_AT_LUNCH_TIME = '0 12 * * 0';
public constructor( public constructor(
@ -28,8 +29,8 @@ export class CronService {
private readonly userService: UserService private readonly userService: UserService
) {} ) {}
@Cron(CronExpression.EVERY_HOUR) @Cron(CronService.EVERY_HOUR_AT_RANDOM_MINUTE)
public async runEveryHour() { public async runEveryHourAtRandomMinute() {
if (await this.isDataGatheringEnabled()) { if (await this.isDataGatheringEnabled()) {
await this.dataGatheringService.gather7Days(); await this.dataGatheringService.gather7Days();
} }

4
apps/client/src/app/app-routing.module.ts

@ -106,9 +106,7 @@ const routes: Routes = [
{ {
path: publicRoutes.pricing.path, path: publicRoutes.pricing.path,
loadChildren: () => loadChildren: () =>
import('./pages/pricing/pricing-page.module').then( import('./pages/pricing/pricing-page.routes').then((m) => m.routes)
(m) => m.PricingPageModule
)
}, },
{ {
path: publicRoutes.public.path, path: publicRoutes.public.path,

21
apps/client/src/app/pages/pricing/pricing-page-routing.module.ts

@ -1,21 +0,0 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PricingPageComponent } from './pricing-page.component';
const routes: Routes = [
{
canActivate: [AuthGuard],
component: PricingPageComponent,
path: '',
title: $localize`Pricing`
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PricingPageRoutingModule {}

42
apps/client/src/app/pages/pricing/pricing-page.component.ts

@ -5,10 +5,27 @@ import { User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { translate } from '@ghostfolio/ui/i18n'; import { translate } from '@ghostfolio/ui/i18n';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
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 { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons'; import { addIcons } from 'ionicons';
import { checkmarkCircleOutline, checkmarkOutline } from 'ionicons/icons'; import {
checkmarkCircleOutline,
checkmarkOutline,
informationCircleOutline
} from 'ionicons/icons';
import { StringValue } from 'ms'; import { StringValue } from 'ms';
import { StripeService } from 'ngx-stripe'; import { StripeService } from 'ngx-stripe';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@ -16,12 +33,21 @@ import { catchError, switchMap, takeUntil } from 'rxjs/operators';
@Component({ @Component({
host: { class: 'page' }, host: { class: 'page' },
imports: [
CommonModule,
GfPremiumIndicatorComponent,
IonIcon,
MatButtonModule,
MatCardModule,
MatTooltipModule,
RouterModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-pricing-page', selector: 'gf-pricing-page',
styleUrls: ['./pricing-page.scss'], styleUrls: ['./pricing-page.scss'],
templateUrl: './pricing-page.html', templateUrl: './pricing-page.html'
standalone: false
}) })
export class PricingPageComponent implements OnDestroy, OnInit { export class GfPricingPageComponent implements OnDestroy, OnInit {
public baseCurrency: string; public baseCurrency: string;
public coupon: number; public coupon: number;
public couponId: string; public couponId: string;
@ -56,7 +82,11 @@ export class PricingPageComponent implements OnDestroy, OnInit {
private stripeService: StripeService, private stripeService: StripeService,
private userService: UserService private userService: UserService
) { ) {
addIcons({ checkmarkCircleOutline, checkmarkOutline }); addIcons({
checkmarkCircleOutline,
checkmarkOutline,
informationCircleOutline
});
} }
public ngOnInit() { public ngOnInit() {

28
apps/client/src/app/pages/pricing/pricing-page.module.ts

@ -1,28 +0,0 @@
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone';
import { PricingPageRoutingModule } from './pricing-page-routing.module';
import { PricingPageComponent } from './pricing-page.component';
@NgModule({
declarations: [PricingPageComponent],
imports: [
CommonModule,
GfPremiumIndicatorComponent,
IonIcon,
MatButtonModule,
MatCardModule,
MatTooltipModule,
PricingPageRoutingModule,
RouterModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class PricingPageModule {}

14
apps/client/src/app/pages/pricing/pricing-page.routes.ts

@ -0,0 +1,14 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { Routes } from '@angular/router';
import { GfPricingPageComponent } from './pricing-page.component';
export const routes: Routes = [
{
canActivate: [AuthGuard],
component: GfPricingPageComponent,
path: '',
title: $localize`Pricing`
}
];
Loading…
Cancel
Save