mirror of https://github.com/apache/nifi.git
General improvements (#8627)
* [NIFI-13021] - Fix - Status History dialog changes size when switching selected metric * [NIFI-13018] - Fix - Refreshing Node Status History when open for the cluster, makes the incorrect backend call * [NIFI-13023] - Fix - Right click on canvas while search results open shows browser right-click menu * [NIFI-13024] - Improvement - Support Enter to create selected extension type * [NIFI-13000] - Improvement - Prevent text selection in header, flow status, canvas, extension creation dialog table. * prettier * color udpates for new theme classes, turn of text selection on the status history charts
This commit is contained in:
parent
44852fb5d5
commit
d78e817fe8
|
@ -18,7 +18,10 @@
|
|||
<div class="flex flex-col h-screen justify-between">
|
||||
<fd-header></fd-header>
|
||||
<div class="flex-1">
|
||||
<div id="canvas-container" class="canvas-background h-full" [cdkContextMenuTriggerFor]="contextMenu.menu"></div>
|
||||
<div
|
||||
id="canvas-container"
|
||||
class="canvas-background h-full select-none"
|
||||
[cdkContextMenuTriggerFor]="contextMenu.menu"></div>
|
||||
<fd-context-menu #contextMenu [menuProvider]="canvasContextMenu" menuId="root"></fd-context-menu>
|
||||
<graph-controls></graph-controls>
|
||||
</div>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<div class="h-8 flow-status">
|
||||
<div class="h-8 flow-status select-none">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex flex-1 justify-around pr-20">
|
||||
@if (clusterSummary?.clustered) {
|
||||
|
|
|
@ -14,3 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
new-canvas-item:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.icon-import-from-registry-add:before {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
|
|
@ -18,15 +18,6 @@
|
|||
<div class="h-8 flex justify-around search-container" [class.open]="searchInputVisible">
|
||||
<button class="w-8" (click)="toggleSearchVisibility()"><i class="fa fa-search primary-color"></i></button>
|
||||
<form [formGroup]="searchForm">
|
||||
<input
|
||||
type="text"
|
||||
matInput
|
||||
placeholder="Search"
|
||||
class="search-input on-surface-default"
|
||||
[class.open]="searchInputVisible"
|
||||
cdkOverlayOrigin
|
||||
#searchInput="cdkOverlayOrigin"
|
||||
formControlName="searchBar" />
|
||||
<ng-template
|
||||
cdkConnectedOverlay
|
||||
[cdkConnectedOverlayOrigin]="searchInput"
|
||||
|
@ -34,7 +25,7 @@
|
|||
[cdkConnectedOverlayPositions]="positions"
|
||||
[cdkConnectedOverlayHasBackdrop]="true"
|
||||
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
|
||||
(backdropClick)="backdropClicked()">
|
||||
(overlayOutsideClick)="backdropClicked($event)">
|
||||
<div class="search-results w-96 border p-2 text-sm max-h-96 overflow-y-auto">
|
||||
@if (searching) {
|
||||
<div class="unset nifi-surface-default italic">Searching</div>
|
||||
|
@ -185,6 +176,15 @@
|
|||
}
|
||||
</div>
|
||||
</ng-template>
|
||||
<input
|
||||
type="text"
|
||||
matInput
|
||||
placeholder="Search"
|
||||
class="search-input on-surface-default"
|
||||
[class.open]="searchInputVisible"
|
||||
cdkOverlayOrigin
|
||||
#searchInput="cdkOverlayOrigin"
|
||||
formControlName="searchBar" />
|
||||
<ng-template #renderResults let-results let-header="header" let-icon="icon" let-path="path">
|
||||
<li class="flex items-center">
|
||||
<span class="icon mr-1" [class]="icon"></span>
|
||||
|
|
|
@ -170,7 +170,9 @@ export class Search implements OnInit {
|
|||
);
|
||||
}
|
||||
|
||||
backdropClicked() {
|
||||
backdropClicked(event: MouseEvent): void {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.searchingResultsVisible = false;
|
||||
this.searchForm.get('searchBar')?.setValue('');
|
||||
|
||||
|
|
|
@ -31,9 +31,7 @@
|
|||
<mat-progress-bar
|
||||
mode="determinate"
|
||||
[value]="versionChangeRequest.request.percentCompleted"></mat-progress-bar>
|
||||
<div class="accent-color font-medium">
|
||||
{{ versionChangeRequest.request.percentCompleted }}%
|
||||
</div>
|
||||
<div class="accent-color font-medium">{{ versionChangeRequest.request.percentCompleted }}%</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
{{ updateStep.description }}
|
||||
</div>
|
||||
@if (updateStep.failureReason) {
|
||||
<div class="fa fa-times mat-warn"></div>
|
||||
<div class="fa fa-times warn-color"></div>
|
||||
} @else {
|
||||
@if (updateStep.complete) {
|
||||
<div class="fa fa-check nifi-success-default"></div>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
formatBytes(queueSizeByteCount)
|
||||
}}) bytes
|
||||
</div>
|
||||
<div class="listing-message mat-warn">
|
||||
<div class="listing-message warn-color">
|
||||
@if (sourceRunning && destinationRunning) {
|
||||
The source and destination of this queue are currently running. This listing may no longer be accurate.
|
||||
} @else {
|
||||
|
|
|
@ -38,9 +38,7 @@
|
|||
<td mat-cell *matCellDef="let item">
|
||||
<div class="flex items-center gap-x-3">
|
||||
@if (isSyncedToParameterContext(item)) {
|
||||
<div
|
||||
class="fa fa-star primary-color"
|
||||
title="Synced to a parameter context."></div>
|
||||
<div class="fa fa-star primary-color" title="Synced to a parameter context."></div>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
|
|
|
@ -34,9 +34,7 @@
|
|||
@if (canRead(item)) {
|
||||
<div class="flex items-center gap-x-3">
|
||||
<!-- TODO: open details -->
|
||||
<div
|
||||
class="pointer fa fa-info-circle primary-color"
|
||||
title="View details"></div>
|
||||
<div class="pointer fa fa-info-circle primary-color" title="View details"></div>
|
||||
|
||||
<div
|
||||
class="pointer fa fa-book primary-color"
|
||||
|
|
|
@ -22,7 +22,7 @@ import { NiFiState } from '../index';
|
|||
import { StatusHistoryService } from '../../service/status-history.service';
|
||||
import * as StatusHistoryActions from './status-history.actions';
|
||||
import { StatusHistoryRequest } from './index';
|
||||
import { catchError, from, map, of, switchMap, tap } from 'rxjs';
|
||||
import { catchError, filter, from, map, of, switchMap, tap } from 'rxjs';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { StatusHistory } from '../../ui/common/status-history/status-history.component';
|
||||
|
||||
|
@ -35,10 +35,11 @@ export class StatusHistoryEffects {
|
|||
private dialog: MatDialog
|
||||
) {}
|
||||
|
||||
reloadStatusHistory$ = createEffect(() =>
|
||||
reloadComponentStatusHistory$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(StatusHistoryActions.reloadStatusHistory),
|
||||
map((action) => action.request),
|
||||
filter((request) => !!request.componentId && !!request.componentType),
|
||||
switchMap((request: StatusHistoryRequest) =>
|
||||
from(
|
||||
this.statusHistoryService
|
||||
|
@ -67,6 +68,37 @@ export class StatusHistoryEffects {
|
|||
)
|
||||
);
|
||||
|
||||
reloadNodeStatusHistory$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(StatusHistoryActions.reloadStatusHistory),
|
||||
map((action) => action.request),
|
||||
filter((request) => !request.componentId && !request.componentType),
|
||||
switchMap(() =>
|
||||
from(
|
||||
this.statusHistoryService.getNodeStatusHistory().pipe(
|
||||
map((response: any) =>
|
||||
StatusHistoryActions.reloadStatusHistorySuccess({
|
||||
response: {
|
||||
statusHistory: {
|
||||
canRead: response.canRead,
|
||||
statusHistory: response.statusHistory
|
||||
}
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
StatusHistoryActions.statusHistoryApiError({
|
||||
error: error.error
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
getStatusHistoryAndOpenDialog$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(StatusHistoryActions.getStatusHistoryAndOpenDialog),
|
||||
|
|
|
@ -33,9 +33,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<form [formGroup]="filterForm" class="flex flex-col gap-y-2">
|
||||
<div class="accent-color font-medium">
|
||||
Displaying {{ filteredEntries }} of {{ totalEntries }}
|
||||
</div>
|
||||
<div class="accent-color font-medium">Displaying {{ filteredEntries }} of {{ totalEntries }}</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<mat-form-field>
|
||||
<mat-label>Filter</mat-label>
|
||||
|
|
|
@ -121,11 +121,7 @@
|
|||
<ng-template #service let-references>
|
||||
@if (references.length > 0) {
|
||||
<li>
|
||||
<h4>
|
||||
<span class="accent-color font-medium">Controller Services</span> ({{
|
||||
references.length
|
||||
}})
|
||||
</h4>
|
||||
<h4><span class="accent-color font-medium">Controller Services</span> ({{ references.length }})</h4>
|
||||
<div class="references">
|
||||
@for (service of references; track service) {
|
||||
<div class="flex flex-col">
|
||||
|
@ -179,9 +175,7 @@
|
|||
<ng-template #unauthorized let-references>
|
||||
@if (references.length > 0) {
|
||||
<li>
|
||||
<h4>
|
||||
<span class="accent-color font-medium">Unauthorized</span> ({{ references.length }})
|
||||
</h4>
|
||||
<h4><span class="accent-color font-medium">Unauthorized</span> ({{ references.length }})</h4>
|
||||
<div class="references">
|
||||
@for (reference of references; track reference) {
|
||||
<div class="flex">
|
||||
|
|
|
@ -114,9 +114,7 @@
|
|||
</div>
|
||||
}
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="accent-color font-medium">
|
||||
Disabling this controller service
|
||||
</div>
|
||||
<div class="accent-color font-medium">Disabling this controller service</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
getTemplateForStep(SetEnableStep.DisableService, disableRequest)
|
||||
|
@ -165,6 +163,6 @@
|
|||
<div class="complete fa fa-check nifi-success-default"></div>
|
||||
</ng-template>
|
||||
<ng-template #stepError>
|
||||
<div class="fa fa-times mat-warn"></div>
|
||||
<div class="fa fa-times warn-color"></div>
|
||||
</ng-template>
|
||||
<ng-template #stepNotStarted><div class="w-3.5"></div></ng-template>
|
||||
|
|
|
@ -94,9 +94,7 @@
|
|||
</div>
|
||||
<div class="flex flex-col gap-y-1.5">
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="accent-color font-medium">
|
||||
Enabling this controller service
|
||||
</div>
|
||||
<div class="accent-color font-medium">Enabling this controller service</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
getTemplateForStep(SetEnableStep.EnableService, enableRequest)
|
||||
|
@ -186,6 +184,6 @@
|
|||
<div class="complete fa fa-check nifi-success-default"></div>
|
||||
</ng-template>
|
||||
<ng-template #stepError>
|
||||
<div class="fa fa-times mat-warn"></div>
|
||||
<div class="fa fa-times warn-color"></div>
|
||||
</ng-template>
|
||||
<ng-template #stepNotStarted><div class="w-3.5"></div></ng-template>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<section tabindex="0">
|
||||
<section tabindex="0" (keyup)="navigateSelectionList($event)">
|
||||
<div class="extension-creation-dialog p-4 flex flex-col justify-between gap-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<h3 class="text-lg">Add {{ componentType }}</h3>
|
||||
|
@ -32,7 +32,7 @@
|
|||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="listing-table">
|
||||
<div class="listing-table select-none">
|
||||
<div class="h-96 overflow-y-auto overflow-x-hidden">
|
||||
<table
|
||||
mat-table
|
||||
|
@ -46,14 +46,27 @@
|
|||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Type</th>
|
||||
<td mat-cell *matCellDef="let item">
|
||||
<div
|
||||
class="fa"
|
||||
[class.fa-shield]="item.restricted"
|
||||
[class.mat-warn]="item.restricted"
|
||||
nifiTooltip
|
||||
[tooltipComponentType]="RestrictionsTip"
|
||||
[tooltipInputData]="getRestrictionTipData(item)"></div>
|
||||
{{ formatType(item) }}
|
||||
@if (isSelected(item)) {
|
||||
<div #selectedRow>
|
||||
<div
|
||||
class="fa"
|
||||
[class.fa-shield]="item.restricted"
|
||||
[class.warn-color]="item.restricted"
|
||||
nifiTooltip
|
||||
[tooltipComponentType]="RestrictionsTip"
|
||||
[tooltipInputData]="getRestrictionTipData(item)"></div>
|
||||
{{ formatType(item) }}
|
||||
</div>
|
||||
} @else {
|
||||
<div
|
||||
class="fa"
|
||||
[class.fa-shield]="item.restricted"
|
||||
[class.warn-color]="item.restricted"
|
||||
nifiTooltip
|
||||
[tooltipComponentType]="RestrictionsTip"
|
||||
[tooltipInputData]="getRestrictionTipData(item)"></div>
|
||||
{{ formatType(item) }}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
||||
|
@ -68,6 +68,8 @@ export class ExtensionCreation {
|
|||
|
||||
@Output() extensionTypeSelected: EventEmitter<DocumentedType> = new EventEmitter<DocumentedType>();
|
||||
|
||||
@ViewChild('selectedRow', { static: false }) selectedRow: ElementRef | null | undefined;
|
||||
|
||||
protected readonly RestrictionsTip = RestrictionsTip;
|
||||
protected readonly ControllerServiceApiTip = ControllerServiceApiTip;
|
||||
|
||||
|
@ -133,10 +135,23 @@ export class ExtensionCreation {
|
|||
return '';
|
||||
}
|
||||
|
||||
filterTypes(event: Event): void {
|
||||
filterTypes(event: KeyboardEvent): void {
|
||||
switch (event.key) {
|
||||
case 'Enter':
|
||||
case 'ArrowUp':
|
||||
case 'ArrowDown':
|
||||
// handled in navigateSelectionList
|
||||
return;
|
||||
}
|
||||
|
||||
const filterText: string = (event.target as HTMLInputElement).value;
|
||||
this.dataSource.filter = filterText.trim().toLowerCase();
|
||||
this.selectedType = null;
|
||||
|
||||
if (this.dataSource.filteredData.length > 0) {
|
||||
this.selectType(this.dataSource.filteredData[0]);
|
||||
} else {
|
||||
this.selectedType = null;
|
||||
}
|
||||
}
|
||||
|
||||
selectType(documentedType: DocumentedType): void {
|
||||
|
@ -156,6 +171,45 @@ export class ExtensionCreation {
|
|||
}
|
||||
}
|
||||
|
||||
navigateSelectionList(event: KeyboardEvent): void {
|
||||
if (this.selectedType !== null) {
|
||||
switch (event.key) {
|
||||
case 'Enter':
|
||||
this.createExtension(this.selectedType);
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
this.selectRow(-1);
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
this.selectRow(1);
|
||||
break;
|
||||
}
|
||||
if (this.selectedRow) {
|
||||
this.selectedRow?.nativeElement.scrollIntoView({
|
||||
behavior: 'instant',
|
||||
block: 'center',
|
||||
inline: 'nearest'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private selectRow(offset: number) {
|
||||
if (this.selectedType && this.dataSource.filteredData.length > 0) {
|
||||
// find the index of the currently selected row
|
||||
const selectedIndex = this.dataSource.filteredData.findIndex(
|
||||
(data) => data.type === this.selectedType?.type
|
||||
);
|
||||
|
||||
if (selectedIndex > -1) {
|
||||
const newSelectedIndex = selectedIndex + offset;
|
||||
if (newSelectedIndex > -1 && newSelectedIndex < this.dataSource.filteredData.length) {
|
||||
this.selectType(this.dataSource.filteredData[newSelectedIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortData(sort: Sort) {
|
||||
this.activeSort = sort;
|
||||
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<nav class="nifi-navigation">
|
||||
<nav class="nifi-navigation select-none">
|
||||
<div class="flex justify-between items-center h-16 pl-4">
|
||||
<div class="flex">
|
||||
<div class="h-16 w-28 mr-6 relative">
|
||||
|
|
|
@ -90,11 +90,7 @@
|
|||
<ng-template #service let-references>
|
||||
@if (references.length > 0) {
|
||||
<li>
|
||||
<h4>
|
||||
<span class="accent-color font-medium">Controller Services</span> ({{
|
||||
references.length
|
||||
}})
|
||||
</h4>
|
||||
<h4><span class="accent-color font-medium">Controller Services</span> ({{ references.length }})</h4>
|
||||
<div class="references">
|
||||
@for (service of references; track service) {
|
||||
<div class="flex flex-col">
|
||||
|
@ -132,9 +128,7 @@
|
|||
<ng-template #unauthorized let-references>
|
||||
@if (references.length > 0) {
|
||||
<li>
|
||||
<h4>
|
||||
<span class="accent-color font-medium">Unauthorized</span> ({{ references.length }})
|
||||
</h4>
|
||||
<h4><span class="accent-color font-medium">Unauthorized</span> ({{ references.length }})</h4>
|
||||
<div class="references">
|
||||
@for (reference of references; track reference) {
|
||||
<div class="flex">
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<div id="status-history-container" class="flex-1 flex flex-col">
|
||||
<div id="status-history-container" class="flex-1 flex flex-col select-none">
|
||||
<div id="status-history-chart-container" class="grow"></div>
|
||||
<div id="status-history-chart-control-container"></div>
|
||||
</div>
|
||||
|
|
|
@ -41,6 +41,11 @@
|
|||
.chart-panel {
|
||||
min-width: 495px;
|
||||
}
|
||||
|
||||
.component-details {
|
||||
min-width: 300px;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue