Feature/add reusable premium indicator component (#1041)
* Add premium indicator component * Update changelog
This commit is contained in:
parent
f7bf6e652b
commit
069ddcc6b2
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
|
||||
- Added an icon and name column to the positions table
|
||||
- Added a reusable premium indicator component
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -35,11 +35,10 @@
|
||||
>{{ userItem.alias || (userItem.id | slice:0:5) +
|
||||
'...' }}</span
|
||||
>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="userItem?.subscription?.type === 'Premium'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</div>
|
||||
</td>
|
||||
<td class="mat-cell px-1 py-2 text-right">
|
||||
|
@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
|
||||
import { AdminUsersComponent } from './admin-users.component';
|
||||
@ -9,7 +10,13 @@ import { AdminUsersComponent } from './admin-users.component';
|
||||
@NgModule({
|
||||
declarations: [AdminUsersComponent],
|
||||
exports: [],
|
||||
imports: [CommonModule, GfValueModule, MatButtonModule, MatMenuModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GfPremiumIndicatorModule,
|
||||
GfValueModule,
|
||||
MatButtonModule,
|
||||
MatMenuModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class GfAdminUsersModule {}
|
||||
|
@ -19,11 +19,10 @@
|
||||
<a [routerLink]="['/pricing']"
|
||||
>{{ user?.subscription?.type }}</a
|
||||
>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Premium'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</div>
|
||||
<div *ngIf="user?.subscription?.type === 'Premium'">
|
||||
Valid until {{ user?.subscription?.expiresAt | date:
|
||||
@ -56,11 +55,11 @@
|
||||
class="mr-2 my-2"
|
||||
mat-stroked-button
|
||||
[href]="trySubscriptionMail"
|
||||
><span i18n>Try Premium</span
|
||||
><ion-icon
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon
|
||||
><span i18n>Try Premium</span>
|
||||
<gf-premium-indicator
|
||||
class="d-inline-block ml-1"
|
||||
[enableLink]="false"
|
||||
></gf-premium-indicator
|
||||
></a>
|
||||
<a
|
||||
class="mr-2 my-2"
|
||||
|
@ -10,6 +10,7 @@ import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfPortfolioAccessTableModule } from '@ghostfolio/client/components/access-table/access-table.module';
|
||||
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
|
||||
import { AccountPageRoutingModule } from './account-page-routing.module';
|
||||
@ -25,6 +26,7 @@ import { GfCreateOrUpdateAccessDialogModule } from './create-or-update-access-di
|
||||
FormsModule,
|
||||
GfCreateOrUpdateAccessDialogModule,
|
||||
GfPortfolioAccessTableModule,
|
||||
GfPremiumIndicatorModule,
|
||||
GfValueModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
|
@ -108,11 +108,10 @@
|
||||
<div class="flex-grow-1">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>Portfolio Calculations</span>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="hasPermissionForSubscription"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</h4>
|
||||
<p class="m-0">
|
||||
Check the rate of return of your portfolio for
|
||||
@ -127,11 +126,10 @@
|
||||
<div class="flex-grow-1">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>Portfolio Allocations</span>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="hasPermissionForSubscription"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</h4>
|
||||
<p class="m-0">
|
||||
Check the allocations of your portfolio by account, asset class,
|
||||
@ -169,10 +167,7 @@
|
||||
<div class="flex-grow-1">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>Market Mood</span>
|
||||
<ion-icon
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
<gf-premium-indicator class="ml-1"></gf-premium-indicator>
|
||||
</h4>
|
||||
<p class="m-0">
|
||||
Check the current market mood (<a [routerLink]="['/resources']"
|
||||
@ -187,11 +182,10 @@
|
||||
<div class="flex-grow-1">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>Static Analysis</span>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="hasPermissionForSubscription"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</h4>
|
||||
<p class="m-0">
|
||||
Identify potential risks in your portfolio with Ghostfolio
|
||||
|
@ -2,6 +2,7 @@ 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 { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||
|
||||
import { FeaturesPageRoutingModule } from './features-page-routing.module';
|
||||
import { FeaturesPageComponent } from './features-page.component';
|
||||
@ -9,8 +10,9 @@ import { FeaturesPageComponent } from './features-page.component';
|
||||
@NgModule({
|
||||
declarations: [FeaturesPageComponent],
|
||||
imports: [
|
||||
FeaturesPageRoutingModule,
|
||||
CommonModule,
|
||||
FeaturesPageRoutingModule,
|
||||
GfPremiumIndicatorModule,
|
||||
MatButtonModule,
|
||||
MatCardModule
|
||||
],
|
||||
|
@ -37,12 +37,11 @@
|
||||
<mat-card class="mb-3">
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="align-items-center d-flex text-truncate"
|
||||
><span i18n>By Currency</span
|
||||
><ion-icon
|
||||
><span i18n>By Currency</span>
|
||||
<gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon
|
||||
class="ml-1"
|
||||
></gf-premium-indicator
|
||||
></mat-card-title>
|
||||
<gf-toggle
|
||||
[defaultValue]="period"
|
||||
@ -67,11 +66,10 @@
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="align-items-center d-flex text-truncate"
|
||||
><span i18n>By Asset Class</span
|
||||
><ion-icon
|
||||
><gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon
|
||||
class="ml-1"
|
||||
></gf-premium-indicator
|
||||
></mat-card-title>
|
||||
<gf-toggle
|
||||
[defaultValue]="period"
|
||||
@ -96,11 +94,10 @@
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="align-items-center d-flex text-truncate"
|
||||
><span i18n>By Position</span
|
||||
><ion-icon
|
||||
><gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon
|
||||
class="ml-1"
|
||||
></gf-premium-indicator
|
||||
></mat-card-title>
|
||||
<gf-toggle
|
||||
[defaultValue]="period"
|
||||
@ -129,11 +126,10 @@
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="align-items-center d-flex text-truncate"
|
||||
><span i18n>By Sector</span
|
||||
><ion-icon
|
||||
><gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon
|
||||
class="ml-1"
|
||||
></gf-premium-indicator
|
||||
></mat-card-title>
|
||||
<gf-toggle
|
||||
[defaultValue]="period"
|
||||
@ -159,11 +155,10 @@
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="align-items-center d-flex text-truncate"
|
||||
><span i18n>By Continent</span
|
||||
><ion-icon
|
||||
><gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon
|
||||
class="ml-1"
|
||||
></gf-premium-indicator
|
||||
></mat-card-title>
|
||||
<gf-toggle
|
||||
[defaultValue]="period"
|
||||
@ -188,11 +183,10 @@
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="align-items-center d-flex text-truncate"
|
||||
><span i18n>By Country</span
|
||||
><ion-icon
|
||||
><gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon
|
||||
class="ml-1"
|
||||
></gf-premium-indicator
|
||||
></mat-card-title>
|
||||
<gf-toggle
|
||||
[defaultValue]="period"
|
||||
@ -220,11 +214,10 @@
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="align-items-center d-flex text-truncate"
|
||||
><span i18n>Regions</span
|
||||
><ion-icon
|
||||
><gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon
|
||||
class="ml-1"
|
||||
></gf-premium-indicator
|
||||
></mat-card-title>
|
||||
<gf-toggle
|
||||
[defaultValue]="period"
|
||||
|
@ -6,6 +6,7 @@ import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.modu
|
||||
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
|
||||
import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module';
|
||||
import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module';
|
||||
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
|
||||
import { AllocationsPageRoutingModule } from './allocations-page-routing.module';
|
||||
@ -20,6 +21,7 @@ import { AllocationsPageComponent } from './allocations-page.component';
|
||||
GfActivitiesFilterModule,
|
||||
GfPortfolioProportionChartModule,
|
||||
GfPositionsTableModule,
|
||||
GfPremiumIndicatorModule,
|
||||
GfToggleModule,
|
||||
GfWorldMapChartModule,
|
||||
GfValueModule,
|
||||
|
@ -24,11 +24,10 @@
|
||||
<mat-card class="d-flex flex-column h-100">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>Allocations</span>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</h4>
|
||||
<div class="flex-grow-1">
|
||||
Check the allocations of your portfolio by account, asset class,
|
||||
@ -50,11 +49,10 @@
|
||||
<mat-card class="d-flex flex-column h-100">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>Analysis</span>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</h4>
|
||||
<div class="flex-grow-1">
|
||||
Ghostfolio Analysis visualizes your portfolio and shows your top and
|
||||
@ -76,11 +74,10 @@
|
||||
<mat-card class="d-flex flex-column h-100">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>X-ray</span>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</h4>
|
||||
<div class="flex-grow-1">
|
||||
Ghostfolio X-ray uses static analysis to identify potential issues and
|
||||
@ -98,11 +95,10 @@
|
||||
<mat-card class="d-flex flex-column h-100">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>FIRE</span>
|
||||
<ion-icon
|
||||
<gf-premium-indicator
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
class="ml-1"
|
||||
></gf-premium-indicator>
|
||||
</h4>
|
||||
<div class="flex-grow-1">
|
||||
Ghostfolio FIRE calculates metrics for the
|
||||
|
@ -3,6 +3,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||
|
||||
import { PortfolioPageRoutingModule } from './portfolio-page-routing.module';
|
||||
import { PortfolioPageComponent } from './portfolio-page.component';
|
||||
@ -12,6 +13,7 @@ import { PortfolioPageComponent } from './portfolio-page.component';
|
||||
exports: [],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GfPremiumIndicatorModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
PortfolioPageRoutingModule,
|
||||
|
@ -125,10 +125,10 @@
|
||||
<div class="flex-grow-1">
|
||||
<h4 class="align-items-center d-flex">
|
||||
<span i18n>Premium</span>
|
||||
<ion-icon
|
||||
class="ml-1 text-muted"
|
||||
name="diamond-outline"
|
||||
></ion-icon>
|
||||
<gf-premium-indicator
|
||||
class="ml-1"
|
||||
[enableLink]="false"
|
||||
></gf-premium-indicator>
|
||||
</h4>
|
||||
<p>
|
||||
For ambitious investors who need the full picture of their
|
||||
|
@ -3,6 +3,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||
|
||||
import { PricingPageRoutingModule } from './pricing-page-routing.module';
|
||||
import { PricingPageComponent } from './pricing-page.component';
|
||||
@ -12,6 +13,7 @@ import { PricingPageComponent } from './pricing-page.component';
|
||||
exports: [],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GfPremiumIndicatorModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
PricingPageRoutingModule,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { GfLogoModule } from '@ghostfolio/ui/logo';
|
||||
import { Meta, Story, moduleMetadata } from '@storybook/angular';
|
||||
|
||||
@ -8,7 +9,7 @@ export default {
|
||||
component: NoTransactionsInfoComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [GfLogoModule]
|
||||
imports: [GfLogoModule, RouterTestingModule]
|
||||
})
|
||||
]
|
||||
} as Meta<NoTransactionsInfoComponent>;
|
||||
|
1
libs/ui/src/lib/premium-indicator/index.ts
Normal file
1
libs/ui/src/lib/premium-indicator/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './premium-indicator.module';
|
@ -0,0 +1,6 @@
|
||||
<a
|
||||
class="align-items-center d-flex"
|
||||
[ngStyle]="{ 'pointer-events': enableLink ? 'initial' : 'none' }"
|
||||
[routerLink]="['/pricing']"
|
||||
><ion-icon class="text-muted" name="diamond-outline"></ion-icon
|
||||
></a>
|
@ -0,0 +1,3 @@
|
||||
:host {
|
||||
display: block;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { Meta, Story, moduleMetadata } from '@storybook/angular';
|
||||
|
||||
import { PremiumIndicatorComponent } from './premium-indicator.component';
|
||||
|
||||
export default {
|
||||
title: 'Premium Indicator',
|
||||
component: PremiumIndicatorComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [CommonModule, RouterTestingModule]
|
||||
})
|
||||
]
|
||||
} as Meta<PremiumIndicatorComponent>;
|
||||
|
||||
const Template: Story<PremiumIndicatorComponent> = (
|
||||
args: PremiumIndicatorComponent
|
||||
) => ({
|
||||
props: args
|
||||
});
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
||||
|
||||
export const WithoutLink = Template.bind({});
|
||||
WithoutLink.args = {
|
||||
enableLink: false
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'gf-premium-indicator',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: './premium-indicator.component.html',
|
||||
styleUrls: ['./premium-indicator.component.scss']
|
||||
})
|
||||
export class PremiumIndicatorComponent {
|
||||
@Input() enableLink = true;
|
||||
|
||||
public constructor() {}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { PremiumIndicatorComponent } from './premium-indicator.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [PremiumIndicatorComponent],
|
||||
exports: [PremiumIndicatorComponent],
|
||||
imports: [CommonModule, RouterModule],
|
||||
providers: [],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class GfPremiumIndicatorModule {}
|
Loading…
x
Reference in New Issue
Block a user