Feature/optimize dialog sizes for mobile (#3964)

* Optimize dialog sizes for mobile

* Update changelog
pull/3857/merge
Thomas Kaul 2 days ago committed by GitHub
parent 4c658a1f6a
commit a5331dd32b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
### Changed
- Optimized the dialog sizes for mobile (full screen)
### Fixed ### Fixed
- Fixed the warning `export was not found` in connection with `GetValuesParams` - Fixed the warning `export was not found` in connection with `GetValuesParams`

@ -313,8 +313,7 @@ export class AppComponent implements OnDestroy, OnInit {
!this.user?.settings?.isRestrictedView, !this.user?.settings?.isRestrictedView,
locale: this.user?.settings?.locale locale: this.user?.settings?.locale
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
maxWidth: this.deviceType === 'mobile' ? '95vw' : '50rem',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -186,7 +186,7 @@ export class AdminMarketDataDetailComponent implements OnChanges {
symbol: this.symbol, symbol: this.symbol,
user: this.user user: this.user
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -382,7 +382,7 @@ export class AdminMarketDataComponent
deviceType: this.deviceType, deviceType: this.deviceType,
locale: this.user?.settings?.locale locale: this.user?.settings?.locale
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -139,7 +139,7 @@ export class AdminPlatformComponent implements OnInit, OnDestroy {
url: null url: null
} }
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : undefined, height: this.deviceType === 'mobile' ? '98vh' : undefined,
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });
@ -176,7 +176,7 @@ export class AdminPlatformComponent implements OnInit, OnDestroy {
url url
} }
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : undefined, height: this.deviceType === 'mobile' ? '98vh' : undefined,
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -59,7 +59,7 @@ export class AdminSettingsComponent implements OnDestroy, OnInit {
deviceType: this.deviceType, deviceType: this.deviceType,
pricingUrl: this.pricingUrl pricingUrl: this.pricingUrl
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : undefined, height: this.deviceType === 'mobile' ? '98vh' : undefined,
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });
} }

@ -138,7 +138,7 @@ export class AdminTagComponent implements OnInit, OnDestroy {
name: null name: null
} }
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : undefined, height: this.deviceType === 'mobile' ? '98vh' : undefined,
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });
@ -174,7 +174,7 @@ export class AdminTagComponent implements OnInit, OnDestroy {
name name
} }
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : undefined, height: this.deviceType === 'mobile' ? '98vh' : undefined,
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -1 +1,5 @@
export interface SubscriptionInterstitialDialogParams {} import { User } from '@ghostfolio/common/interfaces';
export interface SubscriptionInterstitialDialogParams {
user: User;
}

