Browse Source

Enable Bull Dashboard in tab

pull/7030/head
Thomas Kaul 3 months ago
parent
commit
26671fe4bf
  1. 23
      apps/client/src/app/components/admin-jobs/admin-jobs.component.ts
  2. 9
      apps/client/src/app/components/admin-jobs/admin-jobs.html
  3. 63
      apps/client/src/app/pages/admin/admin-page.component.ts
  4. 9
      libs/ui/src/lib/page-tabs/interfaces/interfaces.ts
  5. 44
      libs/ui/src/lib/page-tabs/page-tabs.component.html
  6. 3
      libs/ui/src/lib/page-tabs/page-tabs.component.ts

23
apps/client/src/app/components/admin-jobs/admin-jobs.component.ts

@ -1,8 +1,5 @@
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UserService } from '@ghostfolio/client/services/user/user.service';
import { import {
BULL_BOARD_COOKIE_NAME,
BULL_BOARD_ROUTE,
DATA_GATHERING_QUEUE_PRIORITY_HIGH, DATA_GATHERING_QUEUE_PRIORITY_HIGH,
DATA_GATHERING_QUEUE_PRIORITY_LOW, DATA_GATHERING_QUEUE_PRIORITY_LOW,
DATA_GATHERING_QUEUE_PRIORITY_MEDIUM, DATA_GATHERING_QUEUE_PRIORITY_MEDIUM,
@ -10,7 +7,6 @@ import {
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { getDateWithTimeFormatString } from '@ghostfolio/common/helper'; import { getDateWithTimeFormatString } from '@ghostfolio/common/helper';
import { AdminJobs, User } from '@ghostfolio/common/interfaces'; import { AdminJobs, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { NotificationService } from '@ghostfolio/ui/notifications'; import { NotificationService } from '@ghostfolio/ui/notifications';
import { AdminService } from '@ghostfolio/ui/services'; import { AdminService } from '@ghostfolio/ui/services';
@ -106,7 +102,6 @@ export class GfAdminJobsComponent implements OnInit {
'actions' 'actions'
]; ];
protected hasPermissionToAccessBullBoard = false;
protected isLoading = false; protected isLoading = false;
protected readonly statusFilterOptions = QUEUE_JOB_STATUS_LIST; protected readonly statusFilterOptions = QUEUE_JOB_STATUS_LIST;
@ -116,7 +111,6 @@ export class GfAdminJobsComponent implements OnInit {
private readonly changeDetectorRef = inject(ChangeDetectorRef); private readonly changeDetectorRef = inject(ChangeDetectorRef);
private readonly destroyRef = inject(DestroyRef); private readonly destroyRef = inject(DestroyRef);
private readonly notificationService = inject(NotificationService); private readonly notificationService = inject(NotificationService);
private readonly tokenStorageService = inject(TokenStorageService);
private readonly userService = inject(UserService); private readonly userService = inject(UserService);
public constructor() { public constructor() {
@ -129,11 +123,6 @@ export class GfAdminJobsComponent implements OnInit {
this.defaultDateTimeFormat = getDateWithTimeFormatString( this.defaultDateTimeFormat = getDateWithTimeFormatString(
this.user.settings.locale this.user.settings.locale
); );
this.hasPermissionToAccessBullBoard = hasPermission(
this.user.permissions,
permissions.accessAdminControlBullBoard
);
} }
}); });
@ -193,18 +182,6 @@ export class GfAdminJobsComponent implements OnInit {
}); });
} }
protected onOpenBullBoard() {
const token = this.tokenStorageService.getToken();
document.cookie = [
`${BULL_BOARD_COOKIE_NAME}=${encodeURIComponent(token)}`,
'path=/',
'SameSite=Strict'
].join('; ');
window.open(BULL_BOARD_ROUTE, '_blank');
}
protected onViewData(aData: AdminJobs['jobs'][0]['data']) { protected onViewData(aData: AdminJobs['jobs'][0]['data']) {
this.notificationService.alert({ this.notificationService.alert({
title: JSON.stringify(aData, null, ' ') title: JSON.stringify(aData, null, ' ')

9
apps/client/src/app/components/admin-jobs/admin-jobs.html

@ -1,15 +1,6 @@
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
@if (hasPermissionToAccessBullBoard) {
<div class="d-flex justify-content-end mb-3">
<button mat-stroked-button (click)="onOpenBullBoard()">
<span><ng-container i18n>Overview</ng-container></span>
<ion-icon class="ml-2" name="open-outline" />
</button>
</div>
}
<form class="align-items-center d-flex" [formGroup]="filterForm"> <form class="align-items-center d-flex" [formGroup]="filterForm">
<mat-form-field appearance="outline" class="w-100 without-hint"> <mat-form-field appearance="outline" class="w-100 without-hint">
<mat-select formControlName="status"> <mat-select formControlName="status">

63
apps/client/src/app/pages/admin/admin-page.component.ts

@ -1,10 +1,19 @@
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import {
BULL_BOARD_COOKIE_NAME,
BULL_BOARD_ROUTE
} from '@ghostfolio/common/config';
import { User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { internalRoutes } from '@ghostfolio/common/routes/routes';
import { import {
GfPageTabsComponent, GfPageTabsComponent,
TabConfiguration TabConfiguration
} from '@ghostfolio/ui/page-tabs'; } from '@ghostfolio/ui/page-tabs';
import { Component, OnInit } from '@angular/core'; import { Component, inject, OnInit } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { addIcons } from 'ionicons'; import { addIcons } from 'ionicons';
import { import {
flashOutline, flashOutline,
@ -24,7 +33,20 @@ import {
export class AdminPageComponent implements OnInit { export class AdminPageComponent implements OnInit {
public tabs: TabConfiguration[] = []; public tabs: TabConfiguration[] = [];
private user: User;
private readonly tokenStorageService = inject(TokenStorageService);
private readonly userService = inject(UserService);
public constructor() { public constructor() {
this.userService.stateChanged
.pipe(takeUntilDestroyed())
.subscribe((state) => {
this.user = state?.user;
this.initializeTabs();
});
addIcons({ addIcons({
flashOutline, flashOutline,
peopleOutline, peopleOutline,
@ -35,6 +57,15 @@ export class AdminPageComponent implements OnInit {
} }
public ngOnInit() { public ngOnInit() {
this.initializeTabs();
}
private initializeTabs() {
const hasPermissionToAccessBullBoard = hasPermission(
this.user?.permissions,
permissions.accessAdminControlBullBoard
);
this.tabs = [ this.tabs = [
{ {
iconName: 'reader-outline', iconName: 'reader-outline',
@ -51,11 +82,19 @@ export class AdminPageComponent implements OnInit {
label: internalRoutes.adminControl.subRoutes.marketData.title, label: internalRoutes.adminControl.subRoutes.marketData.title,
routerLink: internalRoutes.adminControl.subRoutes.marketData.routerLink routerLink: internalRoutes.adminControl.subRoutes.marketData.routerLink
}, },
{ hasPermissionToAccessBullBoard
iconName: 'flash-outline', ? {
label: internalRoutes.adminControl.subRoutes.jobs.title, iconName: 'flash-outline',
routerLink: internalRoutes.adminControl.subRoutes.jobs.routerLink label: $localize`Job Queue`,
}, onClick: () => {
this.onOpenBullBoard();
}
}
: {
iconName: 'flash-outline',
label: internalRoutes.adminControl.subRoutes.jobs.title,
routerLink: internalRoutes.adminControl.subRoutes.jobs.routerLink
},
{ {
iconName: 'people-outline', iconName: 'people-outline',
label: internalRoutes.adminControl.subRoutes.users.title, label: internalRoutes.adminControl.subRoutes.users.title,
@ -63,4 +102,16 @@ export class AdminPageComponent implements OnInit {
} }
]; ];
} }
private onOpenBullBoard() {
const token = this.tokenStorageService.getToken();
document.cookie = [
`${BULL_BOARD_COOKIE_NAME}=${encodeURIComponent(token)}`,
'path=/',
'SameSite=Strict'
].join('; ');
window.open(BULL_BOARD_ROUTE, '_blank');
}
} }

9
libs/ui/src/lib/page-tabs/interfaces/interfaces.ts

@ -1,6 +1,11 @@
export interface TabConfiguration { interface BaseTabConfiguration {
iconName: string; iconName: string;
label: string; label: string;
routerLink: string[];
showCondition?: boolean; showCondition?: boolean;
} }
export type TabConfiguration = BaseTabConfiguration &
(
| { onClick: () => void; routerLink?: never }
| { onClick?: never; routerLink: string[] }
);

44
libs/ui/src/lib/page-tabs/page-tabs.component.html

@ -10,21 +10,35 @@
> >
@for (tab of tabs(); track tab) { @for (tab of tabs(); track tab) {
@if (tab.showCondition !== false) { @if (tab.showCondition !== false) {
<a @if (tab.onClick) {
#rla="routerLinkActive" <a class="no-min-width px-3" mat-tab-link (click)="tab.onClick()">
class="no-min-width px-3" <ng-container
mat-tab-link *ngTemplateOutlet="tabContent; context: { $implicit: tab }"
routerLinkActive />
[active]="rla.isActive" </a>
[routerLink]="tab.routerLink" } @else {
[routerLinkActiveOptions]="{ exact: true }" <a
> #rla="routerLinkActive"
<ion-icon class="no-min-width px-3"
[name]="tab.iconName" mat-tab-link
[size]="deviceType === 'mobile' ? 'large' : 'small'" routerLinkActive
/> [active]="rla.isActive"
<div class="d-none d-sm-block ml-2" [innerHTML]="tab.label"></div> [routerLink]="tab.routerLink"
</a> [routerLinkActiveOptions]="{ exact: true }"
>
<ng-container
*ngTemplateOutlet="tabContent; context: { $implicit: tab }"
/>
</a>
}
} }
} }
</nav> </nav>
<ng-template #tabContent let-tab>
<ion-icon
[name]="tab.iconName"
[size]="deviceType === 'mobile' ? 'large' : 'small'"
/>
<div class="d-none d-sm-block ml-2" [innerHTML]="tab.label"></div>
</ng-template>

3
libs/ui/src/lib/page-tabs/page-tabs.component.ts

@ -1,3 +1,4 @@
import { NgTemplateOutlet } from '@angular/common';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
@ -13,7 +14,7 @@ import { TabConfiguration } from './interfaces/interfaces';
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [IonIcon, MatTabsModule, RouterModule], imports: [IonIcon, MatTabsModule, NgTemplateOutlet, RouterModule],
selector: 'gf-page-tabs', selector: 'gf-page-tabs',
styleUrls: ['./page-tabs.component.scss'], styleUrls: ['./page-tabs.component.scss'],
templateUrl: './page-tabs.component.html' templateUrl: './page-tabs.component.html'

Loading…
Cancel
Save