mirror of
https://github.com/apache/nifi.git
synced 2025-02-07 18:48:51 +00:00
NIFI-12597: Introducing a common navigation bar across all pages (#8237)
* NIFI-12597: - Introducing a common navigation bar across all pages. * NIFI-12597: - Introducing navigation bar to queue listing. This closes #8237
This commit is contained in:
parent
da7c9bcddb
commit
7c09aabb4a
@ -15,14 +15,14 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-between">
|
<header class="nifi-header">
|
||||||
|
<navigation></navigation>
|
||||||
|
</header>
|
||||||
|
<div class="px-5">
|
||||||
<h3 class="text-xl bold access-policies-header">Access Policies</h3>
|
<h3 class="text-xl bold access-policies-header">Access Policies</h3>
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1">
|
<div class="px-5 flex-1">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,15 +21,23 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { provideMockStore } from '@ngrx/store/testing';
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { initialState } from '../state/access-policy/access-policy.reducer';
|
import { initialState } from '../state/access-policy/access-policy.reducer';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
describe('AccessPolicies', () => {
|
describe('AccessPolicies', () => {
|
||||||
let component: AccessPolicies;
|
let component: AccessPolicies;
|
||||||
let fixture: ComponentFixture<AccessPolicies>;
|
let fixture: ComponentFixture<AccessPolicies>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [AccessPolicies],
|
declarations: [AccessPolicies],
|
||||||
imports: [RouterModule, RouterTestingModule],
|
imports: [RouterModule, RouterTestingModule, MockNavigation],
|
||||||
providers: [
|
providers: [
|
||||||
provideMockStore({
|
provideMockStore({
|
||||||
initialState
|
initialState
|
||||||
|
@ -26,6 +26,7 @@ import { MatDialogModule } from '@angular/material/dialog';
|
|||||||
import { AccessPolicyEffects } from '../state/access-policy/access-policy.effects';
|
import { AccessPolicyEffects } from '../state/access-policy/access-policy.effects';
|
||||||
import { TenantsEffects } from '../state/tenants/tenants.effects';
|
import { TenantsEffects } from '../state/tenants/tenants.effects';
|
||||||
import { PolicyComponentEffects } from '../state/policy-component/policy-component.effects';
|
import { PolicyComponentEffects } from '../state/policy-component/policy-component.effects';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AccessPolicies],
|
declarations: [AccessPolicies],
|
||||||
@ -35,7 +36,8 @@ import { PolicyComponentEffects } from '../state/policy-component/policy-compone
|
|||||||
AccessPoliciesRoutingModule,
|
AccessPoliciesRoutingModule,
|
||||||
StoreModule.forFeature(accessPoliciesFeatureKey, reducers),
|
StoreModule.forFeature(accessPoliciesFeatureKey, reducers),
|
||||||
EffectsModule.forFeature(AccessPolicyEffects, TenantsEffects, PolicyComponentEffects),
|
EffectsModule.forFeature(AccessPolicyEffects, TenantsEffects, PolicyComponentEffects),
|
||||||
MatDialogModule
|
MatDialogModule,
|
||||||
|
Navigation
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AccessPoliciesModule {}
|
export class AccessPoliciesModule {}
|
||||||
|
@ -15,14 +15,12 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-between">
|
<header class="nifi-header">
|
||||||
|
<navigation></navigation>
|
||||||
|
</header>
|
||||||
|
<div class="px-5 flex-1 flex flex-col">
|
||||||
<h3 class="text-xl bold bulletin-board-header">NiFi Bulletin Board</h3>
|
<h3 class="text-xl bold bulletin-board-header">NiFi Bulletin Board</h3>
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
<bulletin-board class="flex-1"></bulletin-board>
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<bulletin-board></bulletin-board>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,6 +25,7 @@ import { BulletinBoardEffects } from '../state/bulletin-board/bulletin-board.eff
|
|||||||
import { BulletinsRoutingModule } from './bulletins-routing.module';
|
import { BulletinsRoutingModule } from './bulletins-routing.module';
|
||||||
import { CounterListingModule } from '../../counters/ui/counter-listing/counter-listing.module';
|
import { CounterListingModule } from '../../counters/ui/counter-listing/counter-listing.module';
|
||||||
import { BulletinBoard } from '../ui/bulletin-board/bulletin-board.component';
|
import { BulletinBoard } from '../ui/bulletin-board/bulletin-board.component';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [Bulletins],
|
declarations: [Bulletins],
|
||||||
@ -35,7 +36,8 @@ import { BulletinBoard } from '../ui/bulletin-board/bulletin-board.component';
|
|||||||
StoreModule.forFeature(bulletinsFeatureKey, reducers),
|
StoreModule.forFeature(bulletinsFeatureKey, reducers),
|
||||||
EffectsModule.forFeature(BulletinBoardEffects),
|
EffectsModule.forFeature(BulletinBoardEffects),
|
||||||
CounterListingModule,
|
CounterListingModule,
|
||||||
BulletinBoard
|
BulletinBoard,
|
||||||
|
Navigation
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class BulletinsModule {}
|
export class BulletinsModule {}
|
||||||
|
@ -15,14 +15,12 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-between">
|
<header class="nifi-header">
|
||||||
|
<navigation></navigation>
|
||||||
|
</header>
|
||||||
|
<div class="px-5 flex-1 flex flex-col">
|
||||||
<h3 class="text-xl bold counter-header">NiFi Counters</h3>
|
<h3 class="text-xl bold counter-header">NiFi Counters</h3>
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
<counter-listing class="flex-1"></counter-listing>
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<counter-listing></counter-listing>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,15 +22,23 @@ import { initialState } from '../state/counter-listing/counter-listing.reducer';
|
|||||||
import { CounterListing } from '../ui/counter-listing/counter-listing.component';
|
import { CounterListing } from '../ui/counter-listing/counter-listing.component';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
describe('Counters', () => {
|
describe('Counters', () => {
|
||||||
let component: Counters;
|
let component: Counters;
|
||||||
let fixture: ComponentFixture<Counters>;
|
let fixture: ComponentFixture<Counters>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [Counters, CounterListing],
|
declarations: [Counters, CounterListing],
|
||||||
imports: [RouterModule, RouterTestingModule],
|
imports: [RouterModule, RouterTestingModule, MockNavigation],
|
||||||
providers: [provideMockStore({ initialState })]
|
providers: [provideMockStore({ initialState })]
|
||||||
});
|
});
|
||||||
fixture = TestBed.createComponent(Counters);
|
fixture = TestBed.createComponent(Counters);
|
||||||
|
@ -25,6 +25,7 @@ import { EffectsModule } from '@ngrx/effects';
|
|||||||
import { CounterListingEffects } from '../state/counter-listing/counter-listing.effects';
|
import { CounterListingEffects } from '../state/counter-listing/counter-listing.effects';
|
||||||
import { CounterListingModule } from '../ui/counter-listing/counter-listing.module';
|
import { CounterListingModule } from '../ui/counter-listing/counter-listing.module';
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [Counters],
|
declarations: [Counters],
|
||||||
@ -35,7 +36,8 @@ import { MatDialogModule } from '@angular/material/dialog';
|
|||||||
StoreModule.forFeature(countersFeatureKey, reducers),
|
StoreModule.forFeature(countersFeatureKey, reducers),
|
||||||
EffectsModule.forFeature(CounterListingEffects),
|
EffectsModule.forFeature(CounterListingEffects),
|
||||||
CounterListingModule,
|
CounterListingModule,
|
||||||
MatDialogModule
|
MatDialogModule,
|
||||||
|
Navigation
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class CountersModule {}
|
export class CountersModule {}
|
||||||
|
@ -18,9 +18,6 @@
|
|||||||
.flow-status {
|
.flow-status {
|
||||||
border-bottom: 1px solid #aabbc3;
|
border-bottom: 1px solid #aabbc3;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25);
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
|
||||||
.fa,
|
.fa,
|
||||||
|
@ -15,13 +15,8 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<header>
|
<header class="nifi-header">
|
||||||
<nav class="bg-nifi-primary nifi-header">
|
<navigation>
|
||||||
<div class="flex justify-between items-center h-16 pl-4">
|
|
||||||
<div class="flex">
|
|
||||||
<div class="h-16 w-28 mr-6 relative">
|
|
||||||
<img ngSrc="assets/icons/nifi-logo.svg" fill priority alt="NiFi Logo" />
|
|
||||||
</div>
|
|
||||||
<new-canvas-item
|
<new-canvas-item
|
||||||
[type]="ComponentType.Processor"
|
[type]="ComponentType.Processor"
|
||||||
iconClass="icon-processor"
|
iconClass="icon-processor"
|
||||||
@ -50,116 +45,7 @@
|
|||||||
[type]="ComponentType.Label"
|
[type]="ComponentType.Label"
|
||||||
iconClass="icon-label"
|
iconClass="icon-label"
|
||||||
iconHoverClass="icon-label-add"></new-canvas-item>
|
iconHoverClass="icon-label-add"></new-canvas-item>
|
||||||
</div>
|
</navigation>
|
||||||
<div class="flex justify-between items-center gap-x-1" *ngIf="currentUser$ | async as user">
|
|
||||||
<div class="flex flex-col justify-between items-end gap-y-1">
|
|
||||||
<div class="current-user">{{ user.identity }}</div>
|
|
||||||
<a href="#" *ngIf="allowLogin(user)">log in</a>
|
|
||||||
<a (click)="logout()" *ngIf="hasToken()">log out</a>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
[matMenuTriggerFor]="globalMenu"
|
|
||||||
class="h-16 w-16 flex items-center justify-center icon global-menu">
|
|
||||||
<i class="fa fa-navicon"></i>
|
|
||||||
</button>
|
|
||||||
<mat-menu #globalMenu="matMenu" xPosition="before">
|
|
||||||
<button mat-menu-item class="global-menu-item" [routerLink]="['/summary']">
|
|
||||||
<i class="fa fa-fw fa-table mr-2"></i>
|
|
||||||
Summary
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
class="global-menu-item"
|
|
||||||
[routerLink]="['/counters']"
|
|
||||||
[disabled]="!user.countersPermissions.canRead">
|
|
||||||
<i class="icon fa-fw icon-counter mr-2"></i>
|
|
||||||
Counter
|
|
||||||
</button>
|
|
||||||
<button mat-menu-item class="global-menu-item" [routerLink]="['/bulletins']">
|
|
||||||
<i class="fa fa-fw fa-sticky-note-o mr-2"></i>
|
|
||||||
Bulletin Board
|
|
||||||
</button>
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
class="global-menu-item"
|
|
||||||
[routerLink]="['/provenance']"
|
|
||||||
[disabled]="!user.provenancePermissions.canRead">
|
|
||||||
<i class="icon fa-fw icon-provenance mr-2"></i>
|
|
||||||
Data Provenance
|
|
||||||
</button>
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
class="global-menu-item"
|
|
||||||
[routerLink]="['/settings']"
|
|
||||||
[disabled]="!user.controllerPermissions.canRead">
|
|
||||||
<i class="fa fa-fw fa-wrench mr-2"></i>
|
|
||||||
Controller Settings
|
|
||||||
</button>
|
|
||||||
<button mat-menu-item class="global-menu-item" [routerLink]="['/parameter-contexts']">
|
|
||||||
<i class="fa fa-fw mr-2"></i>
|
|
||||||
Parameter Contexts
|
|
||||||
</button>
|
|
||||||
<button mat-menu-item class="global-menu-item">
|
|
||||||
<i class="fa fa-fw fa-cubes mr-2"></i>
|
|
||||||
Cluster
|
|
||||||
</button>
|
|
||||||
<button mat-menu-item class="global-menu-item">
|
|
||||||
<i class="fa fa-fw fa-history mr-2"></i>
|
|
||||||
Flow Configuration History
|
|
||||||
</button>
|
|
||||||
<button mat-menu-item class="global-menu-item" (click)="viewNodeStatusHistory()">
|
|
||||||
<i class="fa fa-fw fa-area-chart mr-2"></i>
|
|
||||||
Node Status History
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
class="global-menu-item"
|
|
||||||
[disabled]="!user.systemPermissions.canRead"
|
|
||||||
(click)="viewSystemDiagnostics()">
|
|
||||||
<i class="fa fa-fw mr-2"></i>
|
|
||||||
System Diagnostics
|
|
||||||
</button>
|
|
||||||
<ng-container *ngIf="flowConfiguration$ | async as flowConfiguration">
|
|
||||||
<ng-container *ngIf="flowConfiguration.supportsManagedAuthorizer">
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
class="global-menu-item"
|
|
||||||
[routerLink]="['/users']"
|
|
||||||
[disabled]="!user.tenantsPermissions.canRead">
|
|
||||||
<i class="fa fa-fw fa-users mr-2"></i>
|
|
||||||
Users
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
class="global-menu-item"
|
|
||||||
[routerLink]="['/access-policies', 'global']"
|
|
||||||
[disabled]="
|
|
||||||
!user.tenantsPermissions.canRead ||
|
|
||||||
!user.policiesPermissions.canRead ||
|
|
||||||
!user.policiesPermissions.canWrite
|
|
||||||
">
|
|
||||||
<i class="fa fa-fw fa-key mr-2"></i>
|
|
||||||
Policies
|
|
||||||
</button>
|
|
||||||
</ng-container>
|
|
||||||
</ng-container>
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
<button mat-menu-item class="global-menu-item">
|
|
||||||
<i class="fa fa-fw fa-question-circle mr-2"></i>
|
|
||||||
Help
|
|
||||||
</button>
|
|
||||||
<button mat-menu-item class="global-menu-item">
|
|
||||||
<i class="fa fa-fw fa-info-circle mr-2"></i>
|
|
||||||
About
|
|
||||||
</button>
|
|
||||||
</mat-menu>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<flow-status
|
<flow-status
|
||||||
[controllerStatus]="(controllerStatus$ | async)!"
|
[controllerStatus]="(controllerStatus$ | async)!"
|
||||||
[lastRefreshed]="(lastRefreshed$ | async)!"
|
[lastRefreshed]="(lastRefreshed$ | async)!"
|
||||||
|
@ -14,50 +14,3 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.nifi-header {
|
|
||||||
position: relative;
|
|
||||||
z-index: 3;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
font-size: 32px;
|
|
||||||
color: #004849;
|
|
||||||
}
|
|
||||||
|
|
||||||
.current-user {
|
|
||||||
font-family: 'Roboto Slab';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 12px;
|
|
||||||
max-width: 250px;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
line-height: normal;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: #262626;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-size: 12px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.global-menu {
|
|
||||||
height: 64px;
|
|
||||||
width: 64px;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.global-menu:hover {
|
|
||||||
background-color: #e3e8eb;
|
|
||||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button.global-menu-item {
|
|
||||||
.fa,
|
|
||||||
.icon {
|
|
||||||
text-align: start;
|
|
||||||
color: #728e9b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -24,27 +24,35 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
|
|||||||
import { NewCanvasItem } from './new-canvas-item/new-canvas-item.component';
|
import { NewCanvasItem } from './new-canvas-item/new-canvas-item.component';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { MatDividerModule } from '@angular/material/divider';
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
import { FlowStatus } from './flow-status/flow-status.component';
|
|
||||||
import { RouterModule } from '@angular/router';
|
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
|
||||||
import {
|
import {
|
||||||
selectClusterSummary,
|
selectClusterSummary,
|
||||||
selectControllerBulletins,
|
selectControllerBulletins,
|
||||||
selectControllerStatus
|
selectControllerStatus
|
||||||
} from '../../../state/flow/flow.selectors';
|
} from '../../../state/flow/flow.selectors';
|
||||||
import { ClusterSummary, ControllerStatus } from '../../../state/flow';
|
import { ClusterSummary, ControllerStatus } from '../../../state/flow';
|
||||||
import { Search } from './search/search.component';
|
|
||||||
import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
|
import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { selectCurrentUser } from '../../../../../state/current-user/current-user.selectors';
|
import { Component } from '@angular/core';
|
||||||
import * as fromUser from '../../../../../state/current-user/current-user.reducer';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { selectFlowConfiguration } from '../../../../../state/flow-configuration/flow-configuration.selectors';
|
|
||||||
import * as fromFlowConfiguration from '../../../../../state/flow-configuration/flow-configuration.reducer';
|
|
||||||
|
|
||||||
describe('HeaderComponent', () => {
|
describe('HeaderComponent', () => {
|
||||||
let component: HeaderComponent;
|
let component: HeaderComponent;
|
||||||
let fixture: ComponentFixture<HeaderComponent>;
|
let fixture: ComponentFixture<HeaderComponent>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'flow-status',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockFlowStatus {}
|
||||||
|
|
||||||
const clusterSummary: ClusterSummary = {
|
const clusterSummary: ClusterSummary = {
|
||||||
clustered: false,
|
clustered: false,
|
||||||
connectedToCluster: false,
|
connectedToCluster: false,
|
||||||
@ -76,17 +84,16 @@ describe('HeaderComponent', () => {
|
|||||||
imports: [
|
imports: [
|
||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
NewCanvasItem,
|
NewCanvasItem,
|
||||||
FlowStatus,
|
|
||||||
Search,
|
|
||||||
HttpClientTestingModule,
|
HttpClientTestingModule,
|
||||||
|
MockFlowStatus,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatDividerModule,
|
MatDividerModule,
|
||||||
RouterModule,
|
|
||||||
RouterTestingModule,
|
RouterTestingModule,
|
||||||
CdkOverlayOrigin,
|
CdkOverlayOrigin,
|
||||||
CdkConnectedOverlay,
|
CdkConnectedOverlay,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule
|
ReactiveFormsModule,
|
||||||
|
MockNavigation
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
provideMockStore({
|
provideMockStore({
|
||||||
@ -103,14 +110,6 @@ describe('HeaderComponent', () => {
|
|||||||
{
|
{
|
||||||
selector: selectControllerBulletins,
|
selector: selectControllerBulletins,
|
||||||
value: []
|
value: []
|
||||||
},
|
|
||||||
{
|
|
||||||
selector: selectCurrentUser,
|
|
||||||
value: fromUser.initialState.user
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selector: selectFlowConfiguration,
|
|
||||||
value: fromFlowConfiguration.initialState.flowConfiguration
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@ -26,10 +26,6 @@ import {
|
|||||||
selectCurrentProcessGroupId,
|
selectCurrentProcessGroupId,
|
||||||
selectLastRefreshed
|
selectLastRefreshed
|
||||||
} from '../../../state/flow/flow.selectors';
|
} from '../../../state/flow/flow.selectors';
|
||||||
import { selectCurrentUser } from '../../../../../state/current-user/current-user.selectors';
|
|
||||||
import { CurrentUser } from '../../../../../state/current-user';
|
|
||||||
import { AuthStorage } from '../../../../../service/auth-storage.service';
|
|
||||||
import { AuthService } from '../../../../../service/auth.service';
|
|
||||||
import { LoadingService } from '../../../../../service/loading.service';
|
import { LoadingService } from '../../../../../service/loading.service';
|
||||||
import { NewCanvasItem } from './new-canvas-item/new-canvas-item.component';
|
import { NewCanvasItem } from './new-canvas-item/new-canvas-item.component';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
@ -38,9 +34,7 @@ import { AsyncPipe, NgIf, NgOptimizedImage } from '@angular/common';
|
|||||||
import { MatDividerModule } from '@angular/material/divider';
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
import { FlowStatus } from './flow-status/flow-status.component';
|
import { FlowStatus } from './flow-status/flow-status.component';
|
||||||
import { getNodeStatusHistoryAndOpenDialog } from '../../../../../state/status-history/status-history.actions';
|
import { Navigation } from '../../../../../ui/common/navigation/navigation.component';
|
||||||
import { getSystemDiagnosticsAndOpenDialog } from '../../../../../state/system-diagnostics/system-diagnostics.actions';
|
|
||||||
import { selectFlowConfiguration } from '../../../../../state/flow-configuration/flow-configuration.selectors';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'fd-header',
|
selector: 'fd-header',
|
||||||
@ -55,7 +49,8 @@ import { selectFlowConfiguration } from '../../../../../state/flow-configuration
|
|||||||
RouterLink,
|
RouterLink,
|
||||||
NgIf,
|
NgIf,
|
||||||
FlowStatus,
|
FlowStatus,
|
||||||
NgOptimizedImage
|
NgOptimizedImage,
|
||||||
|
Navigation
|
||||||
],
|
],
|
||||||
styleUrls: ['./header.component.scss']
|
styleUrls: ['./header.component.scss']
|
||||||
})
|
})
|
||||||
@ -66,46 +61,10 @@ export class HeaderComponent {
|
|||||||
lastRefreshed$ = this.store.select(selectLastRefreshed);
|
lastRefreshed$ = this.store.select(selectLastRefreshed);
|
||||||
clusterSummary$ = this.store.select(selectClusterSummary);
|
clusterSummary$ = this.store.select(selectClusterSummary);
|
||||||
controllerBulletins$ = this.store.select(selectControllerBulletins);
|
controllerBulletins$ = this.store.select(selectControllerBulletins);
|
||||||
currentUser$ = this.store.select(selectCurrentUser);
|
|
||||||
flowConfiguration$ = this.store.select(selectFlowConfiguration);
|
|
||||||
currentProcessGroupId$ = this.store.select(selectCurrentProcessGroupId);
|
currentProcessGroupId$ = this.store.select(selectCurrentProcessGroupId);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private store: Store<CanvasState>,
|
private store: Store<CanvasState>,
|
||||||
private authStorage: AuthStorage,
|
|
||||||
private authService: AuthService,
|
|
||||||
public loadingService: LoadingService
|
public loadingService: LoadingService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
allowLogin(user: CurrentUser): boolean {
|
|
||||||
return user.anonymous && location.protocol === 'https:';
|
|
||||||
}
|
|
||||||
|
|
||||||
hasToken(): boolean {
|
|
||||||
return this.authStorage.hasToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
logout(): void {
|
|
||||||
this.authService.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
viewNodeStatusHistory(): void {
|
|
||||||
this.store.dispatch(
|
|
||||||
getNodeStatusHistoryAndOpenDialog({
|
|
||||||
request: {
|
|
||||||
source: 'menu'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
viewSystemDiagnostics() {
|
|
||||||
this.store.dispatch(
|
|
||||||
getSystemDiagnosticsAndOpenDialog({
|
|
||||||
request: {
|
|
||||||
nodewise: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,14 +15,12 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-between">
|
<header class="nifi-header">
|
||||||
|
<navigation></navigation>
|
||||||
|
</header>
|
||||||
|
<div class="px-5 flex-1 flex flex-col">
|
||||||
<h3 class="text-xl bold parameter-context-header">Parameter Contexts</h3>
|
<h3 class="text-xl bold parameter-context-header">Parameter Contexts</h3>
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
<parameter-context-listing class="flex-1"></parameter-context-listing>
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<parameter-context-listing></parameter-context-listing>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,15 +23,23 @@ import { initialState } from '../state/parameter-context-listing/parameter-conte
|
|||||||
import { ParameterContextListing } from '../ui/parameter-context-listing/parameter-context-listing.component';
|
import { ParameterContextListing } from '../ui/parameter-context-listing/parameter-context-listing.component';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
describe('ParameterContexts', () => {
|
describe('ParameterContexts', () => {
|
||||||
let component: ParameterContexts;
|
let component: ParameterContexts;
|
||||||
let fixture: ComponentFixture<ParameterContexts>;
|
let fixture: ComponentFixture<ParameterContexts>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ParameterContexts, ParameterContextListing],
|
declarations: [ParameterContexts, ParameterContextListing],
|
||||||
imports: [RouterModule, RouterTestingModule],
|
imports: [RouterModule, RouterTestingModule, MockNavigation],
|
||||||
providers: [
|
providers: [
|
||||||
provideMockStore({
|
provideMockStore({
|
||||||
initialState
|
initialState
|
||||||
|
@ -24,6 +24,7 @@ import { ParameterContextsRoutingModule } from './parameter-contexts-routing.mod
|
|||||||
import { parameterContextsFeatureKey, reducers } from '../state';
|
import { parameterContextsFeatureKey, reducers } from '../state';
|
||||||
import { ParameterContextListingEffects } from '../state/parameter-context-listing/parameter-context-listing.effects';
|
import { ParameterContextListingEffects } from '../state/parameter-context-listing/parameter-context-listing.effects';
|
||||||
import { ParameterContextListingModule } from '../ui/parameter-context-listing/parameter-context-listing.module';
|
import { ParameterContextListingModule } from '../ui/parameter-context-listing/parameter-context-listing.module';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [ParameterContexts],
|
declarations: [ParameterContexts],
|
||||||
@ -33,7 +34,8 @@ import { ParameterContextListingModule } from '../ui/parameter-context-listing/p
|
|||||||
ParameterContextsRoutingModule,
|
ParameterContextsRoutingModule,
|
||||||
StoreModule.forFeature(parameterContextsFeatureKey, reducers),
|
StoreModule.forFeature(parameterContextsFeatureKey, reducers),
|
||||||
EffectsModule.forFeature(ParameterContextListingEffects),
|
EffectsModule.forFeature(ParameterContextListingEffects),
|
||||||
ParameterContextListingModule
|
ParameterContextListingModule,
|
||||||
|
Navigation
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ParameterContextsModule {}
|
export class ParameterContextsModule {}
|
||||||
|
@ -15,14 +15,12 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-between">
|
<header class="nifi-header">
|
||||||
<h3 class="text-xl bold provenance-header">Provenance</h3>
|
<navigation></navigation>
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
</header>
|
||||||
<i class="fa fa-times"></i>
|
<h3 class="px-5 text-xl bold provenance-header">Provenance</h3>
|
||||||
</button>
|
<div class="px-5 flex-1">
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,15 +22,25 @@ import { provideMockStore } from '@ngrx/store/testing';
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { initialState } from '../state/provenance-event-listing/provenance-event-listing.reducer';
|
import { initialState } from '../state/provenance-event-listing/provenance-event-listing.reducer';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
describe('Provenance', () => {
|
describe('Provenance', () => {
|
||||||
let component: Provenance;
|
let component: Provenance;
|
||||||
let fixture: ComponentFixture<Provenance>;
|
let fixture: ComponentFixture<Provenance>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [Provenance],
|
declarations: [Provenance],
|
||||||
imports: [RouterModule, RouterTestingModule],
|
imports: [RouterModule, RouterTestingModule, MockNavigation],
|
||||||
providers: [
|
providers: [
|
||||||
provideMockStore({
|
provideMockStore({
|
||||||
initialState
|
initialState
|
||||||
|
@ -25,6 +25,7 @@ import { provenanceFeatureKey, reducers } from '../state';
|
|||||||
import { ProvenanceEventListingEffects } from '../state/provenance-event-listing/provenance-event-listing.effects';
|
import { ProvenanceEventListingEffects } from '../state/provenance-event-listing/provenance-event-listing.effects';
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
import { LineageEffects } from '../state/lineage/lineage.effects';
|
import { LineageEffects } from '../state/lineage/lineage.effects';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [Provenance],
|
declarations: [Provenance],
|
||||||
@ -34,7 +35,8 @@ import { LineageEffects } from '../state/lineage/lineage.effects';
|
|||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
ProvenanceRoutingModule,
|
ProvenanceRoutingModule,
|
||||||
StoreModule.forFeature(provenanceFeatureKey, reducers),
|
StoreModule.forFeature(provenanceFeatureKey, reducers),
|
||||||
EffectsModule.forFeature(ProvenanceEventListingEffects, LineageEffects)
|
EffectsModule.forFeature(ProvenanceEventListingEffects, LineageEffects),
|
||||||
|
Navigation
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ProvenanceModule {}
|
export class ProvenanceModule {}
|
||||||
|
@ -15,13 +15,11 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-end">
|
<header class="nifi-header">
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
<navigation></navigation>
|
||||||
<i class="fa fa-times"></i>
|
</header>
|
||||||
</button>
|
<div class="px-5 flex-1">
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,15 +22,23 @@ import { provideMockStore } from '@ngrx/store/testing';
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { initialState } from '../state/queue-listing/queue-listing.reducer';
|
import { initialState } from '../state/queue-listing/queue-listing.reducer';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
describe('Queue', () => {
|
describe('Queue', () => {
|
||||||
let component: Queue;
|
let component: Queue;
|
||||||
let fixture: ComponentFixture<Queue>;
|
let fixture: ComponentFixture<Queue>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [Queue],
|
declarations: [Queue],
|
||||||
imports: [RouterModule, RouterTestingModule],
|
imports: [RouterModule, RouterTestingModule, MockNavigation],
|
||||||
providers: [
|
providers: [
|
||||||
provideMockStore({
|
provideMockStore({
|
||||||
initialState
|
initialState
|
||||||
|
@ -17,17 +17,14 @@
|
|||||||
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { StoreModule } from '@ngrx/store';
|
|
||||||
import { EffectsModule } from '@ngrx/effects';
|
|
||||||
import { Queue } from './queue.component';
|
import { Queue } from './queue.component';
|
||||||
import { QueueRoutingModule } from './queue-routing.module';
|
import { QueueRoutingModule } from './queue-routing.module';
|
||||||
import { queueFeatureKey, reducers } from '../state';
|
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
import { QueueListingEffects } from '../state/queue-listing/queue-listing.effects';
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [Queue],
|
declarations: [Queue],
|
||||||
exports: [Queue],
|
exports: [Queue],
|
||||||
imports: [CommonModule, MatDialogModule, QueueRoutingModule]
|
imports: [CommonModule, MatDialogModule, QueueRoutingModule, Navigation]
|
||||||
})
|
})
|
||||||
export class QueueModule {}
|
export class QueueModule {}
|
||||||
|
@ -16,16 +16,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable, throwError } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { NiFiCommon } from '../../../service/nifi-common.service';
|
import { NiFiCommon } from '../../../service/nifi-common.service';
|
||||||
import { ParameterContextUpdateRequest, SubmitParameterContextUpdate } from '../../../state/shared';
|
import { FlowFileSummary, ListingRequest, SubmitQueueListingRequest } from '../state/queue-listing';
|
||||||
import {
|
|
||||||
FlowFileSummary,
|
|
||||||
ListingRequest,
|
|
||||||
ListingRequestEntity,
|
|
||||||
SubmitQueueListingRequest
|
|
||||||
} from '../state/queue-listing';
|
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class QueueService {
|
export class QueueService {
|
||||||
|
@ -22,11 +22,9 @@ import { BulletinsTip } from '../../../../../ui/common/tooltips/bulletins-tip/bu
|
|||||||
import { ValidationErrorsTip } from '../../../../../ui/common/tooltips/validation-errors-tip/validation-errors-tip.component';
|
import { ValidationErrorsTip } from '../../../../../ui/common/tooltips/validation-errors-tip/validation-errors-tip.component';
|
||||||
import { NiFiCommon } from '../../../../../service/nifi-common.service';
|
import { NiFiCommon } from '../../../../../service/nifi-common.service';
|
||||||
import { NgForOf, NgIf } from '@angular/common';
|
import { NgForOf, NgIf } from '@angular/common';
|
||||||
import { ProvenanceEventSummary } from '../../../../../state/shared';
|
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
import { FlowFileSummary, ListingRequest } from '../../../state/queue-listing';
|
import { FlowFileSummary, ListingRequest } from '../../../state/queue-listing';
|
||||||
import { CurrentUser } from '../../../../../state/current-user';
|
import { CurrentUser } from '../../../../../state/current-user';
|
||||||
import { Flow } from '../../../../flow-designer/state/flow';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'flowfile-table',
|
selector: 'flowfile-table',
|
||||||
|
@ -15,14 +15,12 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-between">
|
<header class="nifi-header">
|
||||||
|
<navigation></navigation>
|
||||||
|
</header>
|
||||||
|
<div class="px-5 flex-1 flex flex-col">
|
||||||
<h3 class="text-xl bold settings-header">NiFi Settings</h3>
|
<h3 class="text-xl bold settings-header">NiFi Settings</h3>
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 flex flex-col">
|
|
||||||
<div class="settings-tabs">
|
<div class="settings-tabs">
|
||||||
<nav mat-tab-nav-bar color="primary" [tabPanel]="tabPanel">
|
<nav mat-tab-nav-bar color="primary" [tabPanel]="tabPanel">
|
||||||
<a
|
<a
|
||||||
|
@ -23,15 +23,23 @@ import { MatTabsModule } from '@angular/material/tabs';
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { initialState } from '../state/general/general.reducer';
|
import { initialState } from '../state/general/general.reducer';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
describe('SettingsComponent', () => {
|
describe('Settings', () => {
|
||||||
let component: Settings;
|
let component: Settings;
|
||||||
let fixture: ComponentFixture<Settings>;
|
let fixture: ComponentFixture<Settings>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [Settings],
|
declarations: [Settings],
|
||||||
imports: [MatTabsModule, RouterModule, RouterTestingModule],
|
imports: [MatTabsModule, RouterModule, RouterTestingModule, MockNavigation],
|
||||||
providers: [
|
providers: [
|
||||||
provideMockStore({
|
provideMockStore({
|
||||||
initialState
|
initialState
|
||||||
|
@ -34,6 +34,7 @@ import { MatTabsModule } from '@angular/material/tabs';
|
|||||||
import { ReportingTasksEffects } from '../state/reporting-tasks/reporting-tasks.effects';
|
import { ReportingTasksEffects } from '../state/reporting-tasks/reporting-tasks.effects';
|
||||||
import { RegistryClientsEffects } from '../state/registry-clients/registry-clients.effects';
|
import { RegistryClientsEffects } from '../state/registry-clients/registry-clients.effects';
|
||||||
import { FlowAnalysisRulesEffects } from '../state/flow-analysis-rules/flow-analysis-rules.effects';
|
import { FlowAnalysisRulesEffects } from '../state/flow-analysis-rules/flow-analysis-rules.effects';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [Settings],
|
declarations: [Settings],
|
||||||
@ -55,7 +56,8 @@ import { FlowAnalysisRulesEffects } from '../state/flow-analysis-rules/flow-anal
|
|||||||
FlowAnalysisRulesEffects,
|
FlowAnalysisRulesEffects,
|
||||||
RegistryClientsEffects
|
RegistryClientsEffects
|
||||||
),
|
),
|
||||||
MatTabsModule
|
MatTabsModule,
|
||||||
|
Navigation
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SettingsModule {}
|
export class SettingsModule {}
|
||||||
|
@ -15,14 +15,12 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-between">
|
<header class="nifi-header">
|
||||||
|
<navigation></navigation>
|
||||||
|
</header>
|
||||||
|
<div class="px-5 flex-1 flex flex-col">
|
||||||
<h3 class="text-xl bold summary-header">NiFi Summary</h3>
|
<h3 class="text-xl bold summary-header">NiFi Summary</h3>
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 flex flex-col">
|
|
||||||
<div class="summary-tabs">
|
<div class="summary-tabs">
|
||||||
<nav mat-tab-nav-bar color="primary" [tabPanel]="tabPanel">
|
<nav mat-tab-nav-bar color="primary" [tabPanel]="tabPanel">
|
||||||
<a
|
<a
|
||||||
|
@ -22,15 +22,23 @@ import { RouterTestingModule } from '@angular/router/testing';
|
|||||||
import { provideMockStore } from '@ngrx/store/testing';
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { Summary } from './summary.component';
|
import { Summary } from './summary.component';
|
||||||
import { initialState } from '../state/summary-listing/summary-listing.reducer';
|
import { initialState } from '../state/summary-listing/summary-listing.reducer';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
describe('Summary', () => {
|
describe('Summary', () => {
|
||||||
let component: Summary;
|
let component: Summary;
|
||||||
let fixture: ComponentFixture<Summary>;
|
let fixture: ComponentFixture<Summary>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [Summary],
|
declarations: [Summary],
|
||||||
imports: [MatTabsModule, RouterModule, RouterTestingModule],
|
imports: [MatTabsModule, RouterModule, RouterTestingModule, MockNavigation],
|
||||||
providers: [
|
providers: [
|
||||||
provideMockStore({
|
provideMockStore({
|
||||||
initialState
|
initialState
|
||||||
|
@ -31,6 +31,7 @@ import { OutputPortStatusListingModule } from '../ui/output-port-status-listing/
|
|||||||
import { InputPortStatusListingModule } from '../ui/input-port-status-listing/input-port-status-listing.module';
|
import { InputPortStatusListingModule } from '../ui/input-port-status-listing/input-port-status-listing.module';
|
||||||
import { SummaryListingEffects } from '../state/summary-listing/summary-listing.effects';
|
import { SummaryListingEffects } from '../state/summary-listing/summary-listing.effects';
|
||||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [Summary],
|
declarations: [Summary],
|
||||||
@ -48,7 +49,8 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
|||||||
InputPortStatusListingModule,
|
InputPortStatusListingModule,
|
||||||
StoreModule.forFeature(summaryFeatureKey, reducers),
|
StoreModule.forFeature(summaryFeatureKey, reducers),
|
||||||
EffectsModule.forFeature(SummaryListingEffects),
|
EffectsModule.forFeature(SummaryListingEffects),
|
||||||
NgxSkeletonLoaderModule
|
NgxSkeletonLoaderModule,
|
||||||
|
Navigation
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SummaryModule {}
|
export class SummaryModule {}
|
||||||
|
@ -15,14 +15,12 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="p-4 flex flex-col h-screen justify-between gap-y-5">
|
<div class="pb-5 flex flex-col h-screen justify-between gap-y-5">
|
||||||
<div class="flex justify-between">
|
<header class="nifi-header">
|
||||||
|
<navigation></navigation>
|
||||||
|
</header>
|
||||||
|
<div class="px-5 flex-1 flex flex-col">
|
||||||
<h3 class="text-xl bold user-header">NiFi Users</h3>
|
<h3 class="text-xl bold user-header">NiFi Users</h3>
|
||||||
<button class="nifi-button" [routerLink]="['/']">
|
<user-listing class="flex-1"></user-listing>
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<user-listing></user-listing>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,15 +22,23 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { UserListing } from '../ui/user-listing/user-listing.component';
|
import { UserListing } from '../ui/user-listing/user-listing.component';
|
||||||
import { initialState } from '../state/user-listing/user-listing.reducer';
|
import { initialState } from '../state/user-listing/user-listing.reducer';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
describe('Users', () => {
|
describe('Users', () => {
|
||||||
let component: Users;
|
let component: Users;
|
||||||
let fixture: ComponentFixture<Users>;
|
let fixture: ComponentFixture<Users>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [Users, UserListing],
|
declarations: [Users, UserListing],
|
||||||
imports: [RouterModule, RouterTestingModule],
|
imports: [RouterModule, RouterTestingModule, MockNavigation],
|
||||||
providers: [provideMockStore({ initialState })]
|
providers: [provideMockStore({ initialState })]
|
||||||
});
|
});
|
||||||
fixture = TestBed.createComponent(Users);
|
fixture = TestBed.createComponent(Users);
|
||||||
|
@ -25,6 +25,7 @@ import { EffectsModule } from '@ngrx/effects';
|
|||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
import { UserListingEffects } from '../state/user-listing/user-listing.effects';
|
import { UserListingEffects } from '../state/user-listing/user-listing.effects';
|
||||||
import { UserListingModule } from '../ui/user-listing/user-listing.module';
|
import { UserListingModule } from '../ui/user-listing/user-listing.module';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [Users],
|
declarations: [Users],
|
||||||
@ -35,7 +36,8 @@ import { UserListingModule } from '../ui/user-listing/user-listing.module';
|
|||||||
StoreModule.forFeature(usersFeatureKey, reducers),
|
StoreModule.forFeature(usersFeatureKey, reducers),
|
||||||
EffectsModule.forFeature(UserListingEffects),
|
EffectsModule.forFeature(UserListingEffects),
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
UserListingModule
|
UserListingModule,
|
||||||
|
Navigation
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class UsersModule {}
|
export class UsersModule {}
|
||||||
|
@ -0,0 +1,145 @@
|
|||||||
|
<!--
|
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
~ contributor license agreements. See the NOTICE file distributed with
|
||||||
|
~ this work for additional information regarding copyright ownership.
|
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
~ (the "License"); you may not use this file except in compliance with
|
||||||
|
~ the License. You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<nav class="bg-nifi-primary nifi-navigation">
|
||||||
|
<div class="flex justify-between items-center h-16 pl-4">
|
||||||
|
<div class="flex">
|
||||||
|
<div class="h-16 w-28 mr-6 relative">
|
||||||
|
<img
|
||||||
|
ngSrc="assets/icons/nifi-logo.svg"
|
||||||
|
fill
|
||||||
|
priority
|
||||||
|
alt="NiFi Logo"
|
||||||
|
class="pointer"
|
||||||
|
[routerLink]="['/']" />
|
||||||
|
</div>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between items-center gap-x-1" *ngIf="currentUser$ | async as user">
|
||||||
|
<div class="flex flex-col justify-between items-end gap-y-1">
|
||||||
|
<div class="current-user">{{ user.identity }}</div>
|
||||||
|
<a href="#" *ngIf="allowLogin(user)">log in</a>
|
||||||
|
<a (click)="logout()" *ngIf="hasToken()">log out</a>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
[matMenuTriggerFor]="globalMenu"
|
||||||
|
class="h-16 w-16 flex items-center justify-center icon global-menu">
|
||||||
|
<i class="fa fa-navicon"></i>
|
||||||
|
</button>
|
||||||
|
<mat-menu #globalMenu="matMenu" xPosition="before">
|
||||||
|
<button mat-menu-item class="global-menu-item" [routerLink]="['/']">
|
||||||
|
<i class="icon icon-drop mr-2"></i>
|
||||||
|
Canvas
|
||||||
|
</button>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<button mat-menu-item class="global-menu-item" [routerLink]="['/summary']">
|
||||||
|
<i class="fa fa-fw fa-table mr-2"></i>
|
||||||
|
Summary
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="global-menu-item"
|
||||||
|
[routerLink]="['/counters']"
|
||||||
|
[disabled]="!user.countersPermissions.canRead">
|
||||||
|
<i class="icon fa-fw icon-counter mr-2"></i>
|
||||||
|
Counter
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item class="global-menu-item" [routerLink]="['/bulletins']">
|
||||||
|
<i class="fa fa-fw fa-sticky-note-o mr-2"></i>
|
||||||
|
Bulletin Board
|
||||||
|
</button>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="global-menu-item"
|
||||||
|
[routerLink]="['/provenance']"
|
||||||
|
[disabled]="!user.provenancePermissions.canRead">
|
||||||
|
<i class="icon fa-fw icon-provenance mr-2"></i>
|
||||||
|
Data Provenance
|
||||||
|
</button>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="global-menu-item"
|
||||||
|
[routerLink]="['/settings']"
|
||||||
|
[disabled]="!user.controllerPermissions.canRead">
|
||||||
|
<i class="fa fa-fw fa-wrench mr-2"></i>
|
||||||
|
Controller Settings
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item class="global-menu-item" [routerLink]="['/parameter-contexts']">
|
||||||
|
<i class="fa fa-fw mr-2"></i>
|
||||||
|
Parameter Contexts
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item class="global-menu-item">
|
||||||
|
<i class="fa fa-fw fa-cubes mr-2"></i>
|
||||||
|
Cluster
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item class="global-menu-item">
|
||||||
|
<i class="fa fa-fw fa-history mr-2"></i>
|
||||||
|
Flow Configuration History
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item class="global-menu-item" (click)="viewNodeStatusHistory()">
|
||||||
|
<i class="fa fa-fw fa-area-chart mr-2"></i>
|
||||||
|
Node Status History
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="global-menu-item"
|
||||||
|
[disabled]="!user.systemPermissions.canRead"
|
||||||
|
(click)="viewSystemDiagnostics()">
|
||||||
|
<i class="fa fa-fw mr-2"></i>
|
||||||
|
System Diagnostics
|
||||||
|
</button>
|
||||||
|
<ng-container *ngIf="flowConfiguration$ | async as flowConfiguration">
|
||||||
|
<ng-container *ngIf="flowConfiguration.supportsManagedAuthorizer">
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="global-menu-item"
|
||||||
|
[routerLink]="['/users']"
|
||||||
|
[disabled]="!user.tenantsPermissions.canRead">
|
||||||
|
<i class="fa fa-fw fa-users mr-2"></i>
|
||||||
|
Users
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="global-menu-item"
|
||||||
|
[routerLink]="['/access-policies', 'global']"
|
||||||
|
[disabled]="
|
||||||
|
!user.tenantsPermissions.canRead ||
|
||||||
|
!user.policiesPermissions.canRead ||
|
||||||
|
!user.policiesPermissions.canWrite
|
||||||
|
">
|
||||||
|
<i class="fa fa-fw fa-key mr-2"></i>
|
||||||
|
Policies
|
||||||
|
</button>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<button mat-menu-item class="global-menu-item">
|
||||||
|
<i class="fa fa-fw fa-question-circle mr-2"></i>
|
||||||
|
Help
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item class="global-menu-item">
|
||||||
|
<i class="fa fa-fw fa-info-circle mr-2"></i>
|
||||||
|
About
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.nifi-navigation {
|
||||||
|
.icon {
|
||||||
|
font-size: 32px;
|
||||||
|
color: #004849;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-user {
|
||||||
|
font-family: 'Roboto Slab';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 12px;
|
||||||
|
max-width: 250px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
line-height: normal;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #262626;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-size: 12px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.global-menu {
|
||||||
|
height: 64px;
|
||||||
|
width: 64px;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.global-menu:hover {
|
||||||
|
background-color: #e3e8eb;
|
||||||
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button.global-menu-item {
|
||||||
|
.fa,
|
||||||
|
.icon {
|
||||||
|
text-align: start;
|
||||||
|
color: #728e9b;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { Navigation } from './navigation.component';
|
||||||
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
|
import { initialState } from '../../../state/current-user/current-user.reducer';
|
||||||
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
|
describe('Navigation', () => {
|
||||||
|
let component: Navigation;
|
||||||
|
let fixture: ComponentFixture<Navigation>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [Navigation, HttpClientTestingModule, RouterTestingModule],
|
||||||
|
providers: [
|
||||||
|
provideMockStore({
|
||||||
|
initialState
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(Navigation);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { AsyncPipe, NgIf, NgOptimizedImage } from '@angular/common';
|
||||||
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { getNodeStatusHistoryAndOpenDialog } from '../../../state/status-history/status-history.actions';
|
||||||
|
import { getSystemDiagnosticsAndOpenDialog } from '../../../state/system-diagnostics/system-diagnostics.actions';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AuthStorage } from '../../../service/auth-storage.service';
|
||||||
|
import { AuthService } from '../../../service/auth.service';
|
||||||
|
import { CurrentUser } from '../../../state/current-user';
|
||||||
|
import { RouterLink } from '@angular/router';
|
||||||
|
import { selectCurrentUser } from '../../../state/current-user/current-user.selectors';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { NiFiState } from '../../../state';
|
||||||
|
import { selectFlowConfiguration } from '../../../state/flow-configuration/flow-configuration.selectors';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
imports: [NgOptimizedImage, AsyncPipe, MatDividerModule, MatMenuModule, NgIf, RouterLink, MatButtonModule],
|
||||||
|
templateUrl: './navigation.component.html',
|
||||||
|
styleUrls: ['./navigation.component.scss']
|
||||||
|
})
|
||||||
|
export class Navigation {
|
||||||
|
currentUser$ = this.store.select(selectCurrentUser);
|
||||||
|
flowConfiguration$ = this.store.select(selectFlowConfiguration);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private store: Store<NiFiState>,
|
||||||
|
private authStorage: AuthStorage,
|
||||||
|
private authService: AuthService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
allowLogin(user: CurrentUser): boolean {
|
||||||
|
return user.anonymous && location.protocol === 'https:';
|
||||||
|
}
|
||||||
|
|
||||||
|
hasToken(): boolean {
|
||||||
|
return this.authStorage.hasToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
logout(): void {
|
||||||
|
this.authService.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
viewNodeStatusHistory(): void {
|
||||||
|
this.store.dispatch(
|
||||||
|
getNodeStatusHistoryAndOpenDialog({
|
||||||
|
request: {
|
||||||
|
source: 'menu'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewSystemDiagnostics() {
|
||||||
|
this.store.dispatch(
|
||||||
|
getSystemDiagnosticsAndOpenDialog({
|
||||||
|
request: {
|
||||||
|
nodewise: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -248,6 +248,11 @@ a:hover {
|
|||||||
text-decoration-color: #004849;
|
text-decoration-color: #004849;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header.nifi-header {
|
||||||
|
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Icon for styling mat-icon in forms throughout the application.
|
Icon for styling mat-icon in forms throughout the application.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user