From 1d3c32d3ead935cca670c808fd3ae0e17a817ce6 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Thu, 1 Jun 2023 20:35:38 +0200 Subject: [PATCH] Add tabs to about page --- .../pages/about/about-page-routing.module.ts | 24 +++ .../app/pages/about/about-page.component.ts | 61 ++++-- .../src/app/pages/about/about-page.html | 195 ++---------------- .../src/app/pages/about/about-page.module.ts | 5 +- .../src/app/pages/about/about-page.scss | 45 ++-- .../about-overview-page-routing.module.ts | 20 ++ .../overview/about-overview-page.component.ts | 61 ++++++ .../about/overview/about-overview-page.html | 157 ++++++++++++++ .../overview/about-overview-page.module.ts | 13 ++ .../about/overview/about-overview-page.scss | 36 ++++ .../src/app/pages/admin/admin-page.html | 25 +-- apps/client/src/app/pages/home/home-page.html | 24 ++- .../app/pages/portfolio/portfolio-page.html | 25 +-- apps/client/src/app/pages/zen/zen-page.html | 24 ++- 14 files changed, 452 insertions(+), 263 deletions(-) create mode 100644 apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts create mode 100644 apps/client/src/app/pages/about/overview/about-overview-page.component.ts create mode 100644 apps/client/src/app/pages/about/overview/about-overview-page.html create mode 100644 apps/client/src/app/pages/about/overview/about-overview-page.module.ts create mode 100644 apps/client/src/app/pages/about/overview/about-overview-page.scss diff --git a/apps/client/src/app/pages/about/about-page-routing.module.ts b/apps/client/src/app/pages/about/about-page-routing.module.ts index 33a303a5b..63faf7396 100644 --- a/apps/client/src/app/pages/about/about-page-routing.module.ts +++ b/apps/client/src/app/pages/about/about-page-routing.module.ts @@ -7,6 +7,30 @@ import { AboutPageComponent } from './about-page.component'; const routes: Routes = [ { canActivate: [AuthGuard], + children: [ + { path: '', redirectTo: 'overview', pathMatch: 'full' }, + { + path: 'overview', + loadChildren: () => + import('./overview/about-overview-page.module').then( + (m) => m.AboutOverviewPageModule + ) + }, + { + path: 'changelog', + loadChildren: () => + import('./changelog/changelog-page.module').then( + (m) => m.ChangelogPageModule + ) + }, + { + path: 'privacy-policy', + loadChildren: () => + import('./privacy-policy/privacy-policy-page.module').then( + (m) => m.PrivacyPolicyPageModule + ) + } + ], component: AboutPageComponent, path: '', title: $localize`About` diff --git a/apps/client/src/app/pages/about/about-page.component.ts b/apps/client/src/app/pages/about/about-page.component.ts index 5790d663d..ff2b0c532 100644 --- a/apps/client/src/app/pages/about/about-page.component.ts +++ b/apps/client/src/app/pages/about/about-page.component.ts @@ -1,26 +1,36 @@ -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; -import { environment } from '@ghostfolio/client/../environments/environment'; +import { + 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 { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ - host: { class: 'page' }, selector: 'gf-about-page', styleUrls: ['./about-page.scss'], templateUrl: './about-page.html' }) export class AboutPageComponent implements OnDestroy, OnInit { - public defaultLanguageCode = DEFAULT_LANGUAGE_CODE; - public hasPermissionForBlog: boolean; + @HostBinding('class.with-info-message') get getHasMessage() { + return this.hasMessage; + } + + public hasMessage: boolean; public hasPermissionForSubscription: boolean; - public isLoggedIn: boolean; + public tabs: { + iconName: string; + label: string; + path: string; + showCondition?: boolean; + }[] = []; public user: User; - public version = environment.version; private unsubscribeSubject = new Subject(); @@ -29,31 +39,50 @@ export class AboutPageComponent implements OnDestroy, OnInit { private dataService: DataService, private userService: UserService ) { - const { globalPermissions } = this.dataService.fetchInfo(); - - this.hasPermissionForBlog = hasPermission( - globalPermissions, - permissions.enableBlog - ); + const { globalPermissions, systemMessage } = this.dataService.fetchInfo(); this.hasPermissionForSubscription = hasPermission( globalPermissions, permissions.enableSubscription ); - } - public ngOnInit() { this.userService.stateChanged .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((state) => { if (state?.user) { + this.tabs = [ + { + iconName: 'reader-outline', + label: $localize`About`, + path: 'overview' + }, + { + iconName: 'sparkles-outline', + label: $localize`Changelog & License`, + path: 'changelog' + }, + { + iconName: 'shield-checkmark-outline', + label: $localize`Privacy Policy`, + path: 'privacy-policy', + showCondition: this.hasPermissionForSubscription + } + ]; this.user = state.user; + this.hasMessage = + hasPermission( + this.user?.permissions, + permissions.createUserAccount + ) || !!systemMessage; + this.changeDetectorRef.markForCheck(); } }); } + public ngOnInit() {} + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/pages/about/about-page.html b/apps/client/src/app/pages/about/about-page.html index c761b9aed..6b15d795d 100644 --- a/apps/client/src/app/pages/about/about-page.html +++ b/apps/client/src/app/pages/about/about-page.html @@ -1,178 +1,21 @@ -
-
-
-

About Ghostfolio

-
-

- Ghostfolio is a lightweight wealth management application for - individuals to keep track of stocks, ETFs or cryptocurrencies and make - solid, data-driven investment decisions. The source code is fully - available as - open source software - (OSS) under the - AGPL-3.0 license - and we share aggregated - key metrics - of the platform’s performance. The project has been initiated by - Thomas Kaul - and is driven by the efforts of its - contributors. - - This instance is running Ghostfolio {{ version }}. - - Check the system status at - status.ghostfol.io. -

-

- If you encounter a bug or would like to suggest an improvement or a - new - feature, please join the - Ghostfolio - Slack community, tweet to - @ghostfolio_, send an e-mail to - hi@ghostfol.io - or start a discussion at - GitHub. -

-

- - - - - - - - - - - - -

-
- -
-
- -
-
-
-
+ + + -
-
- FAQ -
- - -
- Blog -
-
-
+ +
{{ tab.label }}
+ + + diff --git a/apps/client/src/app/pages/about/about-page.module.ts b/apps/client/src/app/pages/about/about-page.module.ts index 05e7a2e30..bd2a1bc80 100644 --- a/apps/client/src/app/pages/about/about-page.module.ts +++ b/apps/client/src/app/pages/about/about-page.module.ts @@ -1,13 +1,14 @@ import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; import { AboutPageRoutingModule } from './about-page-routing.module'; import { AboutPageComponent } from './about-page.component'; @NgModule({ declarations: [AboutPageComponent], - imports: [AboutPageRoutingModule, CommonModule, MatButtonModule], + imports: [CommonModule, MatTabsModule, AboutPageRoutingModule, RouterModule], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class AboutPageModule {} diff --git a/apps/client/src/app/pages/about/about-page.scss b/apps/client/src/app/pages/about/about-page.scss index df6759442..d34bc25c3 100644 --- a/apps/client/src/app/pages/about/about-page.scss +++ b/apps/client/src/app/pages/about/about-page.scss @@ -1,36 +1,35 @@ +@import 'apps/client/src/styles/ghostfolio-style'; + :host { color: rgb(var(--dark-primary-text)); - display: block; + display: flex; + flex-direction: column; + height: calc(100vh - 5rem); + overflow-y: auto; - .about-container { - a { - color: rgba(var(--palette-primary-500), 1); - font-weight: 500; + padding-bottom: env(safe-area-inset-bottom); + padding-bottom: constant(safe-area-inset-bottom); - &:hover { - color: rgba(var(--palette-primary-300), 1); - } + ::ng-deep { + gf-about-page, + gf-changelog-page, + gf-privacy-policy-page { + flex: 1 1 auto; + overflow-y: auto; } - .independent-and-bootstrapped-logo { - background-image: url('/assets/bootstrapped-dark.svg'); - background-position: center; - background-repeat: no-repeat; - background-size: contain; - height: 2rem; - opacity: 0.87; - width: 10rem; + .mat-mdc-tab-link-container { + --mdc-tab-indicator-active-indicator-color: transparent; + + .mat-mdc-tab-link { + &:hover { + opacity: 0.75; + } + } } } } :host-context(.is-dark-theme) { color: rgb(var(--light-primary-text)); - - .about-container { - .independent-and-bootstrapped-logo { - background-image: url('/assets/bootstrapped-light.svg'); - opacity: 1; - } - } } diff --git a/apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts b/apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts new file mode 100644 index 000000000..7713f3971 --- /dev/null +++ b/apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; + +import { AboutOverviewPageComponent } from './about-overview-page.component'; + +const routes: Routes = [ + { + canActivate: [AuthGuard], + component: AboutOverviewPageComponent, + path: '', + title: $localize`About` + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AboutOverviewPageRoutingModule {} diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.component.ts b/apps/client/src/app/pages/about/overview/about-overview-page.component.ts new file mode 100644 index 000000000..abc68d028 --- /dev/null +++ b/apps/client/src/app/pages/about/overview/about-overview-page.component.ts @@ -0,0 +1,61 @@ +import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { environment } from '@ghostfolio/client/../environments/environment'; +import { DataService } from '@ghostfolio/client/services/data.service'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; +import { User } from '@ghostfolio/common/interfaces'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + host: { class: 'page' }, + selector: 'gf-about-overview-page', + styleUrls: ['./about-overview-page.scss'], + templateUrl: './about-overview-page.html' +}) +export class AboutOverviewPageComponent implements OnDestroy, OnInit { + public defaultLanguageCode = DEFAULT_LANGUAGE_CODE; + public hasPermissionForBlog: boolean; + public hasPermissionForSubscription: boolean; + public isLoggedIn: boolean; + public user: User; + public version = environment.version; + + private unsubscribeSubject = new Subject(); + + public constructor( + private changeDetectorRef: ChangeDetectorRef, + private dataService: DataService, + private userService: UserService + ) { + const { globalPermissions } = this.dataService.fetchInfo(); + + this.hasPermissionForBlog = hasPermission( + globalPermissions, + permissions.enableBlog + ); + + this.hasPermissionForSubscription = hasPermission( + globalPermissions, + permissions.enableSubscription + ); + } + + public ngOnInit() { + this.userService.stateChanged + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((state) => { + if (state?.user) { + this.user = state.user; + + this.changeDetectorRef.markForCheck(); + } + }); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } +} diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.html b/apps/client/src/app/pages/about/overview/about-overview-page.html new file mode 100644 index 000000000..0b1d0f090 --- /dev/null +++ b/apps/client/src/app/pages/about/overview/about-overview-page.html @@ -0,0 +1,157 @@ +
+
+
+

About Ghostfolio

+
+

+ Ghostfolio is a lightweight wealth management application for + individuals to keep track of stocks, ETFs or cryptocurrencies and make + solid, data-driven investment decisions. The source code is fully + available as + open source software + (OSS) under the + AGPL-3.0 license + and we share aggregated + key metrics + of the platform’s performance. The project has been initiated by + Thomas Kaul + and is driven by the efforts of its + contributors. + + This instance is running Ghostfolio {{ version }}. + + Check the system status at + status.ghostfol.io. +

+

+ If you encounter a bug or would like to suggest an improvement or a + new + feature, please join the + Ghostfolio + Slack community, tweet to + @ghostfolio_, send an e-mail to + hi@ghostfol.io + or start a discussion at + GitHub. +

+

+ + + + + + + + + + + + +

+
+ +
+
+ +
+
+
+
+ + +
diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.module.ts b/apps/client/src/app/pages/about/overview/about-overview-page.module.ts new file mode 100644 index 000000000..75fcdb8fd --- /dev/null +++ b/apps/client/src/app/pages/about/overview/about-overview-page.module.ts @@ -0,0 +1,13 @@ +import { CommonModule } from '@angular/common'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; + +import { AboutOverviewPageRoutingModule } from './about-overview-page-routing.module'; +import { AboutOverviewPageComponent } from './about-overview-page.component'; + +@NgModule({ + declarations: [AboutOverviewPageComponent], + imports: [AboutOverviewPageRoutingModule, CommonModule, MatButtonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class AboutOverviewPageModule {} diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.scss b/apps/client/src/app/pages/about/overview/about-overview-page.scss new file mode 100644 index 000000000..df6759442 --- /dev/null +++ b/apps/client/src/app/pages/about/overview/about-overview-page.scss @@ -0,0 +1,36 @@ +:host { + color: rgb(var(--dark-primary-text)); + display: block; + + .about-container { + a { + color: rgba(var(--palette-primary-500), 1); + font-weight: 500; + + &:hover { + color: rgba(var(--palette-primary-300), 1); + } + } + + .independent-and-bootstrapped-logo { + background-image: url('/assets/bootstrapped-dark.svg'); + background-position: center; + background-repeat: no-repeat; + background-size: contain; + height: 2rem; + opacity: 0.87; + width: 10rem; + } + } +} + +:host-context(.is-dark-theme) { + color: rgb(var(--light-primary-text)); + + .about-container { + .independent-and-bootstrapped-logo { + background-image: url('/assets/bootstrapped-light.svg'); + opacity: 1; + } + } +} diff --git a/apps/client/src/app/pages/admin/admin-page.html b/apps/client/src/app/pages/admin/admin-page.html index 8de616498..681a42155 100644 --- a/apps/client/src/app/pages/admin/admin-page.html +++ b/apps/client/src/app/pages/admin/admin-page.html @@ -3,16 +3,17 @@ diff --git a/apps/client/src/app/pages/home/home-page.html b/apps/client/src/app/pages/home/home-page.html index ed3c46bd5..681a42155 100644 --- a/apps/client/src/app/pages/home/home-page.html +++ b/apps/client/src/app/pages/home/home-page.html @@ -3,15 +3,17 @@ diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.html b/apps/client/src/app/pages/portfolio/portfolio-page.html index 8de616498..681a42155 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.html +++ b/apps/client/src/app/pages/portfolio/portfolio-page.html @@ -3,16 +3,17 @@ diff --git a/apps/client/src/app/pages/zen/zen-page.html b/apps/client/src/app/pages/zen/zen-page.html index ed3c46bd5..681a42155 100644 --- a/apps/client/src/app/pages/zen/zen-page.html +++ b/apps/client/src/app/pages/zen/zen-page.html @@ -3,15 +3,17 @@