Browse Source

Feature/extend system message (#2628)

* Extend system message

* Update changelog
pull/2629/head
Thomas Kaul 1 year ago
committed by GitHub
parent
commit
12aac101bd
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      CHANGELOG.md
  2. 7
      apps/api/src/app/info/info.service.ts
  3. 19
      apps/api/src/app/user/user.service.ts
  4. 8
      apps/client/src/app/app.component.html
  5. 17
      apps/client/src/app/app.component.ts
  6. 30
      apps/client/src/app/components/admin-overview/admin-overview.component.ts
  7. 5
      apps/client/src/app/components/admin-overview/admin-overview.html
  8. 2
      libs/common/src/lib/interfaces/index.ts
  9. 1
      libs/common/src/lib/interfaces/info-item.interface.ts
  10. 7
      libs/common/src/lib/interfaces/system-message.interface.ts
  11. 2
      libs/common/src/lib/interfaces/user.interface.ts

4
CHANGELOG.md

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
### Changed
- Extended the system message
### Fixed ### Fixed
- Fixed the unit for the _Zen Mode_ in the overview tab of the home page - Fixed the unit for the _Zen Mode_ in the overview tab of the home page

7
apps/api/src/app/info/info.service.ts

@ -15,7 +15,6 @@ import {
PROPERTY_IS_READ_ONLY_MODE, PROPERTY_IS_READ_ONLY_MODE,
PROPERTY_SLACK_COMMUNITY_USERS, PROPERTY_SLACK_COMMUNITY_USERS,
PROPERTY_STRIPE_CONFIG, PROPERTY_STRIPE_CONFIG,
PROPERTY_SYSTEM_MESSAGE,
ghostfolioFearAndGreedIndexDataSource ghostfolioFearAndGreedIndexDataSource
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { import {
@ -58,7 +57,6 @@ export class InfoService {
const platforms = await this.platformService.getPlatforms({ const platforms = await this.platformService.getPlatforms({
orderBy: { name: 'asc' } orderBy: { name: 'asc' }
}); });
let systemMessage: string;
const globalPermissions: string[] = []; const globalPermissions: string[] = [];
@ -104,10 +102,6 @@ export class InfoService {
if (this.configurationService.get('ENABLE_FEATURE_SYSTEM_MESSAGE')) { if (this.configurationService.get('ENABLE_FEATURE_SYSTEM_MESSAGE')) {
globalPermissions.push(permissions.enableSystemMessage); globalPermissions.push(permissions.enableSystemMessage);
systemMessage = (await this.propertyService.getByKey(
PROPERTY_SYSTEM_MESSAGE
)) as string;
} }
const isUserSignupEnabled = const isUserSignupEnabled =
@ -135,7 +129,6 @@ export class InfoService {
platforms, platforms,
statistics, statistics,
subscriptions, subscriptions,
systemMessage,
tags, tags,
baseCurrency: DEFAULT_CURRENCY, baseCurrency: DEFAULT_CURRENCY,
currencies: this.exchangeRateDataService.getCurrencies() currencies: this.exchangeRateDataService.getCurrencies()

19
apps/api/src/app/user/user.service.ts

@ -7,9 +7,14 @@ import { TagService } from '@ghostfolio/api/services/tag/tag.service';
import { import {
DEFAULT_CURRENCY, DEFAULT_CURRENCY,
PROPERTY_IS_READ_ONLY_MODE, PROPERTY_IS_READ_ONLY_MODE,
PROPERTY_SYSTEM_MESSAGE,
locale locale
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { User as IUser, UserSettings } from '@ghostfolio/common/interfaces'; import {
User as IUser,
SystemMessage,
UserSettings
} from '@ghostfolio/common/interfaces';
import { import {
getPermissions, getPermissions,
hasRole, hasRole,
@ -48,6 +53,17 @@ export class UserService {
orderBy: { alias: 'asc' }, orderBy: { alias: 'asc' },
where: { GranteeUser: { id } } where: { GranteeUser: { id } }
}); });
let systemMessage: SystemMessage;
const systemMessageProperty = (await this.propertyService.getByKey(
PROPERTY_SYSTEM_MESSAGE
)) as SystemMessage;
if (systemMessageProperty?.targetGroups?.includes(subscription.type)) {
systemMessage = systemMessageProperty;
}
let tags = await this.tagService.getByUser(id); let tags = await this.tagService.getByUser(id);
if ( if (
@ -61,6 +77,7 @@ export class UserService {
id, id,
permissions, permissions,
subscription, subscription,
systemMessage,
tags, tags,
access: access.map((accessItem) => { access: access.map((accessItem) => {
return { return {

8
apps/client/src/app/app.component.html

@ -1,6 +1,6 @@
<header> <header>
<div <div
*ngIf="canCreateAccount || (info?.systemMessage && user)" *ngIf="canCreateAccount || user?.systemMessage"
class="info-message-container" class="info-message-container"
> >
<div class="info-message-inner-container position-fixed w-100"> <div class="info-message-inner-container position-fixed w-100">
@ -19,11 +19,11 @@
</div></a </div></a
> >
<div <div
*ngIf="!canCreateAccount && info?.systemMessage && user" *ngIf="!canCreateAccount && user?.systemMessage"
class="cursor-pointer d-inline-block info-message text-truncate" class="cursor-pointer d-inline-block info-message text-truncate"
(click)="onShowSystemMessage()" (click)="onClickSystemMessage()"
> >
{{ info.systemMessage }} {{ user.systemMessage.message }}
</div> </div>
</div> </div>
</div> </div>

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

@ -155,10 +155,7 @@ export class AppComponent implements OnDestroy, OnInit {
); );
this.hasInfoMessage = this.hasInfoMessage =
hasPermission( this.canCreateAccount || !!this.user?.systemMessage;
this.user?.permissions,
permissions.createUserAccount
) || !!this.info.systemMessage;
this.initializeTheme(this.user?.settings.colorScheme); this.initializeTheme(this.user?.settings.colorScheme);
@ -166,12 +163,16 @@ export class AppComponent implements OnDestroy, OnInit {
}); });
} }
public onCreateAccount() { public onClickSystemMessage() {
this.tokenStorageService.signOut(); if (this.user.systemMessage.routerLink) {
this.router.navigate(this.user.systemMessage.routerLink);
} else {
alert(this.user.systemMessage.message);
}
} }
public onShowSystemMessage() { public onCreateAccount() {
alert(this.info.systemMessage); this.tokenStorageService.signOut();
} }
public onSignOut() { public onSignOut() {

30
apps/client/src/app/components/admin-overview/admin-overview.component.ts

@ -12,7 +12,12 @@ import {
PROPERTY_SYSTEM_MESSAGE, PROPERTY_SYSTEM_MESSAGE,
ghostfolioPrefix ghostfolioPrefix
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { Coupon, InfoItem, User } from '@ghostfolio/common/interfaces'; import {
Coupon,
InfoItem,
SystemMessage,
User
} from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { import {
differenceInSeconds, differenceInSeconds,
@ -39,6 +44,7 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
public hasPermissionToToggleReadOnlyMode: boolean; public hasPermissionToToggleReadOnlyMode: boolean;
public info: InfoItem; public info: InfoItem;
public permissions = permissions; public permissions = permissions;
public systemMessage: SystemMessage;
public transactionCount: number; public transactionCount: number;
public userCount: number; public userCount: number;
public user: User; public user: User;
@ -149,8 +155,14 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
} }
public onDeleteSystemMessage() { public onDeleteSystemMessage() {
const confirmation = confirm(
$localize`Do you really want to delete this system message?`
);
if (confirmation === true) {
this.putAdminSetting({ key: PROPERTY_SYSTEM_MESSAGE, value: undefined }); this.putAdminSetting({ key: PROPERTY_SYSTEM_MESSAGE, value: undefined });
} }
}
public onFlushCache() { public onFlushCache() {
const confirmation = confirm( const confirmation = confirm(
@ -184,12 +196,21 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
} }
public onSetSystemMessage() { public onSetSystemMessage() {
const systemMessage = prompt($localize`Please set your system message:`); const systemMessage = prompt(
$localize`Please set your system message:`,
JSON.stringify(
this.systemMessage ??
<SystemMessage>{
message: '⚒️ Scheduled maintenance in progress...',
targetGroups: ['Basic', 'Premium']
}
)
);
if (systemMessage) { if (systemMessage) {
this.putAdminSetting({ this.putAdminSetting({
key: PROPERTY_SYSTEM_MESSAGE, key: PROPERTY_SYSTEM_MESSAGE,
value: systemMessage value: JSON.parse(systemMessage)
}); });
} }
} }
@ -208,6 +229,9 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
this.coupons = (settings[PROPERTY_COUPONS] as Coupon[]) ?? []; this.coupons = (settings[PROPERTY_COUPONS] as Coupon[]) ?? [];
this.customCurrencies = settings[PROPERTY_CURRENCIES] as string[]; this.customCurrencies = settings[PROPERTY_CURRENCIES] as string[];
this.exchangeRates = exchangeRates; this.exchangeRates = exchangeRates;
this.systemMessage = settings[
PROPERTY_SYSTEM_MESSAGE
] as SystemMessage;
this.transactionCount = transactionCount; this.transactionCount = transactionCount;
this.userCount = userCount; this.userCount = userCount;
this.version = version; this.version = version;

5
apps/client/src/app/components/admin-overview/admin-overview.html

@ -115,8 +115,8 @@
<div *ngIf="hasPermissionForSystemMessage" class="d-flex my-3"> <div *ngIf="hasPermissionForSystemMessage" class="d-flex my-3">
<div class="w-50" i18n>System Message</div> <div class="w-50" i18n>System Message</div>
<div class="w-50"> <div class="w-50">
<div *ngIf="info?.systemMessage"> <div *ngIf="systemMessage" class="align-items-center d-flex">
<span>{{ info.systemMessage }}</span> <div class="text-truncate">{{ systemMessage | json }}</div>
<button <button
class="h-100 mx-1 no-min-width px-2" class="h-100 mx-1 no-min-width px-2"
mat-button mat-button
@ -127,6 +127,7 @@
</div> </div>
<button <button
*ngIf="!info?.systemMessage" *ngIf="!info?.systemMessage"
class="mt-2"
color="accent" color="accent"
mat-flat-button mat-flat-button
(click)="onSetSystemMessage()" (click)="onSetSystemMessage()"

2
libs/common/src/lib/interfaces/index.ts

@ -42,6 +42,7 @@ import type { PortfolioPerformanceResponse } from './responses/portfolio-perform
import type { ScraperConfiguration } from './scraper-configuration.interface'; import type { ScraperConfiguration } from './scraper-configuration.interface';
import type { Statistics } from './statistics.interface'; import type { Statistics } from './statistics.interface';
import type { Subscription } from './subscription.interface'; import type { Subscription } from './subscription.interface';
import { SystemMessage } from './system-message.interface';
import { TabConfiguration } from './tab-configuration.interface'; import { TabConfiguration } from './tab-configuration.interface';
import type { TimelinePosition } from './timeline-position.interface'; import type { TimelinePosition } from './timeline-position.interface';
import type { UniqueAsset } from './unique-asset.interface'; import type { UniqueAsset } from './unique-asset.interface';
@ -90,6 +91,7 @@ export {
ResponseError, ResponseError,
ScraperConfiguration, ScraperConfiguration,
Statistics, Statistics,
SystemMessage,
Subscription, Subscription,
TabConfiguration, TabConfiguration,
TimelinePosition, TimelinePosition,

1
libs/common/src/lib/interfaces/info-item.interface.ts

@ -17,6 +17,5 @@ export interface InfoItem {
statistics: Statistics; statistics: Statistics;
stripePublicKey?: string; stripePublicKey?: string;
subscriptions: { [offer in SubscriptionOffer]: Subscription }; subscriptions: { [offer in SubscriptionOffer]: Subscription };
systemMessage?: string;
tags: Tag[]; tags: Tag[];
} }

7
libs/common/src/lib/interfaces/system-message.interface.ts

@ -0,0 +1,7 @@
import { SubscriptionType } from '@ghostfolio/common/types/subscription-type.type';
export interface SystemMessage {
message: string;
routerLink?: string[];
targetGroups: SubscriptionType[];
}

2
libs/common/src/lib/interfaces/user.interface.ts

@ -2,6 +2,7 @@ import { SubscriptionOffer } from '@ghostfolio/common/types';
import { SubscriptionType } from '@ghostfolio/common/types/subscription-type.type'; import { SubscriptionType } from '@ghostfolio/common/types/subscription-type.type';
import { Account, Tag } from '@prisma/client'; import { Account, Tag } from '@prisma/client';
import { SystemMessage } from './system-message.interface';
import { UserSettings } from './user-settings.interface'; import { UserSettings } from './user-settings.interface';
// TODO: Compare with UserWithSettings // TODO: Compare with UserWithSettings
@ -14,6 +15,7 @@ export interface User {
id: string; id: string;
permissions: string[]; permissions: string[];
settings: UserSettings; settings: UserSettings;
systemMessage?: SystemMessage;
subscription: { subscription: {
expiresAt?: Date; expiresAt?: Date;
offer: SubscriptionOffer; offer: SubscriptionOffer;

Loading…
Cancel
Save