Improve sidebar (#2343)
* Improve sidebar * Improve style of system message * Update changelog
This commit is contained in:
parent
7f25066f0f
commit
6f6ff94979
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Improved the style of the system message
|
||||||
- Upgraded _Postgres_ from version `12` to `15` in the `docker-compose` files
|
- Upgraded _Postgres_ from version `12` to `15` in the `docker-compose` files
|
||||||
|
|
||||||
## 2.1.0 - 2023-09-15
|
## 2.1.0 - 2023-09-15
|
||||||
|
@ -1,37 +1,26 @@
|
|||||||
<header>
|
<header>
|
||||||
<gf-header
|
|
||||||
class="position-fixed w-100"
|
|
||||||
[currentRoute]="currentRoute"
|
|
||||||
[info]="info"
|
|
||||||
[pageTitle]="pageTitle"
|
|
||||||
[user]="user"
|
|
||||||
(signOut)="onSignOut()"
|
|
||||||
></gf-header>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main role="main">
|
|
||||||
<div
|
<div
|
||||||
*ngIf="canCreateAccount || (info?.systemMessage && user)"
|
*ngIf="canCreateAccount || (info?.systemMessage && user)"
|
||||||
class="container info-message-container"
|
class="info-message-container"
|
||||||
>
|
>
|
||||||
<div class="row">
|
<div class="info-message-inner-container position-fixed w-100">
|
||||||
<div class="col-md-8 offset-md-2 text-center">
|
<div class="align-items-center d-flex h-100 justify-content-center">
|
||||||
<a
|
<a
|
||||||
*ngIf="canCreateAccount"
|
*ngIf="canCreateAccount"
|
||||||
class="text-center"
|
class="text-center"
|
||||||
[routerLink]="routerLinkRegister"
|
[routerLink]="routerLinkRegister"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="cursor-pointer d-inline-block info-message px-3 py-2"
|
class="cursor-pointer d-inline-block info-message"
|
||||||
(click)="onCreateAccount()"
|
(click)="onCreateAccount()"
|
||||||
>
|
>
|
||||||
<span>You are using the Live Demo.</span>
|
<span i18n>You are using the Live Demo.</span>
|
||||||
<span class="a ml-2">Create Account</span>
|
<span class="a ml-2" i18n>Create Account</span>
|
||||||
</div></a
|
</div></a
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
*ngIf="!canCreateAccount && info?.systemMessage && user"
|
*ngIf="!canCreateAccount && info?.systemMessage && user"
|
||||||
class="cursor-pointer d-inline-block info-message px-3 py-2 text-truncate"
|
class="cursor-pointer d-inline-block info-message text-truncate"
|
||||||
(click)="onShowSystemMessage()"
|
(click)="onShowSystemMessage()"
|
||||||
>
|
>
|
||||||
{{ info.systemMessage }}
|
{{ info.systemMessage }}
|
||||||
@ -40,6 +29,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<gf-header
|
||||||
|
class="position-fixed w-100"
|
||||||
|
[currentRoute]="currentRoute"
|
||||||
|
[hasTabs]="hasTabs"
|
||||||
|
[info]="info"
|
||||||
|
[pageTitle]="pageTitle"
|
||||||
|
[user]="user"
|
||||||
|
(signOut)="onSignOut()"
|
||||||
|
></gf-header>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main role="main">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
@ -4,31 +4,47 @@
|
|||||||
display: block;
|
display: block;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|
||||||
|
&.has-info-message {
|
||||||
|
header {
|
||||||
|
height: calc(2 * var(--mat-toolbar-standard-height));
|
||||||
|
|
||||||
|
.info-message-container {
|
||||||
|
height: var(--mat-toolbar-standard-height);
|
||||||
|
|
||||||
|
.info-message-inner-container {
|
||||||
|
background-color: rgba(var(--palette-primary-500), 1);
|
||||||
|
height: var(--mat-toolbar-standard-height);
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
.info-message {
|
||||||
|
color: rgba(var(--palette-foreground-text), 1);
|
||||||
|
font-size: 80%;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
.a {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
min-height: calc(100vh - 2 * var(--mat-toolbar-standard-height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
background-color: rgba(var(--palette-foreground-text), 0.05);
|
background-color: rgba(var(--palette-foreground-text), 0.05);
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
height: var(--mat-toolbar-standard-height);
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
min-height: 100vh;
|
min-height: calc(100vh - var(--mat-toolbar-standard-height));
|
||||||
padding-top: 5rem;
|
|
||||||
|
|
||||||
.info-message-container {
|
|
||||||
height: 3.5rem;
|
|
||||||
margin-top: -0.5rem;
|
|
||||||
|
|
||||||
.info-message {
|
|
||||||
background-color: rgba(var(--palette-foreground-text), 0.05);
|
|
||||||
border-radius: 2rem;
|
|
||||||
font-size: 80%;
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
.a {
|
|
||||||
color: rgba(var(--palette-primary-500), 1);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,12 +52,4 @@
|
|||||||
footer {
|
footer {
|
||||||
background-color: rgba(var(--palette-foreground-text-dark), 0.05);
|
background-color: rgba(var(--palette-foreground-text-dark), 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
|
||||||
.info-message-container {
|
|
||||||
.info-message {
|
|
||||||
background-color: rgba(var(--palette-foreground-text-dark), 0.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import {
|
|||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
Component,
|
Component,
|
||||||
|
HostBinding,
|
||||||
Inject,
|
Inject,
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
OnInit
|
OnInit
|
||||||
@ -28,14 +29,20 @@ import { UserService } from './services/user/user.service';
|
|||||||
styleUrls: ['./app.component.scss']
|
styleUrls: ['./app.component.scss']
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnDestroy, OnInit {
|
export class AppComponent implements OnDestroy, OnInit {
|
||||||
|
@HostBinding('class.has-info-message') get getHasMessage() {
|
||||||
|
return this.hasInfoMessage;
|
||||||
|
}
|
||||||
|
|
||||||
public canCreateAccount: boolean;
|
public canCreateAccount: boolean;
|
||||||
public currentRoute: string;
|
public currentRoute: string;
|
||||||
public currentYear = new Date().getFullYear();
|
public currentYear = new Date().getFullYear();
|
||||||
public deviceType: string;
|
public deviceType: string;
|
||||||
|
public hasInfoMessage: boolean;
|
||||||
public hasPermissionForBlog: boolean;
|
public hasPermissionForBlog: boolean;
|
||||||
public hasPermissionForStatistics: boolean;
|
public hasPermissionForStatistics: boolean;
|
||||||
public hasPermissionForSubscription: boolean;
|
public hasPermissionForSubscription: boolean;
|
||||||
public hasPermissionToAccessFearAndGreedIndex: boolean;
|
public hasPermissionToAccessFearAndGreedIndex: boolean;
|
||||||
|
public hasTabs = false;
|
||||||
public info: InfoItem;
|
public info: InfoItem;
|
||||||
public pageTitle: string;
|
public pageTitle: string;
|
||||||
public routerLinkAbout = ['/' + $localize`about`];
|
public routerLinkAbout = ['/' + $localize`about`];
|
||||||
@ -103,6 +110,14 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
const urlSegments = urlSegmentGroup.segments;
|
const urlSegments = urlSegmentGroup.segments;
|
||||||
this.currentRoute = urlSegments[0].path;
|
this.currentRoute = urlSegments[0].path;
|
||||||
|
|
||||||
|
this.hasTabs =
|
||||||
|
(this.currentRoute === this.routerLinkAbout[0].slice(1) ||
|
||||||
|
this.currentRoute === 'admin' ||
|
||||||
|
this.currentRoute === 'home' ||
|
||||||
|
this.currentRoute === 'portfolio' ||
|
||||||
|
this.currentRoute === 'zen') &&
|
||||||
|
this.deviceType !== 'mobile';
|
||||||
|
|
||||||
this.showFooter =
|
this.showFooter =
|
||||||
(this.currentRoute === 'blog' ||
|
(this.currentRoute === 'blog' ||
|
||||||
this.currentRoute === this.routerLinkFaq[0].slice(1) ||
|
this.currentRoute === this.routerLinkFaq[0].slice(1) ||
|
||||||
@ -140,6 +155,12 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
permissions.createUserAccount
|
permissions.createUserAccount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.hasInfoMessage =
|
||||||
|
hasPermission(
|
||||||
|
this.user?.permissions,
|
||||||
|
permissions.createUserAccount
|
||||||
|
) || !!this.info.systemMessage;
|
||||||
|
|
||||||
this.initializeTheme(this.user?.settings.colorScheme);
|
this.initializeTheme(this.user?.settings.colorScheme);
|
||||||
|
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
|
@ -8,7 +8,6 @@ import { Subject } from 'rxjs';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-admin-settings',
|
selector: 'gf-admin-settings',
|
||||||
styleUrls: ['./admin-settings.component.scss'],
|
styleUrls: ['./admin-settings.component.scss'],
|
||||||
templateUrl: './admin-settings.component.html'
|
templateUrl: './admin-settings.component.html'
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
<mat-toolbar class="px-2">
|
<mat-toolbar class="px-0">
|
||||||
<ng-container *ngIf="user">
|
<ng-container *ngIf="user">
|
||||||
<a
|
<div class="d-flex h-100 logo-container" [ngClass]="{ filled: hasTabs }">
|
||||||
class="align-items-center d-flex h-100 no-min-width px-2 rounded-0"
|
<a
|
||||||
mat-button
|
class="align-items-center justify-content-start rounded-0"
|
||||||
[routerLink]="['/']"
|
mat-button
|
||||||
>
|
[ngClass]="{ 'w-100': hasTabs }"
|
||||||
<gf-logo [label]="pageTitle"></gf-logo>
|
[routerLink]="['/']"
|
||||||
</a>
|
>
|
||||||
|
<gf-logo class="px-2" [label]="pageTitle"></gf-logo>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<ul class="alig-items-center d-flex list-inline m-0">
|
<ul class="alig-items-center d-flex list-inline m-0 px-2">
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<a
|
<a
|
||||||
class="d-none d-sm-block"
|
class="d-none d-sm-block"
|
||||||
@ -246,18 +249,22 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="user === null">
|
<ng-container *ngIf="user === null">
|
||||||
<a
|
<div class="d-flex h-100 logo-container" [ngClass]="{ filled: hasTabs }">
|
||||||
class="align-items-center d-flex h-100 mx-2 no-min-width px-2 rounded-0"
|
<a
|
||||||
mat-button
|
class="align-items-center justify-content-start rounded-0"
|
||||||
[routerLink]="['/']"
|
mat-button
|
||||||
>
|
[ngClass]="{ 'w-100': hasTabs }"
|
||||||
<gf-logo
|
[routerLink]="['/']"
|
||||||
[label]="pageTitle"
|
>
|
||||||
[showLabel]="currentRoute !== 'register'"
|
<gf-logo
|
||||||
></gf-logo>
|
class="px-2"
|
||||||
</a>
|
[label]="pageTitle"
|
||||||
|
[showLabel]="currentRoute !== 'register'"
|
||||||
|
></gf-logo>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<ul class="alig-items-center d-flex list-inline m-0">
|
<ul class="alig-items-center d-flex list-inline m-0 px-2">
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<a
|
<a
|
||||||
class="d-none d-sm-block"
|
class="d-none d-sm-block"
|
||||||
|
@ -7,6 +7,16 @@
|
|||||||
.mat-toolbar {
|
.mat-toolbar {
|
||||||
background-color: var(--light-background);
|
background-color: var(--light-background);
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
&.filled {
|
||||||
|
background-color: rgba(var(--palette-foreground-base), 0.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
width: 14rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.list-inline-item {
|
.list-inline-item {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@ -34,5 +44,11 @@
|
|||||||
:host-context(.is-dark-theme) {
|
:host-context(.is-dark-theme) {
|
||||||
.mat-toolbar {
|
.mat-toolbar {
|
||||||
background-color: var(--dark-background);
|
background-color: var(--dark-background);
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
&.filled {
|
||||||
|
background-color: rgba(var(--palette-foreground-base-dark), 0.02);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import { catchError, takeUntil } from 'rxjs/operators';
|
|||||||
})
|
})
|
||||||
export class HeaderComponent implements OnChanges {
|
export class HeaderComponent implements OnChanges {
|
||||||
@Input() currentRoute: string;
|
@Input() currentRoute: string;
|
||||||
|
@Input() hasTabs: boolean;
|
||||||
@Input() info: InfoItem;
|
@Input() info: InfoItem;
|
||||||
@Input() pageTitle: string;
|
@Input() pageTitle: string;
|
||||||
@Input() user: User;
|
@Input() user: User;
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
import {
|
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
|
||||||
HostBinding,
|
|
||||||
OnDestroy,
|
|
||||||
OnInit
|
|
||||||
} from '@angular/core';
|
|
||||||
import { DataService } from '@ghostfolio/client/services/data.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 { TabConfiguration, User } from '@ghostfolio/common/interfaces';
|
import { TabConfiguration, User } from '@ghostfolio/common/interfaces';
|
||||||
@ -14,18 +8,13 @@ import { Subject } from 'rxjs';
|
|||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page with-tabs' },
|
host: { class: 'page has-tabs' },
|
||||||
selector: 'gf-about-page',
|
selector: 'gf-about-page',
|
||||||
styleUrls: ['./about-page.scss'],
|
styleUrls: ['./about-page.scss'],
|
||||||
templateUrl: './about-page.html'
|
templateUrl: './about-page.html'
|
||||||
})
|
})
|
||||||
export class AboutPageComponent implements OnDestroy, OnInit {
|
export class AboutPageComponent implements OnDestroy, OnInit {
|
||||||
@HostBinding('class.with-info-message') get getHasMessage() {
|
|
||||||
return this.hasMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public deviceType: string;
|
public deviceType: string;
|
||||||
public hasMessage: boolean;
|
|
||||||
public hasPermissionForSubscription: boolean;
|
public hasPermissionForSubscription: boolean;
|
||||||
public tabs: TabConfiguration[] = [];
|
public tabs: TabConfiguration[] = [];
|
||||||
public user: User;
|
public user: User;
|
||||||
@ -38,7 +27,7 @@ export class AboutPageComponent implements OnDestroy, OnInit {
|
|||||||
private deviceService: DeviceDetectorService,
|
private deviceService: DeviceDetectorService,
|
||||||
private userService: UserService
|
private userService: UserService
|
||||||
) {
|
) {
|
||||||
const { globalPermissions, systemMessage } = this.dataService.fetchInfo();
|
const { globalPermissions } = this.dataService.fetchInfo();
|
||||||
|
|
||||||
this.hasPermissionForSubscription = hasPermission(
|
this.hasPermissionForSubscription = hasPermission(
|
||||||
globalPermissions,
|
globalPermissions,
|
||||||
@ -75,12 +64,6 @@ export class AboutPageComponent implements OnDestroy, OnInit {
|
|||||||
});
|
});
|
||||||
this.user = state.user;
|
this.user = state.user;
|
||||||
|
|
||||||
this.hasMessage =
|
|
||||||
hasPermission(
|
|
||||||
this.user?.permissions,
|
|
||||||
permissions.createUserAccount
|
|
||||||
) || !!systemMessage;
|
|
||||||
|
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</mat-tab-nav-panel>
|
</mat-tab-nav-panel>
|
||||||
|
|
||||||
<nav mat-align-tabs="center" mat-tab-nav-bar [tabPanel]="tabPanel">
|
<nav
|
||||||
|
mat-align-tabs="center"
|
||||||
|
mat-tab-nav-bar
|
||||||
|
[disablePagination]="true"
|
||||||
|
[tabPanel]="tabPanel"
|
||||||
|
>
|
||||||
<ng-container *ngFor="let tab of tabs">
|
<ng-container *ngFor="let tab of tabs">
|
||||||
<a
|
<a
|
||||||
#rla="routerLinkActive"
|
#rla="routerLinkActive"
|
||||||
|
@ -2,7 +2,6 @@ import { Component, OnDestroy } from '@angular/core';
|
|||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-changelog-page',
|
selector: 'gf-changelog-page',
|
||||||
styleUrls: ['./changelog-page.scss'],
|
styleUrls: ['./changelog-page.scss'],
|
||||||
templateUrl: './changelog-page.html'
|
templateUrl: './changelog-page.html'
|
||||||
|
@ -2,7 +2,6 @@ import { Component, OnDestroy } from '@angular/core';
|
|||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-license-page',
|
selector: 'gf-license-page',
|
||||||
styleUrls: ['./license-page.scss'],
|
styleUrls: ['./license-page.scss'],
|
||||||
templateUrl: './license-page.html'
|
templateUrl: './license-page.html'
|
||||||
|
@ -4,7 +4,6 @@ import { Subject } from 'rxjs';
|
|||||||
const ossFriends = require('../../../../assets/oss-friends.json');
|
const ossFriends = require('../../../../assets/oss-friends.json');
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-oss-friends-page',
|
selector: 'gf-oss-friends-page',
|
||||||
styleUrls: ['./oss-friends-page.scss'],
|
styleUrls: ['./oss-friends-page.scss'],
|
||||||
templateUrl: './oss-friends-page.html'
|
templateUrl: './oss-friends-page.html'
|
||||||
|
@ -8,7 +8,6 @@ import { Subject } from 'rxjs';
|
|||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-about-overview-page',
|
selector: 'gf-about-overview-page',
|
||||||
styleUrls: ['./about-overview-page.scss'],
|
styleUrls: ['./about-overview-page.scss'],
|
||||||
templateUrl: './about-overview-page.html'
|
templateUrl: './about-overview-page.html'
|
||||||
|
@ -2,7 +2,6 @@ import { Component, OnDestroy } from '@angular/core';
|
|||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-privacy-policy-page',
|
selector: 'gf-privacy-policy-page',
|
||||||
styleUrls: ['./privacy-policy-page.scss'],
|
styleUrls: ['./privacy-policy-page.scss'],
|
||||||
templateUrl: './privacy-policy-page.html'
|
templateUrl: './privacy-policy-page.html'
|
||||||
|
@ -1,34 +1,21 @@
|
|||||||
import { Component, HostBinding, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
|
||||||
import { TabConfiguration } from '@ghostfolio/common/interfaces';
|
import { TabConfiguration } from '@ghostfolio/common/interfaces';
|
||||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page with-tabs' },
|
host: { class: 'page has-tabs' },
|
||||||
selector: 'gf-admin-page',
|
selector: 'gf-admin-page',
|
||||||
styleUrls: ['./admin-page.scss'],
|
styleUrls: ['./admin-page.scss'],
|
||||||
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 deviceType: string;
|
public deviceType: string;
|
||||||
public hasMessage: boolean;
|
|
||||||
public tabs: TabConfiguration[] = [];
|
public tabs: TabConfiguration[] = [];
|
||||||
|
|
||||||
private unsubscribeSubject = new Subject<void>();
|
private unsubscribeSubject = new Subject<void>();
|
||||||
|
|
||||||
public constructor(
|
public constructor(private deviceService: DeviceDetectorService) {}
|
||||||
private dataService: DataService,
|
|
||||||
private deviceService: DeviceDetectorService
|
|
||||||
) {
|
|
||||||
const { systemMessage } = this.dataService.fetchInfo();
|
|
||||||
|
|
||||||
this.hasMessage = !!systemMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
|
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</mat-tab-nav-panel>
|
</mat-tab-nav-panel>
|
||||||
|
|
||||||
<nav mat-align-tabs="center" mat-tab-nav-bar [tabPanel]="tabPanel">
|
<nav
|
||||||
|
mat-align-tabs="center"
|
||||||
|
mat-tab-nav-bar
|
||||||
|
[disablePagination]="true"
|
||||||
|
[tabPanel]="tabPanel"
|
||||||
|
>
|
||||||
<ng-container *ngFor="let tab of tabs">
|
<ng-container *ngFor="let tab of tabs">
|
||||||
<a
|
<a
|
||||||
#rla="routerLinkActive"
|
#rla="routerLinkActive"
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
import {
|
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
|
||||||
HostBinding,
|
|
||||||
OnDestroy,
|
|
||||||
OnInit
|
|
||||||
} from '@angular/core';
|
|
||||||
import { DataService } from '@ghostfolio/client/services/data.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 { TabConfiguration, User } from '@ghostfolio/common/interfaces';
|
import { TabConfiguration, User } from '@ghostfolio/common/interfaces';
|
||||||
@ -14,18 +8,13 @@ import { Subject } from 'rxjs';
|
|||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page with-tabs' },
|
host: { class: 'page has-tabs' },
|
||||||
selector: 'gf-home-page',
|
selector: 'gf-home-page',
|
||||||
styleUrls: ['./home-page.scss'],
|
styleUrls: ['./home-page.scss'],
|
||||||
templateUrl: './home-page.html'
|
templateUrl: './home-page.html'
|
||||||
})
|
})
|
||||||
export class HomePageComponent implements OnDestroy, OnInit {
|
export class HomePageComponent implements OnDestroy, OnInit {
|
||||||
@HostBinding('class.with-info-message') get getHasMessage() {
|
|
||||||
return this.hasMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public deviceType: string;
|
public deviceType: string;
|
||||||
public hasMessage: boolean;
|
|
||||||
public hasPermissionToAccessFearAndGreedIndex: boolean;
|
public hasPermissionToAccessFearAndGreedIndex: boolean;
|
||||||
public tabs: TabConfiguration[] = [];
|
public tabs: TabConfiguration[] = [];
|
||||||
public user: User;
|
public user: User;
|
||||||
@ -38,7 +27,7 @@ export class HomePageComponent implements OnDestroy, OnInit {
|
|||||||
private deviceService: DeviceDetectorService,
|
private deviceService: DeviceDetectorService,
|
||||||
private userService: UserService
|
private userService: UserService
|
||||||
) {
|
) {
|
||||||
const { globalPermissions, systemMessage } = this.dataService.fetchInfo();
|
const { globalPermissions } = this.dataService.fetchInfo();
|
||||||
|
|
||||||
this.hasPermissionToAccessFearAndGreedIndex = hasPermission(
|
this.hasPermissionToAccessFearAndGreedIndex = hasPermission(
|
||||||
globalPermissions,
|
globalPermissions,
|
||||||
@ -74,12 +63,6 @@ export class HomePageComponent implements OnDestroy, OnInit {
|
|||||||
];
|
];
|
||||||
this.user = state.user;
|
this.user = state.user;
|
||||||
|
|
||||||
this.hasMessage =
|
|
||||||
hasPermission(
|
|
||||||
this.user?.permissions,
|
|
||||||
permissions.createUserAccount
|
|
||||||
) || !!systemMessage;
|
|
||||||
|
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</mat-tab-nav-panel>
|
</mat-tab-nav-panel>
|
||||||
|
|
||||||
<nav mat-align-tabs="center" mat-tab-nav-bar [tabPanel]="tabPanel">
|
<nav
|
||||||
|
mat-align-tabs="center"
|
||||||
|
mat-tab-nav-bar
|
||||||
|
[disablePagination]="true"
|
||||||
|
[tabPanel]="tabPanel"
|
||||||
|
>
|
||||||
<ng-container *ngFor="let tab of tabs">
|
<ng-container *ngFor="let tab of tabs">
|
||||||
<a
|
<a
|
||||||
#rla="routerLinkActive"
|
#rla="routerLinkActive"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<div class="mt-5">
|
<div>
|
||||||
<div class="badge badge-light badge-pill border mb-3 px-3 py-2">
|
<div class="badge badge-light badge-pill border mb-3 px-3 py-2">
|
||||||
<a href="../en/blog/2023/09/ghostfolio-2"
|
<a href="../en/blog/2023/09/ghostfolio-2"
|
||||||
><span class="mr-1 text-uppercase" i18n>New</span>
|
><span class="mr-1 text-uppercase" i18n>New</span>
|
||||||
|
@ -24,7 +24,6 @@ import { ImportActivitiesDialog } from './import-activities-dialog/import-activi
|
|||||||
import { ImportActivitiesDialogParams } from './import-activities-dialog/interfaces/interfaces';
|
import { ImportActivitiesDialogParams } from './import-activities-dialog/interfaces/interfaces';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-activities-page',
|
selector: 'gf-activities-page',
|
||||||
styleUrls: ['./activities-page.scss'],
|
styleUrls: ['./activities-page.scss'],
|
||||||
templateUrl: './activities-page.html'
|
templateUrl: './activities-page.html'
|
||||||
|
@ -27,7 +27,6 @@ import { Subject } from 'rxjs';
|
|||||||
import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
|
import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-allocations-page',
|
selector: 'gf-allocations-page',
|
||||||
styleUrls: ['./allocations-page.scss'],
|
styleUrls: ['./allocations-page.scss'],
|
||||||
templateUrl: './allocations-page.html'
|
templateUrl: './allocations-page.html'
|
||||||
|
@ -26,7 +26,6 @@ import { Subject } from 'rxjs';
|
|||||||
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
|
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-analysis-page',
|
selector: 'gf-analysis-page',
|
||||||
styleUrls: ['./analysis-page.scss'],
|
styleUrls: ['./analysis-page.scss'],
|
||||||
templateUrl: './analysis-page.html'
|
templateUrl: './analysis-page.html'
|
||||||
|
@ -10,7 +10,6 @@ import { Subject } from 'rxjs';
|
|||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-fire-page',
|
selector: 'gf-fire-page',
|
||||||
styleUrls: ['./fire-page.scss'],
|
styleUrls: ['./fire-page.scss'],
|
||||||
templateUrl: './fire-page.html'
|
templateUrl: './fire-page.html'
|
||||||
|
@ -20,7 +20,6 @@ import { Subject } from 'rxjs';
|
|||||||
import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
|
import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
|
||||||
selector: 'gf-holdings-page',
|
selector: 'gf-holdings-page',
|
||||||
styleUrls: ['./holdings-page.scss'],
|
styleUrls: ['./holdings-page.scss'],
|
||||||
templateUrl: './holdings-page.html'
|
templateUrl: './holdings-page.html'
|
||||||
|
@ -1,36 +1,18 @@
|
|||||||
import {
|
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
|
||||||
HostBinding,
|
|
||||||
OnDestroy,
|
|
||||||
OnInit
|
|
||||||
} from '@angular/core';
|
|
||||||
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 { TabConfiguration, User } from '@ghostfolio/common/interfaces';
|
||||||
InfoItem,
|
|
||||||
TabConfiguration,
|
|
||||||
User
|
|
||||||
} from '@ghostfolio/common/interfaces';
|
|
||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
|
||||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page with-tabs' },
|
host: { class: 'page has-tabs' },
|
||||||
selector: 'gf-portfolio-page',
|
selector: 'gf-portfolio-page',
|
||||||
styleUrls: ['./portfolio-page.scss'],
|
styleUrls: ['./portfolio-page.scss'],
|
||||||
templateUrl: './portfolio-page.html'
|
templateUrl: './portfolio-page.html'
|
||||||
})
|
})
|
||||||
export class PortfolioPageComponent implements OnDestroy, OnInit {
|
export class PortfolioPageComponent implements OnDestroy, OnInit {
|
||||||
@HostBinding('class.with-info-message') get getHasMessage() {
|
|
||||||
return this.hasMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public deviceType: string;
|
public deviceType: string;
|
||||||
public hasMessage: boolean;
|
|
||||||
public info: InfoItem;
|
|
||||||
public tabs: TabConfiguration[] = [];
|
public tabs: TabConfiguration[] = [];
|
||||||
public user: User;
|
public user: User;
|
||||||
|
|
||||||
@ -38,12 +20,9 @@ export class PortfolioPageComponent implements OnDestroy, OnInit {
|
|||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private dataService: DataService,
|
|
||||||
private deviceService: DeviceDetectorService,
|
private deviceService: DeviceDetectorService,
|
||||||
private userService: UserService
|
private userService: UserService
|
||||||
) {
|
) {
|
||||||
this.info = this.dataService.fetchInfo();
|
|
||||||
|
|
||||||
this.userService.stateChanged
|
this.userService.stateChanged
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe((state) => {
|
.subscribe((state) => {
|
||||||
@ -77,12 +56,6 @@ export class PortfolioPageComponent implements OnDestroy, OnInit {
|
|||||||
];
|
];
|
||||||
this.user = state.user;
|
this.user = state.user;
|
||||||
|
|
||||||
this.hasMessage =
|
|
||||||
hasPermission(
|
|
||||||
this.user?.permissions,
|
|
||||||
permissions.createUserAccount
|
|
||||||
) || !!this.info.systemMessage;
|
|
||||||
|
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</mat-tab-nav-panel>
|
</mat-tab-nav-panel>
|
||||||
|
|
||||||
<nav mat-align-tabs="center" mat-tab-nav-bar [tabPanel]="tabPanel">
|
<nav
|
||||||
|
mat-align-tabs="center"
|
||||||
|
mat-tab-nav-bar
|
||||||
|
[disablePagination]="true"
|
||||||
|
[tabPanel]="tabPanel"
|
||||||
|
>
|
||||||
<ng-container *ngFor="let tab of tabs">
|
<ng-container *ngFor="let tab of tabs">
|
||||||
<a
|
<a
|
||||||
#rla="routerLinkActive"
|
#rla="routerLinkActive"
|
||||||
|
@ -6,7 +6,7 @@ import { Subject } from 'rxjs';
|
|||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page with-tabs' },
|
host: { class: 'page has-tabs' },
|
||||||
selector: 'gf-zen-page',
|
selector: 'gf-zen-page',
|
||||||
styleUrls: ['./zen-page.scss'],
|
styleUrls: ['./zen-page.scss'],
|
||||||
templateUrl: './zen-page.html'
|
templateUrl: './zen-page.html'
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</mat-tab-nav-panel>
|
</mat-tab-nav-panel>
|
||||||
|
|
||||||
<nav mat-align-tabs="center" mat-tab-nav-bar [tabPanel]="tabPanel">
|
<nav
|
||||||
|
mat-align-tabs="center"
|
||||||
|
mat-tab-nav-bar
|
||||||
|
[disablePagination]="true"
|
||||||
|
[tabPanel]="tabPanel"
|
||||||
|
>
|
||||||
<ng-container *ngFor="let tab of tabs">
|
<ng-container *ngFor="let tab of tabs">
|
||||||
<a
|
<a
|
||||||
#rla="routerLinkActive"
|
#rla="routerLinkActive"
|
||||||
|
@ -275,12 +275,18 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
&.with-tabs {
|
&.has-tabs {
|
||||||
.mat-mdc-tab-nav-bar {
|
.mat-mdc-tab-nav-bar {
|
||||||
--mat-tab-header-inactive-label-text-color: rgba(
|
--mat-tab-header-inactive-label-text-color: rgba(
|
||||||
var(--light-primary-text)
|
var(--light-primary-text)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
.mat-mdc-tab-header {
|
||||||
|
background-color: rgba(var(--palette-foreground-base-dark), 0.02);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,6 +373,12 @@ ngx-skeleton-loader {
|
|||||||
@include gf-table;
|
@include gf-table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.has-info-message {
|
||||||
|
.page.has-tabs {
|
||||||
|
height: calc(100vh - 2 * var(--mat-toolbar-standard-height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
@ -469,12 +481,14 @@ ngx-skeleton-loader {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
&:not(.with-tabs) {
|
&:not(.has-tabs) {
|
||||||
padding-bottom: 5rem;
|
@media (min-width: 576px) {
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.with-tabs {
|
&.has-tabs {
|
||||||
height: calc(100vh - 5rem);
|
height: calc(100vh - var(--mat-toolbar-standard-height));
|
||||||
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);
|
||||||
|
|
||||||
@ -491,7 +505,10 @@ ngx-skeleton-loader {
|
|||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
|
|
||||||
.mat-mdc-tab-header {
|
.mat-mdc-tab-header {
|
||||||
width: 12rem;
|
background-color: rgba(var(--palette-foreground-base), 0.02);
|
||||||
|
padding: 2rem 0;
|
||||||
|
width: 14rem;
|
||||||
|
--mat-tab-header-label-text-tracking: normal;
|
||||||
--mdc-secondary-navigation-tab-container-height: 2rem;
|
--mdc-secondary-navigation-tab-container-height: 2rem;
|
||||||
|
|
||||||
.mat-mdc-tab-links {
|
.mat-mdc-tab-links {
|
||||||
@ -502,6 +519,10 @@ ngx-skeleton-loader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mat-mdc-tab-nav-panel {
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,10 +539,6 @@ ngx-skeleton-loader {
|
|||||||
text-decoration: underline !important;
|
text-decoration: underline !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.with-info-message {
|
|
||||||
height: calc(100vh - 5rem - 3.5rem + 0.5rem) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.with-placeholder-as-option {
|
.with-placeholder-as-option {
|
||||||
.mat-mdc-select-placeholder {
|
.mat-mdc-select-placeholder {
|
||||||
color: rgba(var(--dark-primary-text));
|
color: rgba(var(--dark-primary-text));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user