mirror of https://github.com/apache/nifi.git
NIFI-12795: (#8416)
- Including embedded help documentation. - Support linking to specific help documentation from the canvas and component listings.
This commit is contained in:
parent
bd11031725
commit
6f6ddf8960
|
@ -28,6 +28,12 @@ const routes: Routes = [
|
||||||
path: 'error',
|
path: 'error',
|
||||||
loadChildren: () => import('./pages/error/feature/error.module').then((m) => m.ErrorModule)
|
loadChildren: () => import('./pages/error/feature/error.module').then((m) => m.ErrorModule)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'documentation',
|
||||||
|
canMatch: [authenticationGuard],
|
||||||
|
loadChildren: () =>
|
||||||
|
import('./pages/documentation/feature/documentation.module').then((m) => m.DocumentationModule)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'settings',
|
path: 'settings',
|
||||||
canMatch: [authenticationGuard],
|
canMatch: [authenticationGuard],
|
||||||
|
|
|
@ -45,6 +45,7 @@ import { ComponentStateEffects } from './state/component-state/component-state.e
|
||||||
import { ErrorEffects } from './state/error/error.effects';
|
import { ErrorEffects } from './state/error/error.effects';
|
||||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
import { PipesModule } from './pipes/pipes.module';
|
import { PipesModule } from './pipes/pipes.module';
|
||||||
|
import { DocumentationEffects } from './state/documentation/documentation.effects';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
|
@ -71,7 +72,8 @@ import { PipesModule } from './pipes/pipes.module';
|
||||||
StatusHistoryEffects,
|
StatusHistoryEffects,
|
||||||
ControllerServiceStateEffects,
|
ControllerServiceStateEffects,
|
||||||
SystemDiagnosticsEffects,
|
SystemDiagnosticsEffects,
|
||||||
ComponentStateEffects
|
ComponentStateEffects,
|
||||||
|
DocumentationEffects
|
||||||
),
|
),
|
||||||
StoreDevtoolsModule.instrument({
|
StoreDevtoolsModule.instrument({
|
||||||
maxAge: 25,
|
maxAge: 25,
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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 { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { Documentation } from './documentation.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: Documentation
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class DocumentationRoutingModule {}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<div class="pb-5 flex flex-col h-screen justify-between">
|
||||||
|
<header class="nifi-header">
|
||||||
|
<navigation></navigation>
|
||||||
|
</header>
|
||||||
|
@if (frameSource) {
|
||||||
|
<iframe class="flex-1" [src]="frameSource"></iframe>
|
||||||
|
} @else {
|
||||||
|
<iframe class="flex-1" src="../nifi-docs/documentation"></iframe>
|
||||||
|
}
|
||||||
|
</div>
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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 { Documentation } from './documentation.component';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
|
import { initialState } from '../../../state/documentation/documentation.reducer';
|
||||||
|
|
||||||
|
describe('Documentation', () => {
|
||||||
|
let component: Documentation;
|
||||||
|
let fixture: ComponentFixture<Documentation>;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'navigation',
|
||||||
|
standalone: true,
|
||||||
|
template: ''
|
||||||
|
})
|
||||||
|
class MockNavigation {}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [Documentation],
|
||||||
|
imports: [RouterModule, RouterTestingModule, MockNavigation],
|
||||||
|
providers: [provideMockStore({ initialState })]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(Documentation);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* 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, OnDestroy, SecurityContext } from '@angular/core';
|
||||||
|
import { NiFiState } from '../../../state';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
|
||||||
|
import { HttpParams } from '@angular/common/http';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
import { selectDocumentationParameters } from '../../../state/documentation/documentation.selectors';
|
||||||
|
import { DocumentationParameters } from '../../../state/documentation';
|
||||||
|
import { clearDocumentationParameters } from '../../../state/documentation/documentation.actions';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'documentation',
|
||||||
|
templateUrl: './documentation.component.html',
|
||||||
|
styleUrls: ['./documentation.component.scss']
|
||||||
|
})
|
||||||
|
export class Documentation implements OnDestroy {
|
||||||
|
frameSource!: SafeResourceUrl | null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private store: Store<NiFiState>,
|
||||||
|
private domSanitizer: DomSanitizer
|
||||||
|
) {
|
||||||
|
this.store
|
||||||
|
.select(selectDocumentationParameters)
|
||||||
|
.pipe(takeUntilDestroyed())
|
||||||
|
.subscribe((params) => {
|
||||||
|
this.frameSource = this.getFrameSource(params);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private getFrameSource(params: DocumentationParameters | null): SafeResourceUrl | null {
|
||||||
|
let url = '../nifi-docs/documentation';
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
if (Object.keys(params).length > 0) {
|
||||||
|
const queryParams: string = new HttpParams({ fromObject: params }).toString();
|
||||||
|
url = `${url}?${queryParams}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sanitizedUrl = this.domSanitizer.sanitize(SecurityContext.URL, url);
|
||||||
|
|
||||||
|
if (sanitizedUrl) {
|
||||||
|
return this.domSanitizer.bypassSecurityTrustResourceUrl(sanitizedUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.store.dispatch(clearDocumentationParameters());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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 { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Documentation } from './documentation.component';
|
||||||
|
import { DocumentationRoutingModule } from './documentation-routing.module';
|
||||||
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
import { Navigation } from '../../../ui/common/navigation/navigation.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [Documentation],
|
||||||
|
exports: [Documentation],
|
||||||
|
imports: [CommonModule, MatDialogModule, DocumentationRoutingModule, Navigation]
|
||||||
|
})
|
||||||
|
export class DocumentationModule {}
|
|
@ -57,6 +57,7 @@ import {
|
||||||
} from '../../../ui/common/context-menu/context-menu.component';
|
} from '../../../ui/common/context-menu/context-menu.component';
|
||||||
import { promptEmptyQueueRequest, promptEmptyQueuesRequest } from '../state/queue/queue.actions';
|
import { promptEmptyQueueRequest, promptEmptyQueuesRequest } from '../state/queue/queue.actions';
|
||||||
import { getComponentStateAndOpenDialog } from '../../../state/component-state/component-state.actions';
|
import { getComponentStateAndOpenDialog } from '../../../state/component-state/component-state.actions';
|
||||||
|
import { navigateToComponentDocumentation } from '../../../state/documentation/documentation.actions';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanvasContextMenu implements ContextMenuDefinitionProvider {
|
export class CanvasContextMenu implements ContextMenuDefinitionProvider {
|
||||||
|
@ -717,13 +718,26 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
condition: (selection: any) => {
|
condition: (selection: any) => {
|
||||||
// TODO - hasUsage
|
return (
|
||||||
return false;
|
this.canvasUtils.canRead(selection) &&
|
||||||
|
selection.size() === 1 &&
|
||||||
|
this.canvasUtils.isProcessor(selection)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
clazz: 'fa fa-book',
|
clazz: 'fa fa-book',
|
||||||
text: 'View usage',
|
text: 'View documentation',
|
||||||
action: () => {
|
action: (selection: any) => {
|
||||||
// TODO - showUsage
|
const selectionData = selection.datum();
|
||||||
|
this.store.dispatch(
|
||||||
|
navigateToComponentDocumentation({
|
||||||
|
params: {
|
||||||
|
select: selectionData.component.type,
|
||||||
|
group: selectionData.component.bundle.group,
|
||||||
|
artifact: selectionData.component.bundle.artifact,
|
||||||
|
version: selectionData.component.bundle.version
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
[flowConfiguration]="flowConfiguration"
|
[flowConfiguration]="flowConfiguration"
|
||||||
[canModifyParent]="canModifyParent(serviceState.breadcrumb)"
|
[canModifyParent]="canModifyParent(serviceState.breadcrumb)"
|
||||||
(selectControllerService)="selectControllerService($event)"
|
(selectControllerService)="selectControllerService($event)"
|
||||||
|
(viewControllerServiceDocumentation)="viewControllerServiceDocumentation($event)"
|
||||||
(configureControllerService)="configureControllerService($event)"
|
(configureControllerService)="configureControllerService($event)"
|
||||||
(enableControllerService)="enableControllerService($event)"
|
(enableControllerService)="enableControllerService($event)"
|
||||||
(disableControllerService)="disableControllerService($event)"
|
(disableControllerService)="disableControllerService($event)"
|
||||||
|
|
|
@ -46,6 +46,7 @@ import { selectFlowConfiguration } from '../../../../state/flow-configuration/fl
|
||||||
import { NiFiState } from '../../../../state';
|
import { NiFiState } from '../../../../state';
|
||||||
import { loadFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.actions';
|
import { loadFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.actions';
|
||||||
import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions';
|
import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions';
|
||||||
|
import { navigateToComponentDocumentation } from '../../../../state/documentation/documentation.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'controller-services',
|
selector: 'controller-services',
|
||||||
|
@ -160,6 +161,19 @@ export class ControllerServices implements OnInit, OnDestroy {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewControllerServiceDocumentation(entity: ControllerServiceEntity): void {
|
||||||
|
this.store.dispatch(
|
||||||
|
navigateToComponentDocumentation({
|
||||||
|
params: {
|
||||||
|
select: entity.component.type,
|
||||||
|
group: entity.component.bundle.group,
|
||||||
|
artifact: entity.component.bundle.artifact,
|
||||||
|
version: entity.component.bundle.version
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
configureControllerService(entity: ControllerServiceEntity): void {
|
configureControllerService(entity: ControllerServiceEntity): void {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
navigateToEditService({
|
navigateToEditService({
|
||||||
|
|
|
@ -31,7 +31,10 @@
|
||||||
<td mat-cell *matCellDef="let item">
|
<td mat-cell *matCellDef="let item">
|
||||||
@if (canRead(item)) {
|
@if (canRead(item)) {
|
||||||
<div class="flex items-center gap-x-3">
|
<div class="flex items-center gap-x-3">
|
||||||
<div class="pointer fa fa-book" title="Usage"></div>
|
<div
|
||||||
|
class="pointer fa fa-book"
|
||||||
|
(click)="viewDocumentationClicked(item, $event)"
|
||||||
|
title="View Documentation"></div>
|
||||||
<!-- TODO - handle read only in configure component? -->
|
<!-- TODO - handle read only in configure component? -->
|
||||||
@if (hasComments(item)) {
|
@if (hasComments(item)) {
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -51,10 +51,13 @@ export class FlowAnalysisRuleTable {
|
||||||
@Input() set flowAnalysisRules(flowAnalysisRuleEntities: FlowAnalysisRuleEntity[]) {
|
@Input() set flowAnalysisRules(flowAnalysisRuleEntities: FlowAnalysisRuleEntity[]) {
|
||||||
this.dataSource.data = this.sortFlowAnalysisRules(flowAnalysisRuleEntities, this.sort);
|
this.dataSource.data = this.sortFlowAnalysisRules(flowAnalysisRuleEntities, this.sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input() selectedFlowAnalysisRuleId!: string;
|
@Input() selectedFlowAnalysisRuleId!: string;
|
||||||
@Input() currentUser!: CurrentUser;
|
@Input() currentUser!: CurrentUser;
|
||||||
|
|
||||||
@Output() selectFlowAnalysisRule: EventEmitter<FlowAnalysisRuleEntity> = new EventEmitter<FlowAnalysisRuleEntity>();
|
@Output() selectFlowAnalysisRule: EventEmitter<FlowAnalysisRuleEntity> = new EventEmitter<FlowAnalysisRuleEntity>();
|
||||||
|
@Output() viewFlowAnalysisRuleDocumentation: EventEmitter<FlowAnalysisRuleEntity> =
|
||||||
|
new EventEmitter<FlowAnalysisRuleEntity>();
|
||||||
@Output() deleteFlowAnalysisRule: EventEmitter<FlowAnalysisRuleEntity> = new EventEmitter<FlowAnalysisRuleEntity>();
|
@Output() deleteFlowAnalysisRule: EventEmitter<FlowAnalysisRuleEntity> = new EventEmitter<FlowAnalysisRuleEntity>();
|
||||||
@Output() configureFlowAnalysisRule: EventEmitter<FlowAnalysisRuleEntity> =
|
@Output() configureFlowAnalysisRule: EventEmitter<FlowAnalysisRuleEntity> =
|
||||||
new EventEmitter<FlowAnalysisRuleEntity>();
|
new EventEmitter<FlowAnalysisRuleEntity>();
|
||||||
|
@ -123,6 +126,11 @@ export class FlowAnalysisRuleTable {
|
||||||
return !!entity.operatePermissions?.canWrite;
|
return !!entity.operatePermissions?.canWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewDocumentationClicked(entity: FlowAnalysisRuleEntity, event: MouseEvent): void {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.viewFlowAnalysisRuleDocumentation.next(entity);
|
||||||
|
}
|
||||||
|
|
||||||
hasComments(entity: FlowAnalysisRuleEntity): boolean {
|
hasComments(entity: FlowAnalysisRuleEntity): boolean {
|
||||||
return !this.nifiCommon.isBlank(entity.component.comments);
|
return !this.nifiCommon.isBlank(entity.component.comments);
|
||||||
}
|
}
|
||||||
|
@ -236,7 +244,7 @@ export class FlowAnalysisRuleTable {
|
||||||
this.isDisabled(entity) &&
|
this.isDisabled(entity) &&
|
||||||
this.canRead(entity) &&
|
this.canRead(entity) &&
|
||||||
this.canWrite(entity) &&
|
this.canWrite(entity) &&
|
||||||
entity.component.multipleVersionsAvailable === true
|
entity.component.multipleVersionsAvailable
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
[flowAnalysisRules]="flowAnalysisRuleState.flowAnalysisRules"
|
[flowAnalysisRules]="flowAnalysisRuleState.flowAnalysisRules"
|
||||||
(configureFlowAnalysisRule)="configureFlowAnalysisRule($event)"
|
(configureFlowAnalysisRule)="configureFlowAnalysisRule($event)"
|
||||||
(selectFlowAnalysisRule)="selectFlowAnalysisRule($event)"
|
(selectFlowAnalysisRule)="selectFlowAnalysisRule($event)"
|
||||||
|
(viewFlowAnalysisRuleDocumentation)="viewFlowAnalysisRuleDocumentation($event)"
|
||||||
(enableFlowAnalysisRule)="enableFlowAnalysisRule($event)"
|
(enableFlowAnalysisRule)="enableFlowAnalysisRule($event)"
|
||||||
(disableFlowAnalysisRule)="disableFlowAnalysisRule($event)"
|
(disableFlowAnalysisRule)="disableFlowAnalysisRule($event)"
|
||||||
(viewStateFlowAnalysisRule)="viewStateFlowAnalysisRule($event)"
|
(viewStateFlowAnalysisRule)="viewStateFlowAnalysisRule($event)"
|
||||||
|
|
|
@ -41,6 +41,7 @@ import { selectCurrentUser } from '../../../../state/current-user/current-user.s
|
||||||
import { NiFiState } from '../../../../state';
|
import { NiFiState } from '../../../../state';
|
||||||
import { FlowAnalysisRuleEntity, FlowAnalysisRulesState } from '../../state/flow-analysis-rules';
|
import { FlowAnalysisRuleEntity, FlowAnalysisRulesState } from '../../state/flow-analysis-rules';
|
||||||
import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions';
|
import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions';
|
||||||
|
import { navigateToComponentDocumentation } from '../../../../state/documentation/documentation.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'flow-analysis-rules',
|
selector: 'flow-analysis-rules',
|
||||||
|
@ -106,6 +107,19 @@ export class FlowAnalysisRules implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewFlowAnalysisRuleDocumentation(entity: FlowAnalysisRuleEntity): void {
|
||||||
|
this.store.dispatch(
|
||||||
|
navigateToComponentDocumentation({
|
||||||
|
params: {
|
||||||
|
select: entity.component.type,
|
||||||
|
group: entity.component.bundle.group,
|
||||||
|
artifact: entity.component.bundle.artifact,
|
||||||
|
version: entity.component.bundle.version
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
enableFlowAnalysisRule(entity: FlowAnalysisRuleEntity): void {
|
enableFlowAnalysisRule(entity: FlowAnalysisRuleEntity): void {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
enableFlowAnalysisRule({
|
enableFlowAnalysisRule({
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
[canModifyParent]="canModifyParent(currentUser)"
|
[canModifyParent]="canModifyParent(currentUser)"
|
||||||
[flowConfiguration]="(flowConfiguration$ | async)!"
|
[flowConfiguration]="(flowConfiguration$ | async)!"
|
||||||
(selectControllerService)="selectControllerService($event)"
|
(selectControllerService)="selectControllerService($event)"
|
||||||
|
(viewControllerServiceDocumentation)="viewControllerServiceDocumentation($event)"
|
||||||
(configureControllerService)="configureControllerService($event)"
|
(configureControllerService)="configureControllerService($event)"
|
||||||
(enableControllerService)="enableControllerService($event)"
|
(enableControllerService)="enableControllerService($event)"
|
||||||
(disableControllerService)="disableControllerService($event)"
|
(disableControllerService)="disableControllerService($event)"
|
||||||
|
|
|
@ -45,6 +45,7 @@ import { selectFlowConfiguration } from '../../../../state/flow-configuration/fl
|
||||||
import { loadFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.actions';
|
import { loadFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.actions';
|
||||||
import { CurrentUser } from '../../../../state/current-user';
|
import { CurrentUser } from '../../../../state/current-user';
|
||||||
import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions';
|
import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions';
|
||||||
|
import { navigateToComponentDocumentation } from '../../../../state/documentation/documentation.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'management-controller-services',
|
selector: 'management-controller-services',
|
||||||
|
@ -110,6 +111,19 @@ export class ManagementControllerServices implements OnInit, OnDestroy {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewControllerServiceDocumentation(entity: ControllerServiceEntity): void {
|
||||||
|
this.store.dispatch(
|
||||||
|
navigateToComponentDocumentation({
|
||||||
|
params: {
|
||||||
|
select: entity.component.type,
|
||||||
|
group: entity.component.bundle.group,
|
||||||
|
artifact: entity.component.bundle.artifact,
|
||||||
|
version: entity.component.bundle.version
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
configureControllerService(entity: ControllerServiceEntity): void {
|
configureControllerService(entity: ControllerServiceEntity): void {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
navigateToEditService({
|
navigateToEditService({
|
||||||
|
|
|
@ -31,25 +31,29 @@
|
||||||
<ng-container matColumnDef="moreDetails">
|
<ng-container matColumnDef="moreDetails">
|
||||||
<th mat-header-cell *matHeaderCellDef></th>
|
<th mat-header-cell *matHeaderCellDef></th>
|
||||||
<td mat-cell *matCellDef="let item">
|
<td mat-cell *matCellDef="let item">
|
||||||
<div class="flex items-center gap-x-3">
|
@if (canRead(item)) {
|
||||||
<!-- TODO: open details -->
|
<div class="flex items-center gap-x-3">
|
||||||
<div class="pointer fa fa-info-circle" title="View details"></div>
|
<!-- TODO: open details -->
|
||||||
|
<div class="pointer fa fa-info-circle" title="View details"></div>
|
||||||
|
|
||||||
<!-- TODO: open documentation -->
|
<div
|
||||||
<div class="pointer fa fa-book" title="View Documentation"></div>
|
class="pointer fa fa-book"
|
||||||
|
(click)="viewDocumentationClicked(item, $event)"
|
||||||
|
title="View Documentation"></div>
|
||||||
|
|
||||||
<!-- Validation Errors -->
|
<!-- Validation Errors -->
|
||||||
@if (hasErrors(item)) {
|
@if (hasErrors(item)) {
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="pointer fa fa-warning has-errors"
|
class="pointer fa fa-warning has-errors"
|
||||||
nifiTooltip
|
nifiTooltip
|
||||||
[delayClose]="false"
|
[delayClose]="false"
|
||||||
[tooltipComponentType]="ValidationErrorsTip"
|
[tooltipComponentType]="ValidationErrorsTip"
|
||||||
[tooltipInputData]="getValidationErrorsTipData(item)"></div>
|
[tooltipInputData]="getValidationErrorsTipData(item)"></div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,8 @@ export class ParameterProvidersTable {
|
||||||
|
|
||||||
@Output() selectParameterProvider: EventEmitter<ParameterProviderEntity> =
|
@Output() selectParameterProvider: EventEmitter<ParameterProviderEntity> =
|
||||||
new EventEmitter<ParameterProviderEntity>();
|
new EventEmitter<ParameterProviderEntity>();
|
||||||
|
@Output() viewParameterProviderDocumentation: EventEmitter<ParameterProviderEntity> =
|
||||||
|
new EventEmitter<ParameterProviderEntity>();
|
||||||
@Output() configureParameterProvider: EventEmitter<ParameterProviderEntity> =
|
@Output() configureParameterProvider: EventEmitter<ParameterProviderEntity> =
|
||||||
new EventEmitter<ParameterProviderEntity>();
|
new EventEmitter<ParameterProviderEntity>();
|
||||||
@Output() deleteParameterProvider: EventEmitter<ParameterProviderEntity> =
|
@Output() deleteParameterProvider: EventEmitter<ParameterProviderEntity> =
|
||||||
|
@ -129,6 +131,11 @@ export class ParameterProvidersTable {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewDocumentationClicked(entity: ParameterProviderEntity, event: MouseEvent): void {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.viewParameterProviderDocumentation.next(entity);
|
||||||
|
}
|
||||||
|
|
||||||
formatName(entity: ParameterProviderEntity): string {
|
formatName(entity: ParameterProviderEntity): string {
|
||||||
return this.canRead(entity) ? entity.component.name : entity.id;
|
return this.canRead(entity) ? entity.component.name : entity.id;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +149,7 @@ export class ParameterProvidersTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasErrors(entity: ParameterProviderEntity): boolean {
|
hasErrors(entity: ParameterProviderEntity): boolean {
|
||||||
return this.canRead(entity) && !this.nifiCommon.isEmpty(entity.component.validationErrors);
|
return !this.nifiCommon.isEmpty(entity.component.validationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
getValidationErrorsTipData(entity: ParameterProviderEntity): ValidationErrorsTipInput | null {
|
getValidationErrorsTipData(entity: ParameterProviderEntity): ValidationErrorsTipInput | null {
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
(deleteParameterProvider)="deleteParameterProvider($event)"
|
(deleteParameterProvider)="deleteParameterProvider($event)"
|
||||||
(configureParameterProvider)="openConfigureParameterProviderDialog($event)"
|
(configureParameterProvider)="openConfigureParameterProviderDialog($event)"
|
||||||
(fetchParameterProvider)="fetchParameterProviderParameters($event)"
|
(fetchParameterProvider)="fetchParameterProviderParameters($event)"
|
||||||
|
(viewParameterProviderDocumentation)="viewParameterProviderDocumentation($event)"
|
||||||
(selectParameterProvider)="selectParameterProvider($event)"></parameter-providers-table>
|
(selectParameterProvider)="selectParameterProvider($event)"></parameter-providers-table>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
|
|
|
@ -34,6 +34,7 @@ import { initialParameterProvidersState } from '../../state/parameter-providers/
|
||||||
import { switchMap, take } from 'rxjs';
|
import { switchMap, take } from 'rxjs';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { isDefinedAndNotNull } from '../../../../state/shared';
|
import { isDefinedAndNotNull } from '../../../../state/shared';
|
||||||
|
import { navigateToComponentDocumentation } from '../../../../state/documentation/documentation.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'parameter-providers',
|
selector: 'parameter-providers',
|
||||||
|
@ -130,6 +131,19 @@ export class ParameterProviders implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewParameterProviderDocumentation(parameterProvider: ParameterProviderEntity): void {
|
||||||
|
this.store.dispatch(
|
||||||
|
navigateToComponentDocumentation({
|
||||||
|
params: {
|
||||||
|
select: parameterProvider.component.type,
|
||||||
|
group: parameterProvider.component.bundle.group,
|
||||||
|
artifact: parameterProvider.component.bundle.artifact,
|
||||||
|
version: parameterProvider.component.bundle.version
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
deleteParameterProvider(parameterProvider: ParameterProviderEntity) {
|
deleteParameterProvider(parameterProvider: ParameterProviderEntity) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
ParameterProviderActions.promptParameterProviderDeletion({
|
ParameterProviderActions.promptParameterProviderDeletion({
|
||||||
|
|
|
@ -31,7 +31,10 @@
|
||||||
<td mat-cell *matCellDef="let item">
|
<td mat-cell *matCellDef="let item">
|
||||||
@if (canRead(item)) {
|
@if (canRead(item)) {
|
||||||
<div class="flex items-center gap-x-3">
|
<div class="flex items-center gap-x-3">
|
||||||
<div class="pointer fa fa-book" title="Usage"></div>
|
<div
|
||||||
|
class="pointer fa fa-book"
|
||||||
|
(click)="viewDocumentationClicked(item, $event)"
|
||||||
|
title="View Documentation"></div>
|
||||||
<!-- TODO - handle read only in configure component? -->
|
<!-- TODO - handle read only in configure component? -->
|
||||||
@if (hasComments(item)) {
|
@if (hasComments(item)) {
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -49,6 +49,8 @@ export class ReportingTaskTable {
|
||||||
@Input() currentUser!: CurrentUser;
|
@Input() currentUser!: CurrentUser;
|
||||||
|
|
||||||
@Output() selectReportingTask: EventEmitter<ReportingTaskEntity> = new EventEmitter<ReportingTaskEntity>();
|
@Output() selectReportingTask: EventEmitter<ReportingTaskEntity> = new EventEmitter<ReportingTaskEntity>();
|
||||||
|
@Output() viewReportingTaskDocumentation: EventEmitter<ReportingTaskEntity> =
|
||||||
|
new EventEmitter<ReportingTaskEntity>();
|
||||||
@Output() deleteReportingTask: EventEmitter<ReportingTaskEntity> = new EventEmitter<ReportingTaskEntity>();
|
@Output() deleteReportingTask: EventEmitter<ReportingTaskEntity> = new EventEmitter<ReportingTaskEntity>();
|
||||||
@Output() startReportingTask: EventEmitter<ReportingTaskEntity> = new EventEmitter<ReportingTaskEntity>();
|
@Output() startReportingTask: EventEmitter<ReportingTaskEntity> = new EventEmitter<ReportingTaskEntity>();
|
||||||
@Output() configureReportingTask: EventEmitter<ReportingTaskEntity> = new EventEmitter<ReportingTaskEntity>();
|
@Output() configureReportingTask: EventEmitter<ReportingTaskEntity> = new EventEmitter<ReportingTaskEntity>();
|
||||||
|
@ -79,6 +81,11 @@ export class ReportingTaskTable {
|
||||||
return !!entity.operatePermissions?.canWrite;
|
return !!entity.operatePermissions?.canWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewDocumentationClicked(entity: ReportingTaskEntity, event: MouseEvent): void {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.viewReportingTaskDocumentation.next(entity);
|
||||||
|
}
|
||||||
|
|
||||||
hasComments(entity: ReportingTaskEntity): boolean {
|
hasComments(entity: ReportingTaskEntity): boolean {
|
||||||
return !this.nifiCommon.isBlank(entity.component.comments);
|
return !this.nifiCommon.isBlank(entity.component.comments);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
(configureReportingTask)="configureReportingTask($event)"
|
(configureReportingTask)="configureReportingTask($event)"
|
||||||
(viewStateReportingTask)="viewStateReportingTask($event)"
|
(viewStateReportingTask)="viewStateReportingTask($event)"
|
||||||
(selectReportingTask)="selectReportingTask($event)"
|
(selectReportingTask)="selectReportingTask($event)"
|
||||||
|
(viewReportingTaskDocumentation)="viewReportingTaskDocumentation($event)"
|
||||||
(deleteReportingTask)="deleteReportingTask($event)"
|
(deleteReportingTask)="deleteReportingTask($event)"
|
||||||
(stopReportingTask)="stopReportingTask($event)"
|
(stopReportingTask)="stopReportingTask($event)"
|
||||||
(startReportingTask)="startReportingTask($event)"></reporting-task-table>
|
(startReportingTask)="startReportingTask($event)"></reporting-task-table>
|
||||||
|
|
|
@ -43,6 +43,7 @@ import { NiFiState } from '../../../../state';
|
||||||
import { loadFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.actions';
|
import { loadFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.actions';
|
||||||
import { selectFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.selectors';
|
import { selectFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.selectors';
|
||||||
import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions';
|
import { getComponentStateAndOpenDialog } from '../../../../state/component-state/component-state.actions';
|
||||||
|
import { navigateToComponentDocumentation } from '../../../../state/documentation/documentation.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'reporting-tasks',
|
selector: 'reporting-tasks',
|
||||||
|
@ -110,6 +111,19 @@ export class ReportingTasks implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewReportingTaskDocumentation(entity: ReportingTaskEntity): void {
|
||||||
|
this.store.dispatch(
|
||||||
|
navigateToComponentDocumentation({
|
||||||
|
params: {
|
||||||
|
select: entity.component.type,
|
||||||
|
group: entity.component.bundle.group,
|
||||||
|
artifact: entity.component.bundle.artifact,
|
||||||
|
version: entity.component.bundle.version
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
deleteReportingTask(entity: ReportingTaskEntity): void {
|
deleteReportingTask(entity: ReportingTaskEntity): void {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
promptReportingTaskDeletion({
|
promptReportingTaskDeletion({
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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 { createAction, props } from '@ngrx/store';
|
||||||
|
import { DocumentationParameters } from './index';
|
||||||
|
|
||||||
|
export const navigateToComponentDocumentation = createAction(
|
||||||
|
'[Documentation] Navigate To Component Documentation',
|
||||||
|
props<{
|
||||||
|
params: DocumentationParameters;
|
||||||
|
}>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const clearDocumentationParameters = createAction('[Documentation] Clear Documentation Parameters');
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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 { Injectable } from '@angular/core';
|
||||||
|
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||||
|
import * as DocumentationActions from './documentation.actions';
|
||||||
|
import { tap } from 'rxjs';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DocumentationEffects {
|
||||||
|
constructor(
|
||||||
|
private actions$: Actions,
|
||||||
|
private router: Router
|
||||||
|
) {}
|
||||||
|
|
||||||
|
navigateToComponentDocumentation$ = createEffect(
|
||||||
|
() =>
|
||||||
|
this.actions$.pipe(
|
||||||
|
ofType(DocumentationActions.navigateToComponentDocumentation),
|
||||||
|
tap(() => {
|
||||||
|
this.router.navigate(['/documentation']);
|
||||||
|
})
|
||||||
|
),
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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 { createReducer, on } from '@ngrx/store';
|
||||||
|
import { DocumentationState } from './index';
|
||||||
|
import { clearDocumentationParameters, navigateToComponentDocumentation } from './documentation.actions';
|
||||||
|
|
||||||
|
export const initialState: DocumentationState = {
|
||||||
|
documentationParameters: null
|
||||||
|
};
|
||||||
|
|
||||||
|
export const documentationReducer = createReducer(
|
||||||
|
initialState,
|
||||||
|
on(navigateToComponentDocumentation, (state, { params }) => ({
|
||||||
|
...state,
|
||||||
|
documentationParameters: params
|
||||||
|
})),
|
||||||
|
on(clearDocumentationParameters, (state) => ({
|
||||||
|
...state,
|
||||||
|
documentationParameters: null
|
||||||
|
}))
|
||||||
|
);
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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 { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||||
|
import { documentationFeatureKey, DocumentationState } from './index';
|
||||||
|
|
||||||
|
export const selectDocumentationState = createFeatureSelector<DocumentationState>(documentationFeatureKey);
|
||||||
|
|
||||||
|
export const selectDocumentationParameters = createSelector(
|
||||||
|
selectDocumentationState,
|
||||||
|
(state: DocumentationState) => state.documentationParameters
|
||||||
|
);
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const documentationFeatureKey = 'documentation';
|
||||||
|
|
||||||
|
export interface DocumentationParameters {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DocumentationState {
|
||||||
|
documentationParameters: DocumentationParameters | null;
|
||||||
|
}
|
|
@ -35,6 +35,8 @@ import { componentStateFeatureKey, ComponentStateState } from './component-state
|
||||||
import { componentStateReducer } from './component-state/component-state.reducer';
|
import { componentStateReducer } from './component-state/component-state.reducer';
|
||||||
import { errorFeatureKey, ErrorState } from './error';
|
import { errorFeatureKey, ErrorState } from './error';
|
||||||
import { errorReducer } from './error/error.reducer';
|
import { errorReducer } from './error/error.reducer';
|
||||||
|
import { documentationFeatureKey, DocumentationState } from './documentation';
|
||||||
|
import { documentationReducer } from './documentation/documentation.reducer';
|
||||||
|
|
||||||
export interface NiFiState {
|
export interface NiFiState {
|
||||||
router: RouterReducerState;
|
router: RouterReducerState;
|
||||||
|
@ -47,6 +49,7 @@ export interface NiFiState {
|
||||||
[controllerServiceStateFeatureKey]: ControllerServiceState;
|
[controllerServiceStateFeatureKey]: ControllerServiceState;
|
||||||
[systemDiagnosticsFeatureKey]: SystemDiagnosticsState;
|
[systemDiagnosticsFeatureKey]: SystemDiagnosticsState;
|
||||||
[componentStateFeatureKey]: ComponentStateState;
|
[componentStateFeatureKey]: ComponentStateState;
|
||||||
|
[documentationFeatureKey]: DocumentationState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const rootReducers: ActionReducerMap<NiFiState> = {
|
export const rootReducers: ActionReducerMap<NiFiState> = {
|
||||||
|
@ -59,5 +62,6 @@ export const rootReducers: ActionReducerMap<NiFiState> = {
|
||||||
[statusHistoryFeatureKey]: statusHistoryReducer,
|
[statusHistoryFeatureKey]: statusHistoryReducer,
|
||||||
[controllerServiceStateFeatureKey]: controllerServiceStateReducer,
|
[controllerServiceStateFeatureKey]: controllerServiceStateReducer,
|
||||||
[systemDiagnosticsFeatureKey]: systemDiagnosticsReducer,
|
[systemDiagnosticsFeatureKey]: systemDiagnosticsReducer,
|
||||||
[componentStateFeatureKey]: componentStateReducer
|
[componentStateFeatureKey]: componentStateReducer,
|
||||||
|
[documentationFeatureKey]: documentationReducer
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,13 +31,11 @@
|
||||||
<td mat-cell *matCellDef="let item">
|
<td mat-cell *matCellDef="let item">
|
||||||
@if (canRead(item)) {
|
@if (canRead(item)) {
|
||||||
<div class="flex items-center gap-x-3">
|
<div class="flex items-center gap-x-3">
|
||||||
<div class="pointer fa fa-book" title="Usage"></div>
|
<div
|
||||||
<!--
|
class="pointer fa fa-book"
|
||||||
nifiTooltip dynamically inserts the tooltip component
|
(click)="viewDocumentationClicked(item, $event)"
|
||||||
into the dom. the dom placement caused shifting of icons
|
title="View Documentation"></div>
|
||||||
because of the gap between items. simple solution is to
|
|
||||||
just wrap the target.
|
|
||||||
-->
|
|
||||||
@if (hasComments(item)) {
|
@if (hasComments(item)) {
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -72,6 +72,8 @@ export class ControllerServiceTable {
|
||||||
|
|
||||||
@Output() selectControllerService: EventEmitter<ControllerServiceEntity> =
|
@Output() selectControllerService: EventEmitter<ControllerServiceEntity> =
|
||||||
new EventEmitter<ControllerServiceEntity>();
|
new EventEmitter<ControllerServiceEntity>();
|
||||||
|
@Output() viewControllerServiceDocumentation: EventEmitter<ControllerServiceEntity> =
|
||||||
|
new EventEmitter<ControllerServiceEntity>();
|
||||||
@Output() deleteControllerService: EventEmitter<ControllerServiceEntity> =
|
@Output() deleteControllerService: EventEmitter<ControllerServiceEntity> =
|
||||||
new EventEmitter<ControllerServiceEntity>();
|
new EventEmitter<ControllerServiceEntity>();
|
||||||
@Output() configureControllerService: EventEmitter<ControllerServiceEntity> =
|
@Output() configureControllerService: EventEmitter<ControllerServiceEntity> =
|
||||||
|
@ -117,6 +119,11 @@ export class ControllerServiceTable {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewDocumentationClicked(entity: ControllerServiceEntity, event: MouseEvent): void {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.viewControllerServiceDocumentation.next(entity);
|
||||||
|
}
|
||||||
|
|
||||||
hasErrors(entity: ControllerServiceEntity): boolean {
|
hasErrors(entity: ControllerServiceEntity): boolean {
|
||||||
return !this.nifiCommon.isEmpty(entity.component.validationErrors);
|
return !this.nifiCommon.isEmpty(entity.component.validationErrors);
|
||||||
}
|
}
|
||||||
|
@ -236,7 +243,7 @@ export class ControllerServiceTable {
|
||||||
this.isDisabled(entity) &&
|
this.isDisabled(entity) &&
|
||||||
this.canRead(entity) &&
|
this.canRead(entity) &&
|
||||||
this.canWrite(entity) &&
|
this.canWrite(entity) &&
|
||||||
entity.component.multipleVersionsAvailable === true
|
entity.component.multipleVersionsAvailable
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<button mat-menu-item class="global-menu-item">
|
<button mat-menu-item class="global-menu-item" [routerLink]="['/documentation']">
|
||||||
<i class="fa fa-fw fa-question-circle mr-2"></i>
|
<i class="fa fa-fw fa-question-circle mr-2"></i>
|
||||||
Help
|
Help
|
||||||
</button>
|
</button>
|
||||||
|
@ -144,7 +144,10 @@
|
||||||
<i class="fa fa-fw fa-info-circle mr-2"></i>
|
<i class="fa fa-fw fa-info-circle mr-2"></i>
|
||||||
About
|
About
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item [matMenuTriggerFor]="theming">Appearance</button>
|
<button mat-menu-item [matMenuTriggerFor]="theming">
|
||||||
|
<i class="fa fa-fw mr-2"></i>
|
||||||
|
Appearance
|
||||||
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
<mat-menu #theming="matMenu" xPosition="before">
|
<mat-menu #theming="matMenu" xPosition="before">
|
||||||
<button mat-menu-item class="global-menu-item" (click)="toggleTheme(LIGHT_THEME)">
|
<button mat-menu-item class="global-menu-item" (click)="toggleTheme(LIGHT_THEME)">
|
||||||
|
|
Loading…
Reference in New Issue