mirror of
https://github.com/apache/nifi.git
synced 2025-02-06 10:08:42 +00:00
NIFI-13112: (#8711)
- Fixing linking to non canvas items. - Adding a tooltip to render search match details. This closes #8711
This commit is contained in:
parent
0e373e9c21
commit
2c43a706f8
@ -128,7 +128,6 @@
|
|||||||
}
|
}
|
||||||
"></ng-container>
|
"></ng-container>
|
||||||
}
|
}
|
||||||
<!-- TODO - Handling linking to Controller Services, Parameter Providers, Parameter Contexts, and Parameters -->
|
|
||||||
@if (controllerServiceNodeResults.length > 0) {
|
@if (controllerServiceNodeResults.length > 0) {
|
||||||
<ng-container
|
<ng-container
|
||||||
*ngTemplateOutlet="
|
*ngTemplateOutlet="
|
||||||
@ -186,31 +185,81 @@
|
|||||||
#searchInput="cdkOverlayOrigin"
|
#searchInput="cdkOverlayOrigin"
|
||||||
formControlName="searchBar" />
|
formControlName="searchBar" />
|
||||||
<ng-template #renderResults let-results let-header="header" let-icon="icon" let-path="path">
|
<ng-template #renderResults let-results let-header="header" let-icon="icon" let-path="path">
|
||||||
<li class="flex items-center">
|
@if (results.length > 0) {
|
||||||
<span class="icon mr-1" [class]="icon"></span>
|
<li class="flex items-center">
|
||||||
<span class="font-medium">{{ header }}</span>
|
<span class="icon mr-1 accent-color" [class]="icon"></span>
|
||||||
</li>
|
<span class="font-medium">{{ header }}</span>
|
||||||
<!-- TODO - Consider showing more context of match like existing UI -->
|
</li>
|
||||||
@for (result of results; track result) {
|
@for (result of results; track result) {
|
||||||
<li class="ml-2 py-1">
|
<li class="ml-4 py-1 flex gap-x-2 items-center">
|
||||||
@if (!result.parentGroup) {
|
<i
|
||||||
<a [routerLink]="['/process-groups', result.id]">
|
class="fa fa-info-circle on-surface-medium"
|
||||||
{{ result.name }}
|
nifiTooltip
|
||||||
</a>
|
[tooltipComponentType]="SearchMatchTip"
|
||||||
} @else {
|
[tooltipInputData]="getSearchMatchTipInput(result)"
|
||||||
@if (result.parentGroup.id == currentProcessGroupId) {
|
[delayClose]="false"></i>
|
||||||
|
@if (header === 'Parameters') {
|
||||||
<a
|
<a
|
||||||
(click)="componentLinkClicked(path, result.id)"
|
class="w-full overflow-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
[routerLink]="['/process-groups', result.parentGroup.id, path, result.id]">
|
[title]="result.name"
|
||||||
|
[routerLink]="['/parameter-contexts', result.parentGroup.id]">
|
||||||
|
{{ result.name }}
|
||||||
|
</a>
|
||||||
|
} @else if (header === 'Parameter Contexts') {
|
||||||
|
<a
|
||||||
|
class="w-full overflow-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
|
[title]="result.name"
|
||||||
|
[routerLink]="['/parameter-contexts', result.id]">
|
||||||
|
{{ result.name }}
|
||||||
|
</a>
|
||||||
|
} @else if (header === 'Parameter Providers') {
|
||||||
|
<a
|
||||||
|
class="w-full overflow-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
|
[title]="result.name"
|
||||||
|
[routerLink]="['/settings', 'parameter-providers', result.parentGroup.id]">
|
||||||
|
{{ result.name }}
|
||||||
|
</a>
|
||||||
|
} @else if (header === 'Controller Services') {
|
||||||
|
<a
|
||||||
|
class="w-full overflow-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
|
[title]="result.name"
|
||||||
|
[routerLink]="[
|
||||||
|
'/process-groups',
|
||||||
|
result.parentGroup.id,
|
||||||
|
'controller-services',
|
||||||
|
result.id
|
||||||
|
]">
|
||||||
{{ result.name ? result.name : result.id }}
|
{{ result.name ? result.name : result.id }}
|
||||||
</a>
|
</a>
|
||||||
} @else {
|
} @else {
|
||||||
<a [routerLink]="['/process-groups', result.parentGroup.id, path, result.id]">
|
@if (!result.parentGroup) {
|
||||||
{{ result.name ? result.name : result.id }}
|
<a
|
||||||
</a>
|
class="w-full overflow-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
|
[title]="result.name"
|
||||||
|
[routerLink]="['/process-groups', result.id]">
|
||||||
|
{{ result.name }}
|
||||||
|
</a>
|
||||||
|
} @else {
|
||||||
|
@if (result.parentGroup.id == currentProcessGroupId) {
|
||||||
|
<a
|
||||||
|
class="w-full overflow-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
|
(click)="componentLinkClicked(path, result.id)"
|
||||||
|
[title]="result.name"
|
||||||
|
[routerLink]="['/process-groups', result.parentGroup.id, path, result.id]">
|
||||||
|
{{ result.name ? result.name : result.id }}
|
||||||
|
</a>
|
||||||
|
} @else {
|
||||||
|
<a
|
||||||
|
class="w-full overflow-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
|
[title]="result.name"
|
||||||
|
[routerLink]="['/process-groups', result.parentGroup.id, path, result.id]">
|
||||||
|
{{ result.name ? result.name : result.id }}
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
</li>
|
||||||
</li>
|
}
|
||||||
}
|
}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</form>
|
</form>
|
||||||
|
@ -27,7 +27,7 @@ import {
|
|||||||
OriginConnectionPosition,
|
OriginConnectionPosition,
|
||||||
OverlayConnectionPosition
|
OverlayConnectionPosition
|
||||||
} from '@angular/cdk/overlay';
|
} from '@angular/cdk/overlay';
|
||||||
import { ComponentType } from '../../../../../../state/shared';
|
import { ComponentType, SearchMatchTipInput } from '../../../../../../state/shared';
|
||||||
import { NgTemplateOutlet } from '@angular/common';
|
import { NgTemplateOutlet } from '@angular/common';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
@ -37,6 +37,8 @@ import { Store } from '@ngrx/store';
|
|||||||
import { centerSelectedComponents, setAllowTransition } from '../../../../state/flow/flow.actions';
|
import { centerSelectedComponents, setAllowTransition } from '../../../../state/flow/flow.actions';
|
||||||
import { selectCurrentRoute } from '../../../../../../state/router/router.selectors';
|
import { selectCurrentRoute } from '../../../../../../state/router/router.selectors';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
import { NifiTooltipDirective } from '../../../../../../ui/common/tooltips/nifi-tooltip.directive';
|
||||||
|
import { SearchMatchTip } from '../../../../../../ui/common/tooltips/search-match-tip/search-match-tip.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'search',
|
selector: 'search',
|
||||||
@ -50,11 +52,13 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||||||
NgTemplateOutlet,
|
NgTemplateOutlet,
|
||||||
RouterLink,
|
RouterLink,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
MatInputModule
|
MatInputModule,
|
||||||
|
NifiTooltipDirective
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class Search implements OnInit {
|
export class Search implements OnInit {
|
||||||
protected readonly ComponentType = ComponentType;
|
protected readonly ComponentType = ComponentType;
|
||||||
|
protected readonly SearchMatchTip = SearchMatchTip;
|
||||||
|
|
||||||
@Input() currentProcessGroupId: string = initialState.id;
|
@Input() currentProcessGroupId: string = initialState.id;
|
||||||
@ViewChild('searchInput') searchInput!: CdkOverlayOrigin;
|
@ViewChild('searchInput') searchInput!: CdkOverlayOrigin;
|
||||||
@ -190,6 +194,12 @@ export class Search implements OnInit {
|
|||||||
this.parameterResults = [];
|
this.parameterResults = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSearchMatchTipInput(result: ComponentSearchResult): SearchMatchTipInput {
|
||||||
|
return {
|
||||||
|
matches: result.matches
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
componentLinkClicked(componentType: ComponentType, id: string): void {
|
componentLinkClicked(componentType: ComponentType, id: string): void {
|
||||||
if (componentType == this.selectedComponentType && id == this.selectedComponentId) {
|
if (componentType == this.selectedComponentType && id == this.selectedComponentId) {
|
||||||
this.store.dispatch(centerSelectedComponents({ request: { allowTransition: true } }));
|
this.store.dispatch(centerSelectedComponents({ request: { allowTransition: true } }));
|
||||||
|
@ -229,6 +229,10 @@ export interface UnorderedListTipInput {
|
|||||||
items: string[];
|
items: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SearchMatchTipInput {
|
||||||
|
matches: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface ControllerServiceApi {
|
export interface ControllerServiceApi {
|
||||||
type: string;
|
type: string;
|
||||||
bundle: Bundle;
|
bundle: Bundle;
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
~ 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="tooltip">
|
||||||
|
Search matched:
|
||||||
|
<ul>
|
||||||
|
@for (match of data?.matches; track match) {
|
||||||
|
<li>{{ match }}</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</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,38 @@
|
|||||||
|
/*
|
||||||
|
* 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 { SearchMatchTip } from './search-match-tip.component';
|
||||||
|
|
||||||
|
describe('SearchMatchTip', () => {
|
||||||
|
let component: SearchMatchTip;
|
||||||
|
let fixture: ComponentFixture<SearchMatchTip>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [SearchMatchTip]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(SearchMatchTip);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -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 { Component, Input } from '@angular/core';
|
||||||
|
import { SearchMatchTipInput } from '../../../../state/shared';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'search-match-tip',
|
||||||
|
standalone: true,
|
||||||
|
templateUrl: './search-match-tip.component.html',
|
||||||
|
imports: [],
|
||||||
|
styleUrls: ['./search-match-tip.component.scss']
|
||||||
|
})
|
||||||
|
export class SearchMatchTip {
|
||||||
|
@Input() data: SearchMatchTipInput | undefined;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user