Feature/add system message (#519)
* Add system message * Update changelog
This commit is contained in:
parent
aed8f5cf04
commit
4d9a223491
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Supported the management of additional currencies in the admin control panel
|
- Supported the management of additional currencies in the admin control panel
|
||||||
|
- Introduced the system message
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
AdminMarketDataDetails
|
AdminMarketDataDetails
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Property } from '@prisma/client';
|
||||||
import { differenceInDays } from 'date-fns';
|
import { differenceInDays } from 'date-fns';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -80,7 +81,13 @@ export class AdminService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async putSetting(key: string, value: string) {
|
public async putSetting(key: string, value: string) {
|
||||||
const response = await this.propertyService.put({ key, value });
|
let response: Property;
|
||||||
|
|
||||||
|
if (value === '') {
|
||||||
|
response = await this.propertyService.delete({ key });
|
||||||
|
} else {
|
||||||
|
response = await this.propertyService.put({ key, value });
|
||||||
|
}
|
||||||
|
|
||||||
if (key === PROPERTY_CURRENCIES) {
|
if (key === PROPERTY_CURRENCIES) {
|
||||||
await this.exchangeRateDataService.initialize();
|
await this.exchangeRateDataService.initialize();
|
||||||
|
@ -5,6 +5,7 @@ import { DataGatheringService } from '@ghostfolio/api/services/data-gathering.se
|
|||||||
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
||||||
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
|
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
|
||||||
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
||||||
|
import { PropertyModule } from '@ghostfolio/api/services/property/property.module';
|
||||||
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile.module';
|
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile.module';
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
@ -21,6 +22,7 @@ import { InfoService } from './info.service';
|
|||||||
secret: process.env.JWT_SECRET_KEY,
|
secret: process.env.JWT_SECRET_KEY,
|
||||||
signOptions: { expiresIn: '30 days' }
|
signOptions: { expiresIn: '30 days' }
|
||||||
}),
|
}),
|
||||||
|
PropertyModule,
|
||||||
RedisCacheModule,
|
RedisCacheModule,
|
||||||
SymbolProfileModule
|
SymbolProfileModule
|
||||||
],
|
],
|
||||||
|
@ -4,7 +4,11 @@ import { DataGatheringService } from '@ghostfolio/api/services/data-gathering.se
|
|||||||
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
|
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
|
||||||
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
|
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
|
||||||
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
||||||
import { PROPERTY_STRIPE_CONFIG } from '@ghostfolio/common/config';
|
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
|
||||||
|
import {
|
||||||
|
PROPERTY_STRIPE_CONFIG,
|
||||||
|
PROPERTY_SYSTEM_MESSAGE
|
||||||
|
} from '@ghostfolio/common/config';
|
||||||
import { InfoItem } from '@ghostfolio/common/interfaces';
|
import { InfoItem } from '@ghostfolio/common/interfaces';
|
||||||
import { Statistics } from '@ghostfolio/common/interfaces/statistics.interface';
|
import { Statistics } from '@ghostfolio/common/interfaces/statistics.interface';
|
||||||
import { Subscription } from '@ghostfolio/common/interfaces/subscription.interface';
|
import { Subscription } from '@ghostfolio/common/interfaces/subscription.interface';
|
||||||
@ -16,8 +20,8 @@ import { subDays } from 'date-fns';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InfoService {
|
export class InfoService {
|
||||||
private static DEMO_USER_ID = '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f';
|
|
||||||
private static CACHE_KEY_STATISTICS = 'STATISTICS';
|
private static CACHE_KEY_STATISTICS = 'STATISTICS';
|
||||||
|
private static DEMO_USER_ID = '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f';
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly configurationService: ConfigurationService,
|
private readonly configurationService: ConfigurationService,
|
||||||
@ -26,6 +30,7 @@ export class InfoService {
|
|||||||
private readonly dataGatheringService: DataGatheringService,
|
private readonly dataGatheringService: DataGatheringService,
|
||||||
private readonly jwtService: JwtService,
|
private readonly jwtService: JwtService,
|
||||||
private readonly prismaService: PrismaService,
|
private readonly prismaService: PrismaService,
|
||||||
|
private readonly propertyService: PropertyService,
|
||||||
private readonly redisCacheService: RedisCacheService
|
private readonly redisCacheService: RedisCacheService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -35,6 +40,7 @@ export class InfoService {
|
|||||||
orderBy: { name: 'asc' },
|
orderBy: { name: 'asc' },
|
||||||
select: { id: true, name: true }
|
select: { id: true, name: true }
|
||||||
});
|
});
|
||||||
|
let systemMessage: string;
|
||||||
|
|
||||||
const globalPermissions: string[] = [];
|
const globalPermissions: string[] = [];
|
||||||
|
|
||||||
@ -60,10 +66,19 @@ export class InfoService {
|
|||||||
info.stripePublicKey = this.configurationService.get('STRIPE_PUBLIC_KEY');
|
info.stripePublicKey = this.configurationService.get('STRIPE_PUBLIC_KEY');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.configurationService.get('ENABLE_FEATURE_SYSTEM_MESSAGE')) {
|
||||||
|
globalPermissions.push(permissions.enableSystemMessage);
|
||||||
|
|
||||||
|
systemMessage = (await this.propertyService.getByKey(
|
||||||
|
PROPERTY_SYSTEM_MESSAGE
|
||||||
|
)) as string;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...info,
|
...info,
|
||||||
globalPermissions,
|
globalPermissions,
|
||||||
platforms,
|
platforms,
|
||||||
|
systemMessage,
|
||||||
currencies: this.exchangeRateDataService.getCurrencies(),
|
currencies: this.exchangeRateDataService.getCurrencies(),
|
||||||
demoAuthToken: this.getDemoAuthToken(),
|
demoAuthToken: this.getDemoAuthToken(),
|
||||||
lastDataGathering: await this.getLastDataGathering(),
|
lastDataGathering: await this.getLastDataGathering(),
|
||||||
|
@ -21,6 +21,7 @@ export class ConfigurationService {
|
|||||||
ENABLE_FEATURE_SOCIAL_LOGIN: bool({ default: false }),
|
ENABLE_FEATURE_SOCIAL_LOGIN: bool({ default: false }),
|
||||||
ENABLE_FEATURE_STATISTICS: bool({ default: false }),
|
ENABLE_FEATURE_STATISTICS: bool({ default: false }),
|
||||||
ENABLE_FEATURE_SUBSCRIPTION: bool({ default: false }),
|
ENABLE_FEATURE_SUBSCRIPTION: bool({ default: false }),
|
||||||
|
ENABLE_FEATURE_SYSTEM_MESSAGE: bool({ default: false }),
|
||||||
GOOGLE_CLIENT_ID: str({ default: 'dummyClientId' }),
|
GOOGLE_CLIENT_ID: str({ default: 'dummyClientId' }),
|
||||||
GOOGLE_SECRET: str({ default: 'dummySecret' }),
|
GOOGLE_SECRET: str({ default: 'dummySecret' }),
|
||||||
JWT_SECRET_KEY: str({}),
|
JWT_SECRET_KEY: str({}),
|
||||||
|
@ -12,6 +12,7 @@ export interface Environment extends CleanedEnvAccessors {
|
|||||||
ENABLE_FEATURE_SOCIAL_LOGIN: boolean;
|
ENABLE_FEATURE_SOCIAL_LOGIN: boolean;
|
||||||
ENABLE_FEATURE_STATISTICS: boolean;
|
ENABLE_FEATURE_STATISTICS: boolean;
|
||||||
ENABLE_FEATURE_SUBSCRIPTION: boolean;
|
ENABLE_FEATURE_SUBSCRIPTION: boolean;
|
||||||
|
ENABLE_FEATURE_SYSTEM_MESSAGE: boolean;
|
||||||
GOOGLE_CLIENT_ID: string;
|
GOOGLE_CLIENT_ID: string;
|
||||||
GOOGLE_SECRET: string;
|
GOOGLE_SECRET: string;
|
||||||
JWT_SECRET_KEY: string;
|
JWT_SECRET_KEY: string;
|
||||||
|
@ -6,6 +6,12 @@ import { Injectable } from '@nestjs/common';
|
|||||||
export class PropertyService {
|
export class PropertyService {
|
||||||
public constructor(private readonly prismaService: PrismaService) {}
|
public constructor(private readonly prismaService: PrismaService) {}
|
||||||
|
|
||||||
|
public async delete({ key }: { key: string }) {
|
||||||
|
return this.prismaService.property.delete({
|
||||||
|
where: { key }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async get() {
|
public async get() {
|
||||||
const response: {
|
const response: {
|
||||||
[key: string]: object | string | string[];
|
[key: string]: object | string | string[];
|
||||||
|
@ -9,18 +9,27 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main role="main">
|
<main role="main">
|
||||||
<div *ngIf="canCreateAccount" class="container create-account-container">
|
<div
|
||||||
|
*ngIf="canCreateAccount || (info?.systemMessage && user)"
|
||||||
|
class="container info-message-container"
|
||||||
|
>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8 offset-md-2 text-center">
|
<div class="col-md-8 offset-md-2 text-center">
|
||||||
<a class="text-center" [routerLink]="['/']">
|
<a *ngIf="canCreateAccount" class="text-center" [routerLink]="['/']">
|
||||||
<div
|
<div
|
||||||
class="create-account-box d-inline-block px-3 py-2"
|
class="cursor-pointer d-inline-block info-message px-3 py-2"
|
||||||
(click)="onCreateAccount()"
|
(click)="onCreateAccount()"
|
||||||
>
|
>
|
||||||
<span i18n>You are using the Live Demo.</span>
|
<span i18n>You are using the Live Demo.</span>
|
||||||
<a class="ml-2" href="#" i18n>Create Account</a>
|
<a class="ml-2" href="#" i18n>Create Account</a>
|
||||||
</div></a
|
</div></a
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
*ngIf="!canCreateAccount && info?.systemMessage && user"
|
||||||
|
class="d-inline-block info-message px-3 py-2"
|
||||||
|
>
|
||||||
|
{{ info.systemMessage }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
padding-top: 5rem;
|
padding-top: 5rem;
|
||||||
|
|
||||||
.create-account-container {
|
.info-message-container {
|
||||||
height: 3.5rem;
|
height: 3.5rem;
|
||||||
margin-top: -0.5rem;
|
margin-top: -0.5rem;
|
||||||
|
|
||||||
.create-account-box {
|
.info-message {
|
||||||
background-color: rgba(0, 0, 0, $alpha-hover);
|
background-color: rgba(0, 0, 0, $alpha-hover);
|
||||||
border-radius: 2rem;
|
border-radius: 2rem;
|
||||||
cursor: pointer;
|
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -5,9 +5,11 @@ import { DataService } from '@ghostfolio/client/services/data.service';
|
|||||||
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
||||||
import {
|
import {
|
||||||
DEFAULT_DATE_FORMAT,
|
DEFAULT_DATE_FORMAT,
|
||||||
PROPERTY_CURRENCIES
|
PROPERTY_CURRENCIES,
|
||||||
|
PROPERTY_SYSTEM_MESSAGE
|
||||||
} from '@ghostfolio/common/config';
|
} from '@ghostfolio/common/config';
|
||||||
import { User } from '@ghostfolio/common/interfaces';
|
import { InfoItem, User } from '@ghostfolio/common/interfaces';
|
||||||
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
import {
|
import {
|
||||||
differenceInSeconds,
|
differenceInSeconds,
|
||||||
formatDistanceToNowStrict,
|
formatDistanceToNowStrict,
|
||||||
@ -29,6 +31,8 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
|
|||||||
public dataGatheringProgress: number;
|
public dataGatheringProgress: number;
|
||||||
public defaultDateFormat = DEFAULT_DATE_FORMAT;
|
public defaultDateFormat = DEFAULT_DATE_FORMAT;
|
||||||
public exchangeRates: { label1: string; label2: string; value: number }[];
|
public exchangeRates: { label1: string; label2: string; value: number }[];
|
||||||
|
public hasPermissionForSystemMessage: boolean;
|
||||||
|
public info: InfoItem;
|
||||||
public lastDataGathering: string;
|
public lastDataGathering: string;
|
||||||
public transactionCount: number;
|
public transactionCount: number;
|
||||||
public userCount: number;
|
public userCount: number;
|
||||||
@ -45,7 +49,14 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
|
|||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private dataService: DataService,
|
private dataService: DataService,
|
||||||
private userService: UserService
|
private userService: UserService
|
||||||
) {}
|
) {
|
||||||
|
this.info = this.dataService.fetchInfo();
|
||||||
|
|
||||||
|
this.hasPermissionForSystemMessage = hasPermission(
|
||||||
|
this.info.globalPermissions,
|
||||||
|
permissions.enableSystemMessage
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the controller
|
* Initializes the controller
|
||||||
@ -62,6 +73,21 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public formatDistanceToNow(aDateString: string) {
|
||||||
|
if (aDateString) {
|
||||||
|
const distanceString = formatDistanceToNowStrict(parseISO(aDateString), {
|
||||||
|
addSuffix: true
|
||||||
|
});
|
||||||
|
|
||||||
|
return Math.abs(differenceInSeconds(parseISO(aDateString), new Date())) <
|
||||||
|
60
|
||||||
|
? 'just now'
|
||||||
|
: distanceString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
public onAddCurrency() {
|
public onAddCurrency() {
|
||||||
const currency = prompt('Please add a currency:');
|
const currency = prompt('Please add a currency:');
|
||||||
|
|
||||||
@ -82,6 +108,10 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onDeleteSystemMessage() {
|
||||||
|
this.putSystemMessage('');
|
||||||
|
}
|
||||||
|
|
||||||
public onFlushCache() {
|
public onFlushCache() {
|
||||||
this.cacheService
|
this.cacheService
|
||||||
.flush()
|
.flush()
|
||||||
@ -117,19 +147,12 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
|
|||||||
.subscribe(() => {});
|
.subscribe(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public formatDistanceToNow(aDateString: string) {
|
public onSetSystemMessage() {
|
||||||
if (aDateString) {
|
const systemMessage = prompt('Please set your system message:');
|
||||||
const distanceString = formatDistanceToNowStrict(parseISO(aDateString), {
|
|
||||||
addSuffix: true
|
|
||||||
});
|
|
||||||
|
|
||||||
return Math.abs(differenceInSeconds(parseISO(aDateString), new Date())) <
|
if (systemMessage) {
|
||||||
60
|
this.putSystemMessage(systemMessage);
|
||||||
? 'just now'
|
|
||||||
: distanceString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy() {
|
public ngOnDestroy() {
|
||||||
@ -187,4 +210,17 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
|
|||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private putSystemMessage(aSystemMessage: string) {
|
||||||
|
this.dataService
|
||||||
|
.putAdminSetting(PROPERTY_SYSTEM_MESSAGE, {
|
||||||
|
value: aSystemMessage
|
||||||
|
})
|
||||||
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
|
.subscribe(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,34 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="hasPermissionForSystemMessage" class="d-flex my-3">
|
||||||
|
<div class="w-50" i18n>System Message</div>
|
||||||
|
<div class="w-50">
|
||||||
|
<div *ngIf="info.systemMessage">
|
||||||
|
<span>{{ info.systemMessage }}</span>
|
||||||
|
<button
|
||||||
|
class="mini-icon mx-1 no-min-width px-2"
|
||||||
|
mat-button
|
||||||
|
[disabled]="dataGatheringInProgress"
|
||||||
|
(click)="onDeleteSystemMessage()"
|
||||||
|
>
|
||||||
|
<ion-icon name="trash-outline"></ion-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
*ngIf="!info.systemMessage"
|
||||||
|
color="accent"
|
||||||
|
mat-flat-button
|
||||||
|
(click)="onSetSystemMessage()"
|
||||||
|
>
|
||||||
|
<ion-icon
|
||||||
|
class="mr-1"
|
||||||
|
name="information-circle-outline"
|
||||||
|
></ion-icon>
|
||||||
|
<span i18n>Set System Message</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, HostBinding, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -7,12 +8,22 @@ import { Subject } from 'rxjs';
|
|||||||
templateUrl: './admin-page.html'
|
templateUrl: './admin-page.html'
|
||||||
})
|
})
|
||||||
export class AdminPageComponent implements OnDestroy, OnInit {
|
export class AdminPageComponent implements OnDestroy, OnInit {
|
||||||
|
@HostBinding('class.with-info-message') get getHasMessage() {
|
||||||
|
return this.hasMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public hasMessage: boolean;
|
||||||
|
|
||||||
private unsubscribeSubject = new Subject<void>();
|
private unsubscribeSubject = new Subject<void>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
public constructor() {}
|
public constructor(private dataService: DataService) {
|
||||||
|
const { systemMessage } = this.dataService.fetchInfo();
|
||||||
|
|
||||||
|
this.hasMessage = !!systemMessage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the controller
|
* Initializes the controller
|
||||||
|
@ -5,11 +5,10 @@ import {
|
|||||||
OnDestroy,
|
OnDestroy,
|
||||||
OnInit
|
OnInit
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
|
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||||
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
||||||
import { User } from '@ghostfolio/common/interfaces';
|
import { User } from '@ghostfolio/common/interfaces';
|
||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -19,11 +18,11 @@ import { takeUntil } from 'rxjs/operators';
|
|||||||
templateUrl: './home-page.html'
|
templateUrl: './home-page.html'
|
||||||
})
|
})
|
||||||
export class HomePageComponent implements OnDestroy, OnInit {
|
export class HomePageComponent implements OnDestroy, OnInit {
|
||||||
@HostBinding('class.with-create-account-container') get isDemo() {
|
@HostBinding('class.with-info-message') get getHasMessage() {
|
||||||
return this.canCreateAccount;
|
return this.hasMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public canCreateAccount: boolean;
|
public hasMessage: boolean;
|
||||||
public hasPermissionToAccessFearAndGreedIndex: boolean;
|
public hasPermissionToAccessFearAndGreedIndex: boolean;
|
||||||
public tabs: { iconName: string; path: string }[] = [];
|
public tabs: { iconName: string; path: string }[] = [];
|
||||||
public user: User;
|
public user: User;
|
||||||
@ -35,10 +34,11 @@ export class HomePageComponent implements OnDestroy, OnInit {
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private deviceService: DeviceDetectorService,
|
private dataService: DataService,
|
||||||
private impersonationStorageService: ImpersonationStorageService,
|
|
||||||
private userService: UserService
|
private userService: UserService
|
||||||
) {
|
) {
|
||||||
|
const { systemMessage } = this.dataService.fetchInfo();
|
||||||
|
|
||||||
this.userService.stateChanged
|
this.userService.stateChanged
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe((state) => {
|
.subscribe((state) => {
|
||||||
@ -50,10 +50,11 @@ export class HomePageComponent implements OnDestroy, OnInit {
|
|||||||
];
|
];
|
||||||
this.user = state.user;
|
this.user = state.user;
|
||||||
|
|
||||||
this.canCreateAccount = hasPermission(
|
this.hasMessage =
|
||||||
this.user?.permissions,
|
hasPermission(
|
||||||
permissions.createUserAccount
|
this.user?.permissions,
|
||||||
);
|
permissions.createUserAccount
|
||||||
|
) || !!systemMessage;
|
||||||
|
|
||||||
this.hasPermissionToAccessFearAndGreedIndex = hasPermission(
|
this.hasPermissionToAccessFearAndGreedIndex = hasPermission(
|
||||||
this.user.permissions,
|
this.user.permissions,
|
||||||
|
@ -10,10 +10,6 @@
|
|||||||
padding-bottom: env(safe-area-inset-bottom);
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
padding-bottom: constant(safe-area-inset-bottom);
|
padding-bottom: constant(safe-area-inset-bottom);
|
||||||
|
|
||||||
&.with-create-account-container {
|
|
||||||
height: calc(100vh - 5rem - 3.5rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
::ng-deep {
|
::ng-deep {
|
||||||
gf-home-holdings,
|
gf-home-holdings,
|
||||||
gf-home-market,
|
gf-home-market,
|
||||||
|
@ -42,8 +42,6 @@ import { map } from 'rxjs/operators';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class DataService {
|
export class DataService {
|
||||||
private info: InfoItem;
|
|
||||||
|
|
||||||
public constructor(private http: HttpClient) {}
|
public constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
public createCheckoutSession({
|
public createCheckoutSession({
|
||||||
@ -241,7 +239,6 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public putAdminSetting(key: string, aData: PropertyDto) {
|
public putAdminSetting(key: string, aData: PropertyDto) {
|
||||||
console.log(key, aData);
|
|
||||||
return this.http.put<void>(`/api/admin/settings/${key}`, aData);
|
return this.http.put<void>(`/api/admin/settings/${key}`, aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,3 +175,7 @@ ngx-skeleton-loader {
|
|||||||
.text-decoration-underline {
|
.text-decoration-underline {
|
||||||
text-decoration: underline !important;
|
text-decoration: underline !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.with-info-message {
|
||||||
|
height: calc(100vh - 5rem - 3.5rem) !important;
|
||||||
|
}
|
||||||
|
@ -34,5 +34,6 @@ export const PROPERTY_CURRENCIES = 'CURRENCIES';
|
|||||||
export const PROPERTY_LAST_DATA_GATHERING = 'LAST_DATA_GATHERING';
|
export const PROPERTY_LAST_DATA_GATHERING = 'LAST_DATA_GATHERING';
|
||||||
export const PROPERTY_LOCKED_DATA_GATHERING = 'LOCKED_DATA_GATHERING';
|
export const PROPERTY_LOCKED_DATA_GATHERING = 'LOCKED_DATA_GATHERING';
|
||||||
export const PROPERTY_STRIPE_CONFIG = 'STRIPE_CONFIG';
|
export const PROPERTY_STRIPE_CONFIG = 'STRIPE_CONFIG';
|
||||||
|
export const PROPERTY_SYSTEM_MESSAGE = 'SYSTEM_MESSAGE';
|
||||||
|
|
||||||
export const UNKNOWN_KEY = 'UNKNOWN';
|
export const UNKNOWN_KEY = 'UNKNOWN';
|
||||||
|
@ -8,10 +8,7 @@ export interface InfoItem {
|
|||||||
demoAuthToken: string;
|
demoAuthToken: string;
|
||||||
globalPermissions: string[];
|
globalPermissions: string[];
|
||||||
lastDataGathering?: Date;
|
lastDataGathering?: Date;
|
||||||
message?: {
|
systemMessage?: string;
|
||||||
text: string;
|
|
||||||
type: string;
|
|
||||||
};
|
|
||||||
platforms: { id: string; name: string }[];
|
platforms: { id: string; name: string }[];
|
||||||
primaryDataSource: DataSource;
|
primaryDataSource: DataSource;
|
||||||
statistics: Statistics;
|
statistics: Statistics;
|
||||||
|
@ -17,6 +17,7 @@ export const permissions = {
|
|||||||
enableSocialLogin: 'enableSocialLogin',
|
enableSocialLogin: 'enableSocialLogin',
|
||||||
enableStatistics: 'enableStatistics',
|
enableStatistics: 'enableStatistics',
|
||||||
enableSubscription: 'enableSubscription',
|
enableSubscription: 'enableSubscription',
|
||||||
|
enableSystemMessage: 'enableSystemMessage',
|
||||||
updateAccount: 'updateAccount',
|
updateAccount: 'updateAccount',
|
||||||
updateAuthDevice: 'updateAuthDevice',
|
updateAuthDevice: 'updateAuthDevice',
|
||||||
updateOrder: 'updateOrder',
|
updateOrder: 'updateOrder',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user