diff --git a/apps/client/src/app/components/platform/platform.component.html b/apps/client/src/app/components/platform/platform.component.html
new file mode 100644
index 000000000..4e8e0e8b9
--- /dev/null
+++ b/apps/client/src/app/components/platform/platform.component.html
@@ -0,0 +1,75 @@
+
diff --git a/apps/client/src/app/components/platform/platform.component.scss b/apps/client/src/app/components/platform/platform.component.scss
new file mode 100644
index 000000000..0fd1e7bb1
--- /dev/null
+++ b/apps/client/src/app/components/platform/platform.component.scss
@@ -0,0 +1,14 @@
+:host {
+ display: block;
+
+ .platforms {
+ overflow-x: auto;
+ }
+
+ .fab-container {
+ position: fixed;
+ right: 2rem;
+ bottom: 4rem;
+ z-index: 999;
+ }
+}
diff --git a/apps/client/src/app/components/platform/platform.component.ts b/apps/client/src/app/components/platform/platform.component.ts
new file mode 100644
index 000000000..4dc2befe3
--- /dev/null
+++ b/apps/client/src/app/components/platform/platform.component.ts
@@ -0,0 +1,97 @@
+import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
+import { MatSort } from '@angular/material/sort';
+import { MatTableDataSource } from '@angular/material/table';
+import { ActivatedRoute, Router } from '@angular/router';
+import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
+import { UserService } from '@ghostfolio/client/services/user/user.service';
+import { User } from '@ghostfolio/common/interfaces';
+import { AdminPlatformsItem } from '@ghostfolio/common/interfaces/admin-platforms.interface';
+
+import { hasPermission, permissions } from '@ghostfolio/common/permissions';
+import { Platform as PlatformModel } from '@prisma/client';
+import { Subject, takeUntil } from 'rxjs';
+
+@Component({
+ selector: 'gf-platform-overview',
+ styleUrls: ['./platform.component.scss'],
+ templateUrl: './platform.component.html'
+})
+export class AdminPlatformComponent implements OnInit {
+ @ViewChild(MatSort) sort: MatSort;
+
+ public displayedColumns = ['id', 'name', 'url'];
+
+ public platforms: PlatformModel[];
+ public hasPermissionToCreatePlatform: boolean;
+ public hasPermissionToDeletePlatform: boolean;
+ public hasImpersonationId: boolean;
+ public user: User;
+
+ public dataSource: MatTableDataSource =
+ new MatTableDataSource();
+
+ private unsubscribeSubject = new Subject();
+
+ public constructor(
+ private changeDetectorRef: ChangeDetectorRef,
+ private userService: UserService,
+ private impersonationStorageService: ImpersonationStorageService,
+ private route: ActivatedRoute,
+ private router: Router
+ ) {
+ this.route.queryParams
+ .pipe(takeUntil(this.unsubscribeSubject))
+ .subscribe((params) => {
+ if (params['platformId'] && params['platformDetailDialog']) {
+ // this.openAccountDetailDialog(params['accountId']);
+ } else if (
+ params['createDialog'] &&
+ this.hasPermissionToCreatePlatform
+ ) {
+ //this.openCreateAccountDialog();
+ } else if (params['editDialog']) {
+ if (this.platforms) {
+ const platform = this.platforms.find(({ id }) => {
+ return id === params['platformId'];
+ });
+
+ // this.openUpdateAccountDialog(account);
+ } else {
+ this.router.navigate(['.'], { relativeTo: this.route });
+ }
+ }
+ });
+ }
+
+ public ngOnInit() {
+ this.impersonationStorageService
+ .onChangeHasImpersonation()
+ .pipe(takeUntil(this.unsubscribeSubject))
+ .subscribe((impersonationId) => {
+ this.hasImpersonationId = !!impersonationId;
+ });
+
+ this.userService.stateChanged
+ .pipe(takeUntil(this.unsubscribeSubject))
+ .subscribe((state) => {
+ if (state?.user) {
+ this.user = state.user;
+
+ this.hasPermissionToCreatePlatform = hasPermission(
+ this.user.permissions,
+ permissions.createPlatform
+ );
+ this.hasPermissionToCreatePlatform = hasPermission(
+ this.user.permissions,
+ permissions.deletePlatform
+ );
+
+ this.changeDetectorRef.markForCheck();
+ }
+ });
+
+ this.fetchPlatforms();
+ }
+
+ private fetchPlatforms() {}
+}
diff --git a/apps/client/src/app/components/platform/platform.module.ts b/apps/client/src/app/components/platform/platform.module.ts
new file mode 100644
index 000000000..0d33213d2
--- /dev/null
+++ b/apps/client/src/app/components/platform/platform.module.ts
@@ -0,0 +1,20 @@
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
+import { AdminPlatformComponent } from './platform.component';
+import { CommonModule } from '@angular/common';
+import { RouterModule } from '@angular/router';
+import { MatButtonModule } from '@angular/material/button';
+import { MatSortModule } from '@angular/material/sort';
+import { MatTableModule } from '@angular/material/table';
+
+@NgModule({
+ declarations: [AdminPlatformComponent],
+ imports: [
+ CommonModule,
+ RouterModule,
+ MatButtonModule,
+ MatSortModule,
+ MatTableModule
+ ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
+})
+export class GfAdminPlatformModule {}
diff --git a/apps/client/src/app/pages/admin/admin-page-routing.module.ts b/apps/client/src/app/pages/admin/admin-page-routing.module.ts
index 49ce08ad3..28cd84617 100644
--- a/apps/client/src/app/pages/admin/admin-page-routing.module.ts
+++ b/apps/client/src/app/pages/admin/admin-page-routing.module.ts
@@ -4,6 +4,7 @@ import { AdminJobsComponent } from '@ghostfolio/client/components/admin-jobs/adm
import { AdminMarketDataComponent } from '@ghostfolio/client/components/admin-market-data/admin-market-data.component';
import { AdminOverviewComponent } from '@ghostfolio/client/components/admin-overview/admin-overview.component';
import { AdminUsersComponent } from '@ghostfolio/client/components/admin-users/admin-users.component';
+import { AdminPlatformComponent } from '@ghostfolio/client/components/platform/platform.component';
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { AdminPageComponent } from './admin-page.component';
@@ -24,7 +25,16 @@ const routes: Routes = [
component: AdminOverviewComponent,
title: $localize`Admin Control`
},
- { path: 'users', component: AdminUsersComponent, title: $localize`Users` }
+ {
+ path: 'users',
+ component: AdminUsersComponent,
+ title: $localize`Users`
+ },
+ {
+ path: 'platforms',
+ component: AdminPlatformComponent,
+ title: $localize`Platforms`
+ }
],
component: AdminPageComponent,
path: ''
diff --git a/apps/client/src/app/pages/admin/admin-page.component.ts b/apps/client/src/app/pages/admin/admin-page.component.ts
index 231dc068c..912c49077 100644
--- a/apps/client/src/app/pages/admin/admin-page.component.ts
+++ b/apps/client/src/app/pages/admin/admin-page.component.ts
@@ -31,6 +31,11 @@ export class AdminPageComponent implements OnDestroy, OnInit {
path: 'overview'
},
{ iconName: 'people-outline', label: $localize`Users`, path: 'users' },
+ {
+ iconName: 'briefcase-outline',
+ label: $localize`Platforms`,
+ path: 'platforms'
+ },
{
iconName: 'server-outline',
label: $localize`Market Data`,
diff --git a/apps/client/src/app/pages/admin/admin-page.module.ts b/apps/client/src/app/pages/admin/admin-page.module.ts
index fa7f0e35b..ab0c80970 100644
--- a/apps/client/src/app/pages/admin/admin-page.module.ts
+++ b/apps/client/src/app/pages/admin/admin-page.module.ts
@@ -5,6 +5,7 @@ import { GfAdminJobsModule } from '@ghostfolio/client/components/admin-jobs/admi
import { GfAdminMarketDataModule } from '@ghostfolio/client/components/admin-market-data/admin-market-data.module';
import { GfAdminOverviewModule } from '@ghostfolio/client/components/admin-overview/admin-overview.module';
import { GfAdminUsersModule } from '@ghostfolio/client/components/admin-users/admin-users.module';
+import { GfAdminPlatformModule } from '@ghostfolio/client/components/platform/platform.module';
import { CacheService } from '@ghostfolio/client/services/cache.service';
import { AdminPageRoutingModule } from './admin-page-routing.module';
@@ -20,6 +21,7 @@ import { AdminPageComponent } from './admin-page.component';
GfAdminMarketDataModule,
GfAdminOverviewModule,
GfAdminUsersModule,
+ GfAdminPlatformModule,
MatTabsModule
],
providers: [CacheService],
diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf
index 7d52a1951..afc2b59a4 100644
--- a/apps/client/src/locales/messages.de.xlf
+++ b/apps/client/src/locales/messages.de.xlf
@@ -878,7 +878,7 @@
oder
apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html
- 20,19
+ 19
apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html
@@ -886,7 +886,7 @@
apps/client/src/app/pages/register/register-page.html
- 30,29
+ 29
apps/client/src/app/pages/webauthn/webauthn-page.html
@@ -1302,7 +1302,7 @@
apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html
- 193,192
+ 192
apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html
@@ -1654,7 +1654,7 @@
Administration
apps/client/src/app/pages/admin/admin-page-routing.module.ts
- 25
+ 26
@@ -1750,7 +1750,7 @@
Nach Konto
apps/client/src/app/pages/portfolio/allocations/allocations-page.html
- 41
+ 256
@@ -2574,7 +2574,7 @@
Filtern nach Konto oder Tag...
apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
- 133
+ 139
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
@@ -3078,11 +3078,11 @@
Jobs
apps/client/src/app/pages/admin/admin-page-routing.module.ts
- 16
+ 17
apps/client/src/app/pages/admin/admin-page.component.ts
- 39
+ 44
@@ -3090,11 +3090,11 @@
Marktdaten
apps/client/src/app/pages/admin/admin-page-routing.module.ts
- 20
+ 21
apps/client/src/app/pages/admin/admin-page.component.ts
- 36
+ 41
@@ -3102,7 +3102,7 @@
Benutzer
apps/client/src/app/pages/admin/admin-page-routing.module.ts
- 27
+ 31
apps/client/src/app/pages/admin/admin-page.component.ts
@@ -3666,7 +3666,7 @@
Nach ETF-Anbieter
apps/client/src/app/pages/portfolio/allocations/allocations-page.html
- 257
+ 276
@@ -3677,6 +3677,26 @@
62
+
+ Platforms
+ Platforms
+
+ apps/client/src/app/pages/admin/admin-page-routing.module.ts
+ 36
+
+
+ apps/client/src/app/pages/admin/admin-page.component.ts
+ 36
+
+
+
+ By Platform
+ By Platform
+
+ apps/client/src/app/pages/portfolio/allocations/allocations-page.html
+ 42
+
+