@ -11,12 +11,17 @@ import { SubscriptionInterstitialDialogParams } from './interfaces/interfaces';
templateUrl: 'subscription-interstitial-dialog.html' templateUrl: 'subscription-interstitial-dialog.html'
}) })
export class SubscriptionInterstitialDialog { export class SubscriptionInterstitialDialog {
private readonly VARIANTS_COUNT = 2;
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`]; public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public variantIndex: number;
public constructor( public constructor(
@Inject(MAT_DIALOG_DATA) public data: SubscriptionInterstitialDialogParams, @Inject(MAT_DIALOG_DATA) public data: SubscriptionInterstitialDialogParams,
public dialogRef: MatDialogRef<SubscriptionInterstitialDialog> public dialogRef: MatDialogRef<SubscriptionInterstitialDialog>
) {} ) {
this.variantIndex = Math.floor(Math.random() * this.VARIANTS_COUNT);
}
public closeDialog() { public closeDialog() {
this.dialogRef.close({}); this.dialogRef.close({});

@ -1,62 +1,98 @@
<div class="flex-grow-1 pt-0" mat-dialog-content> @switch (variantIndex) {
<div class="intro-container"> @case (0) {
<div class="intro-inner-container mx-auto"> <div class="flex-grow-1 pt-0" mat-dialog-content>
<div class="h-100 intro w-100"></div> <div class="intro-container">
<div class="intro-inner-container mx-auto">
<div class="h-100 intro w-100"></div>
</div>
</div>
<div>
<h5 class="align-items-center d-flex justify-content-center mb-3">
<span>Ghostfolio Premium</span>
<gf-premium-indicator class="ml-1" [enableLink]="false" />
</h5>
<div class="font-weight-normal h5 mb-3 text-center" i18n>
Are you an ambitious investor who needs the full picture?
</div>
<p i18n>
Upgrade to Ghostfolio Premium today and gain access to exclusive
features to enhance your investment experience:
</p>
<ul class="list-unstyled mb-3 pl-3">
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>Portfolio Summary</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>Portfolio Allocations</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>Performance Benchmarks</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>FIRE Calculator</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>Professional Data Provider</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>and more Features...</span>
</li>
</ul>
<p class="m-0" i18n>
Get the tools to effectively manage your finances and refine your
personal investment strategy.
</p>
</div>
</div> </div>
</div> <div class="justify-content-end" mat-dialog-actions>
<div> <button i18n mat-button (click)="closeDialog()">Skip</button>
<h5 class="align-items-center d-flex justify-content-center mb-3"> <a
color="primary"
mat-flat-button
[routerLink]="routerLinkPricing"
(click)="closeDialog()"
>
<span i18n>Upgrade Plan</span>
<ion-icon class="ml-1" name="arrow-forward-outline" />
</a>
</div>
}
@case (1) {
<h1
class="align-items-center d-flex justify-content-center"
mat-dialog-title
>
<span>Ghostfolio Premium</span> <span>Ghostfolio Premium</span>
<gf-premium-indicator class="ml-1" [enableLink]="false" /> <gf-premium-indicator class="ml-1" [enableLink]="false" />
</h5> </h1>
<div class="font-weight-normal h5 mb-3 text-center" i18n> <div class="flex-grow-1 pt-0" mat-dialog-content>
Are you an ambitious investor who needs the full picture? <div class="align-items-center d-flex h-100 justify-content-center">
<gf-membership-card
class="gf-pointer-events-none"
[name]="data?.user?.subscription?.type"
/>
</div>
</div>
<div class="flex-column" mat-dialog-actions>
<button class="mb-2 py-4 w-100" i18n mat-button (click)="closeDialog()">
Skip
</button>
<a
class="m-0 py-4 w-100"
color="primary"
mat-flat-button
[routerLink]="routerLinkPricing"
(click)="closeDialog()"
>
<span i18n>Join now</span>
<ion-icon class="ml-1" name="arrow-forward-outline" />
</a>
</div> </div>
<p i18n> }
Upgrade to Ghostfolio Premium today and gain access to exclusive features }
to enhance your investment experience:
</p>
<ul class="list-unstyled mb-3 pl-3">
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>Portfolio Summary</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>Portfolio Allocations</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>Performance Benchmarks</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>FIRE Calculator</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>Professional Data Provider</span>
</li>
<li class="align-items-center d-flex mb-1">
<ion-icon class="mr-1" name="checkmark-circle-outline" />
<span i18n>and more Features...</span>
</li>
</ul>
<p class="m-0" i18n>
Get the tools to effectively manage your finances and refine your personal
investment strategy.
</p>
</div>
</div>
<div class="justify-content-end" mat-dialog-actions>
<button i18n mat-button (click)="closeDialog()">Skip</button>
<a
color="primary"
mat-flat-button
[routerLink]="routerLinkPricing"
(click)="closeDialog()"
>
<span i18n>Upgrade Plan</span>
<ion-icon class="ml-1" name="arrow-forward-outline" />
</a>
</div>

@ -1,3 +1,4 @@
import { GfMembershipCardComponent } from '@ghostfolio/ui/membership-card';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@ -12,6 +13,7 @@ import { SubscriptionInterstitialDialog } from './subscription-interstitial-dial
declarations: [SubscriptionInterstitialDialog], declarations: [SubscriptionInterstitialDialog],
imports: [ imports: [
CommonModule, CommonModule,
GfMembershipCardComponent,
GfPremiumIndicatorComponent, GfPremiumIndicatorComponent,
MatButtonModule, MatButtonModule,
MatDialogModule, MatDialogModule,

@ -111,7 +111,7 @@ export class UserAccountAccessComponent implements OnDestroy, OnInit {
type: 'PRIVATE' type: 'PRIVATE'
} }
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : undefined, height: this.deviceType === 'mobile' ? '98vh' : undefined,
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -184,7 +184,7 @@ export class AccountsPageComponent implements OnDestroy, OnInit {
platformId platformId
} }
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });
@ -231,7 +231,7 @@ export class AccountsPageComponent implements OnDestroy, OnInit {
hasPermission(this.user?.permissions, permissions.createOrder) && hasPermission(this.user?.permissions, permissions.createOrder) &&
!this.user?.settings?.isRestrictedView !this.user?.settings?.isRestrictedView
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });
@ -257,7 +257,7 @@ export class AccountsPageComponent implements OnDestroy, OnInit {
platformId: null platformId: null
} }
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -272,7 +272,7 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit {
accounts: this.user?.accounts, accounts: this.user?.accounts,
user: this.user user: this.user
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });
@ -321,7 +321,7 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit {
}, },
user: this.user user: this.user
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -514,7 +514,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
hasPermission(this.user?.permissions, permissions.createOrder) && hasPermission(this.user?.permissions, permissions.createOrder) &&
!this.user?.settings?.isRestrictedView !this.user?.settings?.isRestrictedView
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -104,8 +104,10 @@ export class UserService extends ObservableStore<UserStoreState> {
) { ) {
const dialogRef = this.dialog.open(SubscriptionInterstitialDialog, { const dialogRef = this.dialog.open(SubscriptionInterstitialDialog, {
autoFocus: false, autoFocus: false,
data: <SubscriptionInterstitialDialogParams>{}, data: <SubscriptionInterstitialDialogParams>{
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', user
},
height: this.deviceType === 'mobile' ? '98vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

@ -369,6 +369,10 @@ ngx-skeleton-loader {
cursor: pointer; cursor: pointer;
} }
.gf-pointer-events-none {
pointer-events: none;
}
.gf-spacer { .gf-spacer {
flex: 1 1 auto; flex: 1 1 auto;
} }

@ -114,6 +114,7 @@ $gf-theme-dark: mat.m2-define-dark-theme(
--gf-theme-secondary-500: #3686cf; --gf-theme-secondary-500: #3686cf;
--gf-theme-secondary-500-rgb: 78, 208, 94; --gf-theme-secondary-500-rgb: 78, 208, 94;
--mat-dialog-container-small-max-width: 96vw;
--mdc-filled-button-label-text-tracking: normal; --mdc-filled-button-label-text-tracking: normal;
--mdc-outlined-button-label-text-tracking: normal; --mdc-outlined-button-label-text-tracking: normal;
--mdc-text-button-label-text-tracking: normal; --mdc-text-button-label-text-tracking: normal;

@ -116,7 +116,7 @@ export class GfBenchmarkComponent implements OnChanges, OnDestroy {
deviceType: this.deviceType, deviceType: this.deviceType,
locale: this.locale locale: this.locale
}, },
height: this.deviceType === 'mobile' ? '97.5vh' : undefined, height: this.deviceType === 'mobile' ? '98vh' : undefined,
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType === 'mobile' ? '100vw' : '50rem'
}); });

Loading…
Cancel
Save