[NIFI-13061] replace actions with menu (#8766)

* [NIFI-13061] replace actions with menu

* Manage Access Policies for all menus

* short Go To menu option text

* align text formatting for menus

* View Clustered Details

* View User Policies menu now uses Manage Access Policies

* hide menu when action clicked

* Manage User Policies

This closes #8766
This commit is contained in:
Scott Aslan 2024-05-09 08:20:25 -04:00 committed by GitHub
parent a61bf2afc2
commit 4c68691faf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
72 changed files with 935 additions and 676 deletions

View File

@ -40,11 +40,22 @@
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (canRemove()) {
<div
class="pointer fa fa-trash primary-color"
title="Remove"
(click)="removeClicked(item)"></div>
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (canRemove()) {
<button mat-menu-item (click)="removeClicked(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Remove
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -14,11 +14,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.policy-table {
.listing-table {
.mat-column-actions {
width: 32px;
}
}
}

View File

@ -23,6 +23,8 @@ import { TenantEntity } from '../../../../../state/shared';
import { AccessPolicyEntity } from '../../../state/shared';
import { RemoveTenantFromPolicyRequest } from '../../../state/access-policy';
import { MatIconButton } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export interface TenantItem {
id: string;
@ -35,7 +37,7 @@ export interface TenantItem {
selector: 'policy-table',
standalone: true,
templateUrl: './policy-table.component.html',
imports: [MatTableModule, MatSortModule],
imports: [MatTableModule, MatSortModule, MatIconButton, MatMenu, MatMenuTrigger, MatMenuItem],
styleUrls: ['./policy-table.component.scss']
})
export class PolicyTable {

View File

@ -146,34 +146,50 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (item.status === 'CONNECTED' || item.status === 'CONNECTING') {
<div
class="pointer fa fa-power-off primary-color"
(click)="disconnect(item)"
title="Disconnect"></div>
} @else if (item.status === 'DISCONNECTED') {
<div
class="pointer fa fa-plug primary-color"
title="Connect"
(click)="connect(item)"></div>
<div
class="pointer fa fa-rotate-90 fa-upload primary-color"
title="Offload"
(click)="offload(item)"></div>
<div
class="pointer fa fa-trash primary-color"
title="Delete"
(click)="remove(item)"></div>
} @else if (item.status === 'OFFLOADED') {
<div
class="pointer fa fa-plug primary-color"
title="Connect"
(click)="connect(item)"></div>
<div
class="pointer fa fa-trash primary-color"
title="Delete"
(click)="remove(item)"></div>
@if (
item.status === 'CONNECTED' ||
item.status === 'CONNECTING' ||
item.status === 'DISCONNECTED' ||
item.status === 'OFFLOADED'
) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (item.status === 'CONNECTED' || item.status === 'CONNECTING') {
<button mat-menu-item (click)="disconnect(item)">
<i class="fa fa-power-off primary-color mr-2"></i>
Disconnect
</button>
} @else if (item.status === 'DISCONNECTED') {
<button mat-menu-item (click)="connect(item)">
<i class="fa fa-plug primary-color mr-2"></i>
Connect
</button>
<button mat-menu-item (click)="offload(item)">
<i class="fa fa-rotate-90 fa-upload primary-color mr-2"></i>
Offload
</button>
<button mat-menu-item (click)="remove(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
} @else if (item.status === 'OFFLOADED') {
<button mat-menu-item (click)="connect(item)">
<i class="fa fa-plug primary-color mr-2"></i>
Connect
</button>
<button mat-menu-item (click)="remove(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -27,11 +27,25 @@ import {
ClusterTableFilterColumn
} from '../../common/cluster-table-filter/cluster-table-filter.component';
import { CurrentUser } from '../../../../../state/current-user';
import { MatIconButton } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'cluster-node-table',
standalone: true,
imports: [MatCell, MatHeaderCell, MatSortHeader, NgClass, MatTableModule, MatSortModule, ClusterTableFilter],
imports: [
MatCell,
MatHeaderCell,
MatSortHeader,
NgClass,
MatTableModule,
MatSortModule,
ClusterTableFilter,
MatIconButton,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
templateUrl: './cluster-node-table.component.html',
styleUrl: './cluster-node-table.component.scss'
})

View File

@ -85,7 +85,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.supportsStartFlowVersioning(selection);
},
clazz: 'fa fa-upload',
text: 'Start version control',
text: 'Start Version Control',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -110,7 +110,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.supportsCommitFlowVersion(selection);
},
clazz: 'fa fa-upload',
text: 'Commit local changes',
text: 'Commit Local Changes',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -132,7 +132,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.supportsForceCommitFlowVersion(selection);
},
clazz: 'fa fa-upload',
text: 'Commit local changes',
text: 'Commit Local Changes',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -155,7 +155,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.hasLocalChanges(selection);
},
clazz: 'fa',
text: 'Show local changes',
text: 'Show Local Changes',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -174,7 +174,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.hasLocalChanges(selection);
},
clazz: 'fa fa-undo',
text: 'Revert local changes',
text: 'Revert Local Changes',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -193,7 +193,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.supportsChangeFlowVersion(selection);
},
clazz: 'fa',
text: 'Change version',
text: 'Change Version',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -215,7 +215,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.supportsStopFlowVersioning(selection);
},
clazz: 'fa',
text: 'Stop version control',
text: 'Stop Version Control',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -240,7 +240,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canReplayComponentProvenance(selection);
},
clazz: 'fa',
text: 'All nodes',
text: 'All Nodes',
action: (selection: any) => {
const selectionData = selection.datum();
this.store.dispatch(
@ -258,7 +258,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canReplayComponentProvenance(selection);
},
clazz: 'fa',
text: 'Primary node',
text: 'Primary Node',
action: (selection: any) => {
const selectionData = selection.datum();
this.store.dispatch(
@ -509,7 +509,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.supportsDownloadFlow(selection);
},
clazz: 'fa',
text: 'Without external services',
text: 'Without External Services',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -532,7 +532,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.supportsDownloadFlow(selection);
},
clazz: 'fa',
text: 'With external services',
text: 'With External Services',
action: (selection: d3.Selection<any, any, any, any>) => {
let pgId;
if (selection.empty()) {
@ -565,7 +565,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
{
condition: this.canvasActionsService.getConditionFunction('leaveGroup'),
clazz: 'fa fa-level-up',
text: 'Leave group',
text: 'Leave Group',
action: this.canvasActionsService.getActionFunction('leaveGroup')
},
{
@ -582,7 +582,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.hasDetails(selection);
},
clazz: 'fa fa-gear',
text: 'View configuration',
text: 'View Configuration',
action: (selection: d3.Selection<any, any, any, any>) => {
if (selection.empty()) {
this.store.dispatch(navigateToEditCurrentProcessGroup());
@ -689,7 +689,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.isProcessGroup(selection);
},
clazz: 'fa fa-sign-in',
text: 'Enter group',
text: 'Enter Group',
action: (selection: any) => {
const d: any = selection.datum();
@ -798,7 +798,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canAllStartTransmitting(selection);
},
clazz: 'fa fa-bullseye',
text: 'Enable transmission',
text: 'Enable Transmission',
action: this.canvasActionsService.getActionFunction('start')
},
{
@ -806,7 +806,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canAllStopTransmitting(selection);
},
clazz: 'icon icon-transmit-false',
text: 'Disable transmission',
text: 'Disable Transmission',
action: this.canvasActionsService.getActionFunction('stop')
},
{
@ -818,7 +818,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return false;
},
clazz: 'fa fa-flash',
text: 'Enable all controller services',
text: 'Enable All Controller Services',
action: () => {
// TODO - enableAllControllerServices
}
@ -829,7 +829,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return false;
},
clazz: 'fa fa-flash',
text: 'Enable all controller services',
text: 'Enable All Controller Services',
action: () => {
// TODO - enableAllControllerServices
}
@ -840,7 +840,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return false;
},
clazz: 'icon icon-enable-false',
text: 'Disable all controller services',
text: 'Disable All Controller Services',
action: () => {
// TODO - disableAllControllerServices
}
@ -851,7 +851,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return false;
},
clazz: 'icon icon-enable-false',
text: 'Disable all controller services',
text: 'Disable All Controller Services',
action: () => {
// TODO - disableAllControllerServices
}
@ -865,7 +865,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
},
clazz: 'icon icon-provenance',
// imgStyle: 'context-menu-provenance',
text: 'View data provenance',
text: 'View Data Provenance',
action: (selection: any) => {
const selectionData = selection.datum();
this.store.dispatch(
@ -877,7 +877,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
},
{
clazz: 'fa fa-repeat',
text: 'Replay last event',
text: 'Replay Last Event',
subMenuId: this.PROVENANCE_REPLAY.id
},
{
@ -888,7 +888,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canViewStatusHistory(selection);
},
clazz: 'fa fa-area-chart',
text: 'View status history',
text: 'View Status History',
action: (selection: any) => {
const selectionData = selection.datum();
this.store.dispatch(
@ -906,7 +906,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.isStatefulProcessor(selection);
},
clazz: 'fa fa-tasks',
text: 'View state',
text: 'View State',
action: (selection: any) => {
const selectionData = selection.datum();
this.store.dispatch(
@ -925,7 +925,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.isConnection(selection);
},
clazz: 'fa fa-list',
text: 'List queue',
text: 'List Queue',
action: (selection: any) => {
const selectionData = selection.datum();
this.store.dispatch(
@ -946,7 +946,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
);
},
clazz: 'fa fa-book',
text: 'View documentation',
text: 'View Documentation',
action: (selection: any) => {
const selectionData = selection.datum();
this.store.dispatch(
@ -963,7 +963,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
},
{
clazz: 'icon icon-connect',
text: 'View connections',
text: 'View Connections',
subMenuId: this.UPSTREAM_DOWNSTREAM.id
},
{
@ -974,7 +974,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canRead(selection) && this.canvasUtils.isRemoteProcessGroup(selection);
},
clazz: 'fa fa-refresh',
text: 'Refresh remote',
text: 'Refresh Remote',
action: (selection: any) => {
const d = selection.datum();
const id = d.id;
@ -994,7 +994,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canRead(selection) && this.canvasUtils.isRemoteProcessGroup(selection);
},
clazz: 'fa fa-cloud',
text: 'Manage remote ports',
text: 'Manage Remote Ports',
action: (selection: any) => {
const selectionData = selection.datum();
@ -1014,7 +1014,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
);
},
clazz: 'fa fa-key',
text: 'Manage access policies',
text: 'Manage Access Policies',
action: (selection: any) => {
this.canvasActionsService.getActionFunction('manageAccess')(selection, {
processGroupId: this.canvasUtils.getProcessGroupId()
@ -1026,7 +1026,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canChangeProcessorVersion(selection);
},
clazz: 'fa fa-exchange',
text: 'Change version',
text: 'Change Version',
action: (selection: d3.Selection<any, any, any, any>) => {
const data = selection.datum();
this.store.dispatch(
@ -1050,7 +1050,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.isConnection(selection);
},
clazz: 'fa fa-long-arrow-left',
text: 'Go to source',
text: 'Go To Source',
action: (selection: d3.Selection<any, any, any, any>) => {
const selectionData = selection.datum();
const remoteConnectableType: string = this.canvasUtils.getConnectableTypeForSource(
@ -1091,7 +1091,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.isConnection(selection);
},
clazz: 'fa fa-long-arrow-right',
text: 'Go to destination',
text: 'Go To Destination',
action: (selection: d3.Selection<any, any, any, any>) => {
const selectionData = selection.datum();
const remoteConnectableType: string = this.canvasUtils.getConnectableTypeForDestination(
@ -1140,7 +1140,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canMoveToFront(selection);
},
clazz: 'fa fa-clone',
text: 'Bring to front',
text: 'Bring To Front',
action: (selection: d3.Selection<any, any, any, any>) => {
const selectionData = selection.datum();
@ -1162,7 +1162,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return !selection.empty();
},
clazz: 'fa fa-crosshairs',
text: 'Center in view',
text: 'Center In View',
action: () => {
this.store.dispatch(centerSelectedComponents({ request: { allowTransition: true } }));
}
@ -1173,7 +1173,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return false;
},
clazz: 'fa fa-paint-brush',
text: 'Change color',
text: 'Change Color',
action: () => {
// TODO - fillColor
}
@ -1183,7 +1183,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.canRead(selection) && this.canvasUtils.isRemoteProcessGroup(selection);
},
clazz: 'fa fa-external-link',
text: 'Go to',
text: 'Go To',
action: (selection: d3.Selection<any, any, any, any>) => {
const selectionData = selection.datum();
const uri = selectionData.component.targetUri;
@ -1199,7 +1199,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.isNotRootGroup();
},
clazz: 'fa fa-arrows',
text: 'Move to parent group',
text: 'Move To Parent Group',
action: (selection: d3.Selection<any, any, any, any>) => {
const components: MoveComponentRequest[] = [];
selection.each(function (d: any) {
@ -1234,7 +1234,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
},
{
clazz: 'fa',
text: 'Download flow definition',
text: 'Download Flow Definition',
subMenuId: this.DOWNLOAD.id
},
{
@ -1269,7 +1269,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return this.canvasUtils.isConnection(selection);
},
clazz: 'fa fa-minus-circle',
text: 'Empty queue',
text: 'Empty Queue',
action: (selection: any) => {
const selectionData = selection.datum();
@ -1287,7 +1287,7 @@ export class CanvasContextMenu implements ContextMenuDefinitionProvider {
return selection.empty() || this.canvasUtils.isProcessGroup(selection);
},
clazz: 'fa fa-minus-circle',
text: 'Empty all queues',
text: 'Empty All Queues',
action: (selection: any) => {
let processGroupId: string;
if (selection.empty()) {

View File

@ -67,10 +67,19 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-long-arrow-right primary-color"
title="Go To"
(click)="goToClicked(item)"></div>
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="goToClicked(item)">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go To
</button>
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -26,6 +26,8 @@ import { ComponentDifference, NavigateToComponentRequest } from '../../../../../
import { debounceTime } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ComponentType } from '../../../../../../../../state/shared';
import { MatIconButton } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
interface LocalChange {
componentType: ComponentType;
@ -39,7 +41,18 @@ interface LocalChange {
@Component({
selector: 'local-changes-table',
standalone: true,
imports: [MatFormField, MatInput, MatLabel, ReactiveFormsModule, MatTableModule, MatSortModule],
imports: [
MatFormField,
MatInput,
MatLabel,
ReactiveFormsModule,
MatTableModule,
MatSortModule,
MatIconButton,
MatMenu,
MatMenuTrigger,
MatMenuItem
],
templateUrl: './local-changes-table.html',
styleUrl: './local-changes-table.scss'
})

View File

@ -188,31 +188,52 @@
<td mat-cell *matCellDef="let port">
<div class="flex items-center justify-end gap-x-2">
@if (
port.exists === true &&
port.connected === true &&
port.transmitting === false
(port.exists === true &&
port.connected === true &&
port.transmitting === false) ||
(currentRpg && port.transmitting) ||
(currentRpg && port.connected && port.exists)
) {
<div
class="pointer fa fa-cog primary-color"
(click)="configureClicked(port, $event)"
title="Edit Port"></div>
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (
port.exists === true &&
port.connected === true &&
port.transmitting === false
) {
<button mat-menu-item (click)="configureClicked(port)">
<i class="fa fa-cog primary-color mr-2"></i>
Edit Port
</button>
}
@if (currentRpg) {
@if (port.transmitting) {
<div
class="pointer success-color fa fa-bullseye"
(click)="toggleTransmission(port)"
title="Transmitting: click to toggle port transmission"></div>
} @else {
@if (port.connected && port.exists) {
<div
class="pointer not-transmitting icon icon-transmit-false surface-color"
(click)="toggleTransmission(port)"
title="Not Transmitting: click to toggle port transmission"></div>
@if (currentRpg) {
@if (port.transmitting) {
<button mat-menu-item (click)="toggleTransmission(port)">
<i
class="fa fa-bullseye transmitting primary-color mr-2"></i>
Transmitting: click to toggle port transmission
</button>
} @else {
@if (port.connected && port.exists) {
<button
mat-menu-item
(click)="toggleTransmission(port)">
<i
class="not-transmitting icon icon-transmit-false primary-color mr-2"></i>
Not Transmitting: click to toggle port transmission
</button>
}
}
}
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -33,10 +33,6 @@
.mat-column-name {
width: 25%;
}
.mat-column-actions {
width: 52px;
}
}
}
}

View File

@ -230,8 +230,7 @@ export class ManageRemotePorts implements OnDestroy {
return entity.type || '';
}
configureClicked(port: PortSummary, event: MouseEvent): void {
event.stopPropagation();
configureClicked(port: PortSummary): void {
this.store.dispatch(
navigateToEditPort({
id: port.id

View File

@ -32,6 +32,7 @@ import { ManageRemotePortsEffects } from '../../state/manage-remote-ports/manage
import { remotePortsFeatureKey } from '../../state/manage-remote-ports';
import { manageRemotePortsReducer } from '../../state/manage-remote-ports/manage-remote-ports.reducer';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@NgModule({
declarations: [ManageRemotePorts],
@ -48,7 +49,10 @@ import { MatButtonModule } from '@angular/material/button';
MatTableModule,
MatSortModule,
NifiTooltipDirective,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
]
})
export class ManageRemotePortsModule {}

View File

@ -26,6 +26,7 @@ import { ParameterContextTable } from './parameter-context-table/parameter-conte
import { MatDialogModule } from '@angular/material/dialog';
import { RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@NgModule({
declarations: [ParameterContextListing, ParameterContextTable],
@ -38,7 +39,10 @@ import { MatButtonModule } from '@angular/material/button';
MatDialogModule,
NifiTooltipDirective,
RouterLink,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
]
})
export class ParameterContextListingModule {}

View File

@ -58,32 +58,52 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (canRead(item)) {
<div
class="pointer fa fa-cog primary-color"
(click)="editClicked(item, $event)"
[title]="canWrite(item) ? 'Edit' : 'View Configuration'"></div>
}
@if (canDelete(item)) {
<div
class="pointer fa fa-trash primary-color"
(click)="deleteClicked(item, $event)"
title="Delete"></div>
}
@if (canManageAccessPolicies()) {
<div
class="pointer fa fa-key primary-color"
(click)="$event.stopPropagation()"
[routerLink]="getPolicyLink(item)"
title="Access Policies"></div>
}
@if (canGoToParameterProvider(item)) {
<div
class="pointer fa fa-long-arrow-right primary-color"
(click)="$event.stopPropagation()"
[routerLink]="getParameterProviderLink(item)"
title="Go to Parameter Provider"></div>
@if (
canRead(item) ||
canDelete(item) ||
canManageAccessPolicies() ||
canGoToParameterProvider(item)
) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (canRead(item)) {
<button mat-menu-item (click)="editClicked(item)">
<i class="fa fa-cog primary-color mr-2"></i>
{{ canWrite(item) ? 'Edit' : 'View Configuration' }}
</button>
}
@if (canDelete(item)) {
<button mat-menu-item (click)="deleteClicked(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
}
@if (canManageAccessPolicies()) {
<button
mat-menu-item
(click)="$event.stopPropagation()"
[routerLink]="getPolicyLink(item)">
<i class="fa fa-key primary-color mr-2"></i>
Manage Access Policies
</button>
}
@if (canGoToParameterProvider(item)) {
<button
mat-menu-item
(click)="$event.stopPropagation()"
[routerLink]="getParameterProviderLink(item)">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go to Parameter Provider
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -80,8 +80,7 @@ export class ParameterContextTable {
return this.canRead(entity) ? entity.component.description : '';
}
editClicked(entity: ParameterContextEntity, event: MouseEvent): void {
event.stopPropagation();
editClicked(entity: ParameterContextEntity): void {
this.editParameterContext.next(entity);
}
@ -92,8 +91,7 @@ export class ParameterContextTable {
return canModifyParameterContexts && this.canRead(entity) && this.canWrite(entity);
}
deleteClicked(entity: ParameterContextEntity, event: MouseEvent): void {
event.stopPropagation();
deleteClicked(entity: ParameterContextEntity): void {
this.deleteParameterContext.next(entity);
}

View File

@ -101,25 +101,42 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (canGoToParameter(item)) {
<div
class="pointer fa fa-long-arrow-right primary-color"
[routerLink]="getParameterLink(item)"
mat-dialog-close="ROUTED"
title="Go to"></div>
}
@if (canEdit(item) && !isDisabled) {
<div
class="pointer fa fa-cog primary-color"
(click)="editClicked(item)"
title="Edit"></div>
}
@if (canDelete(item) && !isDisabled) {
<div
class="pointer fa fa-trash primary-color"
(click)="deleteClicked(item)"
title="Delete"></div>
@if (
canGoToParameter(item) ||
(canEdit(item) && !isDisabled) ||
(canDelete(item) && !isDisabled)
) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (canGoToParameter(item)) {
<button
mat-menu-item
[routerLink]="getParameterLink(item)"
mat-dialog-close="ROUTED">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go to
</button>
}
@if (canEdit(item) && !isDisabled) {
<button mat-menu-item (click)="editClicked(item)">
<i class="fa fa-cog primary-color mr-2"></i>
Edit
</button>
}
@if (canDelete(item) && !isDisabled) {
<button mat-menu-item (click)="deleteClicked(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -20,11 +20,5 @@
.parameter-table {
.listing-table {
@include mat.table-density(-4);
table {
.mat-column-actions {
width: 74px;
}
}
}
}

View File

@ -33,6 +33,7 @@ import { Store } from '@ngrx/store';
import { ParameterContextListingState } from '../../../state/parameter-context-listing';
import { showOkDialog } from '../../../state/parameter-context-listing/parameter-context-listing.actions';
import { MatSortModule, Sort } from '@angular/material/sort';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export interface ParameterItem {
deleted: boolean;
@ -56,7 +57,10 @@ export interface ParameterItem {
RouterLink,
AsyncPipe,
NifiTooltipDirective,
ParameterReferences
ParameterReferences,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
styleUrls: ['./parameter-table.component.scss'],
providers: [

View File

@ -148,16 +148,25 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer icon icon-lineage primary-color"
(click)="showLineageGraph(item)"
title="Show Lineage"></div>
@if (supportsGoTo(item)) {
<div
class="pointer fa fa-long-arrow-right primary-color"
title="Go To"
(click)="goToClicked(item)"></div>
}
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="showLineageGraph(item)">
<i class="icon icon-lineage primary-color mr-2"></i>
Show Lineage
</button>
@if (supportsGoTo(item)) {
<button mat-menu-item (click)="goToClicked(item)">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go To
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -41,6 +41,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ErrorBanner } from '../../../../../ui/common/error-banner/error-banner.component';
import { ClusterSummary } from '../../../../../state/cluster-summary';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'provenance-event-table',
@ -61,7 +62,10 @@ import { MatButtonModule } from '@angular/material/button';
LineageComponent,
MatSliderModule,
ErrorBanner,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
styleUrls: ['./provenance-event-table.component.scss']
})

View File

@ -125,25 +125,42 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (item.size > 0) {
<div
class="pointer fa fa-download primary-color"
title="Download content"
(click)="downloadContentClicked(item)"></div>
}
@if (contentViewerAvailable && item.size > 0) {
<div
class="pointer fa fa-eye primary-color"
title="View content"
(click)="viewContentClicked(item)"></div>
}
@if (currentUser.provenancePermissions.canRead) {
<div
class="pointer icon icon-provenance primary-color"
title="Provenance"
[routerLink]="['/provenance']"
[queryParams]="{ flowFileUuid: item.uuid }"></div>
@if (
item.size > 0 ||
(contentViewerAvailable && item.size > 0) ||
currentUser.provenancePermissions.canRead
) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (item.size > 0) {
<button mat-menu-item (click)="downloadContentClicked(item)">
<i class="fa fa-download primary-color mr-2"></i>
Download content
</button>
}
@if (contentViewerAvailable && item.size > 0) {
<button mat-menu-item (click)="viewContentClicked(item)">
<i class="fa fa-eye primary-color mr-2"></i>
View content
</button>
}
@if (currentUser.provenancePermissions.canRead) {
<button
mat-menu-item
[routerLink]="['/provenance']"
[queryParams]="{ flowFileUuid: item.uuid }">
<i class="icon icon-provenance primary-color mr-2"></i>
Provenance
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -25,10 +25,6 @@
.mat-column-flowFileUuid {
width: 25%;
}
.mat-column-actions {
width: 74px;
}
}
}
}

View File

@ -27,12 +27,14 @@ import { FlowFileSummary, ListingRequest } from '../../../state/queue-listing';
import { CurrentUser } from '../../../../../state/current-user';
import { ErrorBanner } from '../../../../../ui/common/error-banner/error-banner.component';
import { ClusterSummary } from '../../../../../state/cluster-summary';
import { MatIconButton } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'flowfile-table',
standalone: true,
templateUrl: './flowfile-table.component.html',
imports: [MatTableModule, RouterLink, ErrorBanner],
imports: [MatTableModule, RouterLink, ErrorBanner, MatIconButton, MatMenu, MatMenuItem, MatMenuTrigger],
styleUrls: ['./flowfile-table.component.scss']
})
export class FlowFileTable {

View File

@ -115,40 +115,49 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-cog primary-color"
(click)="configureClicked(item, $event)"
[title]="canConfigure(item) ? 'Edit' : 'View Configuration'"></div>
@if (canDisable(item)) {
<div
class="pointer fa icon icon-enable-false primary-color"
(click)="disableClicked(item)"
title="Disable"></div>
}
@if (canEnable(item)) {
<div
class="pointer fa fa-flash primary-color"
(click)="enabledClicked(item)"
title="Enable"></div>
}
@if (canChangeVersion(item)) {
<div
class="pointer fa fa-exchange primary-color"
(click)="changeVersionClicked(item)"
title="Change Version"></div>
}
@if (canDelete(item)) {
<div
class="pointer fa fa-trash primary-color"
(click)="deleteClicked(item)"
title="Delete"></div>
}
@if (canViewState(item)) {
<div
class="pointer fa fa-tasks primary-color"
(click)="viewStateClicked(item)"
title="View State"></div>
}
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="configureClicked(item)">
<i class="fa fa-cog primary-color mr-2"></i>
{{ canConfigure(item) ? 'Edit' : 'View Configuration' }}
</button>
@if (canDisable(item)) {
<button mat-menu-item (click)="disableClicked(item)">
<i class="icon icon-enable-false primary-color mr-2"></i>
Disable
</button>
}
@if (canEnable(item)) {
<button mat-menu-item (click)="enabledClicked(item)">
<i class="fa fa-flash primary-color mr-2"></i>
Enable
</button>
}
@if (canChangeVersion(item)) {
<button mat-menu-item (click)="changeVersionClicked(item)">
<i class="fa fa-exchange primary-color mr-2"></i>
Change Version
</button>
}
@if (canDelete(item)) {
<button mat-menu-item (click)="deleteClicked(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
}
@if (canViewState(item)) {
<button mat-menu-item (click)="viewStateClicked(item)">
<i class="fa fa-tasks primary-color mr-2"></i>
View State
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -31,6 +31,7 @@ import { BulletinsTipInput, ValidationErrorsTipInput } from '../../../../../stat
import { NifiTooltipDirective } from '../../../../../ui/common/tooltips/nifi-tooltip.directive';
import { ReportingTaskEntity } from '../../../state/reporting-tasks';
import { CurrentUser } from '../../../../../state/current-user';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'flow-analysis-rule-table',
@ -43,7 +44,10 @@ import { CurrentUser } from '../../../../../state/current-user';
MatSortModule,
NgClass,
NifiTooltipDirective,
RouterLink
RouterLink,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
styleUrls: ['./flow-analysis-rule-table.component.scss']
})
@ -212,8 +216,7 @@ export class FlowAnalysisRuleTable {
return this.canRead(entity) && this.canWrite(entity) && this.isDisabled(entity);
}
configureClicked(entity: FlowAnalysisRuleEntity, event: MouseEvent): void {
event.stopPropagation();
configureClicked(entity: FlowAnalysisRuleEntity): void {
this.configureFlowAnalysisRule.next(entity);
}

View File

@ -93,37 +93,56 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (canRead(item)) {
<div
class="pointer fa fa-cog primary-color"
(click)="configureClicked(item, $event)"
[title]="canWrite(item) ? 'Edit' : 'View Configuration'"></div>
}
@if (hasAdvancedUi(item)) {
<div
class="pointer fa fa-cogs primary-color"
(click)="advancedClicked(item, $event)"
title="Advanced"></div>
}
@if (canFetch(item)) {
<div
class="pointer fa fa-arrow-circle-down primary-color"
(click)="fetchClicked(item, $event)"
title="Fetch Parameters"></div>
}
@if (canDelete(item)) {
<div
class="pointer fa fa-trash primary-color"
(click)="deleteClicked(item, $event)"
title="Remove"></div>
}
@if (canManageAccessPolicies()) {
<div
class="pointer fa fa-key primary-color"
(click)="$event.stopPropagation()"
[routerLink]="getPolicyLink(item)"
title="Access Policies"></div>
@if (
canRead(item) ||
hasAdvancedUi(item) ||
canFetch(item) ||
canDelete(item) ||
canManageAccessPolicies()
) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (canRead(item)) {
<button mat-menu-item (click)="configureClicked(item)">
<i class="fa fa-cog primary-color mr-2"></i>
{{ canWrite(item) ? 'Edit' : 'View Configuration' }}
</button>
}
@if (hasAdvancedUi(item)) {
<button mat-menu-item (click)="advancedClicked(item)">
<i class="fa fa-cogs primary-color mr-2"></i>
Advanced
</button>
}
@if (canFetch(item)) {
<button mat-menu-item (click)="fetchClicked(item)">
<i class="fa fa-arrow-circle-down primary-color mr-2"></i>
Fetch Parameters
</button>
}
@if (canDelete(item)) {
<button mat-menu-item (click)="deleteClicked(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Remove
</button>
}
@if (canManageAccessPolicies()) {
<button
mat-menu-item
(click)="$event.stopPropagation()"
[routerLink]="getPolicyLink(item)">
<i class="fa fa-key primary-color mr-2"></i>
Manage Access Policies
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -29,6 +29,8 @@ import { ValidationErrorsTip } from '../../../../../ui/common/tooltips/validatio
import { NifiTooltipDirective } from '../../../../../ui/common/tooltips/nifi-tooltip.directive';
import { ValidationErrorsTipInput } from '../../../../../state/shared';
import { RouterLink } from '@angular/router';
import { MatIconButton } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export type SupportedColumns = 'name' | 'type' | 'bundle';
@ -42,7 +44,11 @@ export type SupportedColumns = 'name' | 'type' | 'bundle';
MatTableModule,
SummaryTableFilterModule,
NifiTooltipDirective,
RouterLink
RouterLink,
MatIconButton,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
templateUrl: './parameter-providers-table.component.html',
styleUrls: ['./parameter-providers-table.component.scss']
@ -190,23 +196,19 @@ export class ParameterProvidersTable {
});
}
configureClicked(entity: ParameterProviderEntity, event: MouseEvent) {
event.stopPropagation();
configureClicked(entity: ParameterProviderEntity) {
this.configureParameterProvider.next(entity);
}
advancedClicked(entity: ParameterProviderEntity, event: MouseEvent) {
event.stopPropagation();
advancedClicked(entity: ParameterProviderEntity) {
this.openAdvancedUi.next(entity);
}
fetchClicked(entity: ParameterProviderEntity, event: MouseEvent) {
event.stopPropagation();
fetchClicked(entity: ParameterProviderEntity) {
this.fetchParameterProvider.next(entity);
}
deleteClicked(entity: ParameterProviderEntity, event: MouseEvent) {
event.stopPropagation();
deleteClicked(entity: ParameterProviderEntity) {
this.deleteParameterProvider.next(entity);
}

View File

@ -99,18 +99,29 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (canConfigure(item)) {
<div
class="pointer fa fa-cog primary-color"
(click)="configureClicked(item, $event)"
title="Edit"></div>
}
@if (canDelete(item)) {
<div
class="pointer fa fa-trash primary-color"
(click)="deleteClicked(item, $event)"
title="Delete"></div>
@if (canConfigure(item) || canDelete(item)) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (canConfigure(item)) {
<button mat-menu-item (click)="configureClicked(item)">
<i class="fa fa-cog primary-color mr-2"></i>
Edit
</button>
}
@if (canDelete(item)) {
<button mat-menu-item (click)="deleteClicked(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -129,8 +129,7 @@ export class RegistryClientTable {
return this.canRead(entity) && this.canWrite(entity);
}
configureClicked(entity: RegistryClientEntity, event: MouseEvent): void {
event.stopPropagation();
configureClicked(entity: RegistryClientEntity): void {
this.configureRegistryClient.next(entity);
}
@ -138,8 +137,7 @@ export class RegistryClientTable {
return this.canRead(entity) && this.canWrite(entity);
}
deleteClicked(entity: RegistryClientEntity, event: MouseEvent): void {
event.stopPropagation();
deleteClicked(entity: RegistryClientEntity): void {
this.deleteRegistryClient.next(entity);
}

View File

@ -24,6 +24,7 @@ import { MatTableModule } from '@angular/material/table';
import { MatSortModule } from '@angular/material/sort';
import { NifiTooltipDirective } from '../../../../ui/common/tooltips/nifi-tooltip.directive';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@NgModule({
declarations: [RegistryClients, RegistryClientTable],
@ -34,7 +35,10 @@ import { MatButtonModule } from '@angular/material/button';
MatTableModule,
MatSortModule,
NifiTooltipDirective,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
]
})
export class RegistryClientsModule {}

View File

@ -111,53 +111,64 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-cog primary-color"
(click)="configureClicked(item, $event)"
[title]="canEdit(item) ? 'Edit' : 'View Configuration'"></div>
@if (hasAdvancedUi(item)) {
<div
class="pointer fa fa-cogs primary-color"
(click)="advancedClicked(item, $event)"
title="Advanced"></div>
}
@if (canStop(item)) {
<div
class="pointer fa fa-stop primary-color"
(click)="stopClicked(item)"
title="Stop"></div>
}
@if (canStart(item)) {
<div
class="pointer fa fa-play primary-color"
(click)="startClicked(item)"
title="Start"></div>
}
@if (canChangeVersion(item)) {
<div
class="pointer fa fa-exchange primary-color"
(click)="changeVersionClicked(item)"
title="Change Version"></div>
}
@if (canDelete(item)) {
<div
class="pointer fa fa-trash primary-color"
(click)="deleteClicked(item)"
title="Delete"></div>
}
@if (canViewState(item)) {
<div
class="pointer fa fa-tasks primary-color"
(click)="viewStateClicked(item)"
title="View State"></div>
}
@if (canManageAccessPolicies()) {
<div
class="pointer fa fa-key primary-color"
(click)="$event.stopPropagation()"
[routerLink]="getPolicyLink(item)"
title="Access Policies"></div>
}
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="configureClicked(item)">
<i class="fa fa-cog primary-color mr-2"></i>
{{ canEdit(item) ? 'Edit' : 'View Configuration' }}
</button>
@if (hasAdvancedUi(item)) {
<button mat-menu-item (click)="advancedClicked(item)">
<i class="fa fa-cogs primary-color mr-2"></i>
Advanced
</button>
}
@if (canStop(item)) {
<button mat-menu-item (click)="stopClicked(item)">
<i class="fa fa-stop primary-color mr-2"></i>
Stop
</button>
}
@if (canStart(item)) {
<button mat-menu-item (click)="startClicked(item)">
<i class="fa fa-play primary-color mr-2"></i>
Start
</button>
}
@if (canChangeVersion(item)) {
<button mat-menu-item (click)="changeVersionClicked(item)">
<i class="fa fa-exchange primary-color mr-2"></i>
Change Version
</button>
}
@if (canDelete(item)) {
<button mat-menu-item (click)="deleteClicked(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
}
@if (canViewState(item)) {
<button mat-menu-item (click)="viewStateClicked(item)">
<i class="fa fa-tasks primary-color mr-2"></i>
View State
</button>
}
@if (canManageAccessPolicies()) {
<button
mat-menu-item
(click)="$event.stopPropagation()"
[routerLink]="getPolicyLink(item)">
<i class="fa fa-key primary-color mr-2"></i>
Manage Access Policies
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -20,13 +20,5 @@
.mat-column-moreDetails {
width: 96px;
}
.mat-column-name {
width: 25%;
}
.mat-column-actions {
width: 140px; // only 6 of the 8 action icons can be present at the same time
}
}
}

View File

@ -197,8 +197,7 @@ export class ReportingTaskTable {
return this.canRead(entity) && !!entity.component.customUiUrl;
}
advancedClicked(entity: ReportingTaskEntity, event: MouseEvent): void {
event.stopPropagation();
advancedClicked(entity: ReportingTaskEntity): void {
this.openAdvancedUi.next(entity);
}
@ -238,8 +237,7 @@ export class ReportingTaskTable {
this.deleteReportingTask.next(entity);
}
configureClicked(entity: ReportingTaskEntity, event: MouseEvent): void {
event.stopPropagation();
configureClicked(entity: ReportingTaskEntity): void {
this.configureReportingTask.next(entity);
}

View File

@ -26,6 +26,7 @@ import { ReportingTaskTable } from './reporting-task-table/reporting-task-table.
import { ControllerServiceTable } from '../../../../ui/common/controller-service/controller-service-table/controller-service-table.component';
import { RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@NgModule({
declarations: [ReportingTasks, ReportingTaskTable],
@ -38,7 +39,10 @@ import { MatButtonModule } from '@angular/material/button';
NifiTooltipDirective,
ControllerServiceTable,
RouterLink,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
]
})
export class ReportingTasksModule {}

View File

@ -202,13 +202,11 @@ export abstract class ComponentStatusTable<T extends BaseSnapshotEntity> impleme
return false;
}
viewStatusHistoryClicked(event: MouseEvent, component: T): void {
event.stopPropagation();
viewStatusHistoryClicked(component: T): void {
this.viewStatusHistory.next(component);
}
viewClusteredDetailsClicked(event: MouseEvent, component: T): void {
event.stopPropagation();
viewClusteredDetailsClicked(component: T): void {
this.viewClusteredDetails.next(component);
}

View File

@ -143,17 +143,28 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-long-arrow-right primary-color"
[routerLink]="getPortLink(item)"
(click)="$event.stopPropagation()"
title="Go to {{ portType }} port"></div>
@if (connectedToCluster) {
<div
class="pointer fa fa-cubes primary-color"
title="View Clustered {{ portType | titlecase }} Port Details"
(click)="viewClusteredDetailsClicked($event, item)"></div>
}
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button
mat-menu-item
[routerLink]="getPortLink(item)"
(click)="$event.stopPropagation()">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go To {{ portType }} Port
</button>
@if (connectedToCluster) {
<button mat-menu-item (click)="viewClusteredDetailsClicked(item)">
<i class="fa fa-cubes primary-color mr-2"></i>
View Clustered Details
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -33,10 +33,5 @@
.mat-column-out {
width: 20%;
}
.mat-column-actions {
width: 52px;
min-width: 52px;
}
}
}

View File

@ -28,6 +28,7 @@ import { MatPaginatorModule } from '@angular/material/paginator';
import { PortStatusSnapshot, PortStatusSnapshotEntity } from '../../../state';
import { ComponentStatusTable } from '../component-status-table/component-status-table.component';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export type SupportedColumns = 'name' | 'runStatus' | 'in' | 'out';
@ -41,7 +42,10 @@ export type SupportedColumns = 'name' | 'runStatus' | 'in' | 'out';
MatTableModule,
RouterLink,
MatPaginatorModule,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
templateUrl: './port-status-table.component.html',
styleUrls: ['./port-status-table.component.scss']

View File

@ -214,23 +214,33 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-long-arrow-right primary-color"
[routerLink]="getConnectionLink(item)"
(click)="$event.stopPropagation()"
title="Go to connection"></div>
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button
mat-menu-item
[routerLink]="getConnectionLink(item)"
(click)="$event.stopPropagation()">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go To Connection
</button>
<button mat-menu-item (click)="viewStatusHistoryClicked(item)">
<i class="fa fa-area-chart primary-color mr-2"></i>
View Status History
</button>
<div
class="pointer fa fa-area-chart primary-color"
title="View Status History"
(click)="viewStatusHistoryClicked($event, item)"></div>
@if (connectedToCluster) {
<div
class="pointer fa fa-cubes primary-color"
title="View Clustered Connection Details"
(click)="viewClusteredDetailsClicked($event, item)"></div>
}
@if (connectedToCluster) {
<button mat-menu-item (click)="viewClusteredDetailsClicked(item)">
<i class="fa fa-cubes primary-color mr-2"></i>
View Clustered Details
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -28,6 +28,7 @@ import { MatPaginatorModule } from '@angular/material/paginator';
import { ConnectionStatusSnapshot, ConnectionStatusSnapshotEntity } from '../../../state';
import { ComponentStatusTable } from '../../common/component-status-table/component-status-table.component';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export type SupportedColumns = 'name' | 'queue' | 'in' | 'out' | 'threshold' | 'sourceName' | 'destinationName';
@ -41,7 +42,10 @@ export type SupportedColumns = 'name' | 'queue' | 'in' | 'out' | 'threshold' | '
RouterLink,
MatTableModule,
MatPaginatorModule,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
templateUrl: './connection-status-table.component.html',
styleUrls: ['./connection-status-table.component.scss']

View File

@ -320,25 +320,33 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-long-arrow-right primary-color"
[routerLink]="getProcessGroupLink(item)"
(click)="$event.stopPropagation()"
title="Go to Process Group {{
item?.processGroupStatusSnapshot?.name
}}"></div>
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button
mat-menu-item
[routerLink]="getProcessGroupLink(item)"
(click)="$event.stopPropagation()">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go To Process Group
</button>
<button mat-menu-item (click)="viewStatusHistoryClicked(item)">
<i class="fa fa-area-chart primary-color mr-2"></i>
View Status History
</button>
<div
class="pointer fa fa-area-chart primary-color"
title="View Status History"
(click)="viewStatusHistoryClicked($event, item)"></div>
@if (connectedToCluster) {
<div
class="pointer fa fa-cubes primary-color"
title="View Clustered Process Group Details"
(click)="viewClusteredDetailsClicked($event, item)"></div>
}
@if (connectedToCluster) {
<button mat-menu-item (click)="viewClusteredDetailsClicked(item)">
<i class="fa fa-cubes primary-color mr-2"></i>
View Clustered Details
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -27,6 +27,7 @@ import { MatPaginatorModule } from '@angular/material/paginator';
import { ProcessGroupStatusSnapshot, ProcessGroupStatusSnapshotEntity } from '../../../state';
import { ComponentStatusTable } from '../../common/component-status-table/component-status-table.component';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export type SupportedColumns =
| 'name'
@ -50,7 +51,10 @@ export type SupportedColumns =
SummaryTableFilterModule,
RouterLink,
MatPaginatorModule,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
templateUrl: './process-group-status-table.component.html',
styleUrls: ['./process-group-status-table.component.scss']

View File

@ -248,25 +248,33 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-long-arrow-right primary-color"
[routerLink]="getProcessorLink(item)"
(click)="$event.stopPropagation()"
title="Go to Processor in {{
item?.processorStatusSnapshot?.processGroupNamePath
}}"></div>
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button
mat-menu-item
[routerLink]="getProcessorLink(item)"
(click)="$event.stopPropagation()">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go To Processor
</button>
<button mat-menu-item (click)="viewStatusHistoryClicked(item)">
<i class="fa fa-area-chart primary-color mr-2"></i>
View Status History
</button>
<div
class="pointer fa fa-area-chart primary-color"
title="View Status History"
(click)="viewStatusHistoryClicked($event, item)"></div>
@if (connectedToCluster) {
<div
class="pointer fa fa-cubes primary-color"
title="View Clustered Processor Details"
(click)="viewClusteredDetailsClicked($event, item)"></div>
}
@if (connectedToCluster) {
<button mat-menu-item (click)="viewClusteredDetailsClicked(item)">
<i class="fa fa-cubes primary-color mr-2"></i>
View Clustered Details
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -24,10 +24,6 @@
.mat-column-name {
width: 25%;
}
.mat-column-actions {
width: 74px;
}
}
.primary-node-only {

View File

@ -28,6 +28,7 @@ import { MatPaginatorModule } from '@angular/material/paginator';
import { ProcessorStatusSnapshot, ProcessorStatusSnapshotEntity } from '../../../state';
import { ComponentStatusTable } from '../../common/component-status-table/component-status-table.component';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export type SupportedColumns = 'name' | 'type' | 'processGroup' | 'runStatus' | 'in' | 'out' | 'readWrite' | 'tasks';
@ -43,7 +44,10 @@ export type SupportedColumns = 'name' | 'type' | 'processGroup' | 'runStatus' |
MatSortModule,
NgClass,
MatPaginatorModule,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
]
})
export class ProcessorStatusTable extends ComponentStatusTable<ProcessorStatusSnapshotEntity> {

View File

@ -147,23 +147,32 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-long-arrow-right primary-color"
[routerLink]="getRemoteProcessGroupLink(item)"
(click)="$event.stopPropagation()"
title="Go to remote process group"></div>
<div
class="pointer fa fa-area-chart primary-color"
title="View Status History"
(click)="viewStatusHistoryClicked($event, item)"></div>
@if (connectedToCluster) {
<div
class="pointer fa fa-cubes primary-color"
title="View Clustered Remote Process Group Details"
(click)="viewClusteredDetailsClicked($event, item)"></div>
}
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
<button
mat-menu-item
[routerLink]="getRemoteProcessGroupLink(item)"
(click)="$event.stopPropagation()">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go To Remote Process Group
</button>
<button mat-menu-item (click)="viewStatusHistoryClicked(item)">
<i class="fa fa-area-chart primary-color mr-2"></i>
View Status History
</button>
@if (connectedToCluster) {
<button mat-menu-item (click)="viewClusteredDetailsClicked(item)">
<i class="fa fa-cubes primary-color mr-2"></i>
View Clustered Details
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -28,6 +28,7 @@ import { MatPaginatorModule } from '@angular/material/paginator';
import { RemoteProcessGroupStatusSnapshot, RemoteProcessGroupStatusSnapshotEntity } from '../../../state';
import { ComponentStatusTable } from '../../common/component-status-table/component-status-table.component';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export type SupportedColumns = 'name' | 'uri' | 'transmitting' | 'sent' | 'received';
@ -41,7 +42,10 @@ export type SupportedColumns = 'name' | 'uri' | 'transmitting' | 'sent' | 'recei
MatTableModule,
RouterLink,
MatPaginatorModule,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
templateUrl: './remote-process-group-status-table.component.html',
styleUrls: ['./remote-process-group-status-table.component.scss']

View File

@ -59,15 +59,28 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
@if (canGoToPolicyTarget(item)) {
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-long-arrow-right primary-color"
[routerLink]="getPolicyTargetLink(item)"
mat-dialog-close="ROUTED"
title="Go to"></div>
</div>
}
<div class="flex items-center justify-end gap-x-2">
@if (canGoToPolicyTarget(item)) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (canGoToPolicyTarget(item)) {
<button
mat-menu-item
[routerLink]="getPolicyTargetLink(item)"
mat-dialog-close="ROUTED">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go to
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -19,14 +19,4 @@
.user-access-policies {
@include mat.button-density(-1);
font-size: 14px;
.listing-table {
table {
.mat-column-actions {
width: 32px;
}
}
}
}

View File

@ -30,12 +30,22 @@ import {
import { NiFiCommon } from '../../../../../service/nifi-common.service';
import { RouterLink } from '@angular/router';
import { UserAccessPoliciesDialogRequest } from '../../../state/user-listing';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'user-access-policies',
standalone: true,
templateUrl: './user-access-policies.component.html',
imports: [MatButtonModule, MatDialogModule, MatTableModule, MatSortModule, RouterLink],
imports: [
MatButtonModule,
MatDialogModule,
MatTableModule,
MatSortModule,
RouterLink,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
styleUrls: ['./user-access-policies.component.scss']
})
export class UserAccessPolicies {

View File

@ -79,24 +79,37 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (canEditOrDelete(currentUser, item)) {
<div
class="pointer fa fa-cog primary-color"
title="Edit"
(click)="editClicked(item, $event)"></div>
}
@if (canEditOrDelete(currentUser, item)) {
<div
class="pointer fa fa-trash primary-color"
title="Remove"
(click)="deleteClicked(item)"></div>
}
@if (hasAccessPolicies(item)) {
<div
class="pointer fa fa-key primary-color"
title="View User Policies"
(click)="viewAccessPoliciesClicked(item, $event)"></div>
@if (
canEditOrDelete(currentUser, item) || hasAccessPolicies(item) || hasAccessPolicies(item)
) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (canEditOrDelete(currentUser, item)) {
<button mat-menu-item (click)="editClicked(item)">
<i class="fa fa-cog primary-color mr-2"></i>
Edit
</button>
}
@if (canEditOrDelete(currentUser, item)) {
<button mat-menu-item (click)="deleteClicked(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Remove
</button>
}
@if (hasAccessPolicies(item)) {
<button mat-menu-item (click)="viewAccessPoliciesClicked(item)">
<i class="fa fa-key primary-color mr-2"></i>
Manage User Policies
</button>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -14,11 +14,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.user-table {
.listing-table {
.mat-column-actions {
width: 74px;
}
}
}

View File

@ -29,6 +29,7 @@ import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatButtonModule } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export interface TenantItem {
id: string;
@ -54,7 +55,10 @@ export interface Tenants {
MatTableModule,
MatSortModule,
MatInputModule,
MatButtonModule
MatButtonModule,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
styleUrls: ['./user-table.component.scss']
})
@ -219,8 +223,7 @@ export class UserTable implements AfterViewInit {
return this.canModifyTenants(currentUser) && item.configurable;
}
editClicked(item: TenantItem, event: MouseEvent): void {
event.stopPropagation();
editClicked(item: TenantItem): void {
this.editTenant.next(item.id);
}
@ -258,8 +261,7 @@ export class UserTable implements AfterViewInit {
return !this.nifiCommon.isEmpty(this.getAccessPolicies(item));
}
viewAccessPoliciesClicked(item: TenantItem, event: MouseEvent): void {
event.stopPropagation();
viewAccessPoliciesClicked(item: TenantItem): void {
this.viewAccessPolicies.next(item.id);
}
}

View File

@ -116,62 +116,73 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
@if (definedByCurrentGroup(item)) {
<div class="flex items-center justify-end gap-x-2">
<div
class="pointer fa fa-cog primary-color"
(click)="configureClicked(item, $event)"
[title]="canConfigure(item) ? 'Edit' : 'View Configuration'"></div>
@if (hasAdvancedUi(item)) {
<div
class="pointer fa fa-cogs primary-color"
(click)="advancedClicked(item, $event)"
title="Advanced"></div>
<div class="flex items-center justify-end gap-x-2">
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (definedByCurrentGroup(item)) {
<button mat-menu-item (click)="configureClicked(item)">
<i class="fa fa-cog primary-color mr-2"></i>
{{ canConfigure(item) ? 'Edit' : 'View Configuration' }}
</button>
@if (hasAdvancedUi(item)) {
<button mat-menu-item (click)="advancedClicked(item)">
<i class="fa fa-cogs primary-color mr-2"></i>
Advanced
</button>
}
@if (canDisable(item)) {
<button mat-menu-item (click)="disableClicked(item)">
<i class="icon icon-enable-false primary-color mr-2"></i>
Disable
</button>
}
@if (canEnable(item)) {
<button mat-menu-item (click)="enabledClicked(item)">
<i class="fa fa-flash primary-color mr-2"></i>
Enable
</button>
}
@if (canChangeVersion(item)) {
<button mat-menu-item (click)="changeVersionClicked(item)">
<i class="fa fa-exchange primary-color mr-2"></i>
Change Version
</button>
}
@if (canDelete(item)) {
<button mat-menu-item (click)="deleteClicked(item, $event)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
}
@if (canViewState(item)) {
<button mat-menu-item (click)="viewStateClicked(item)">
<i class="fa fa-tasks primary-color mr-2"></i>
View State
</button>
}
@if (canManageAccessPolicies()) {
<button
mat-menu-item
(click)="$event.stopPropagation()"
[routerLink]="getPolicyLink(item)">
<i class="fa fa-key primary-color mr-2"></i>
Manage Access Policies
</button>
}
} @else {
<button mat-menu-item [routerLink]="getServiceLink(item)">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go To
</button>
}
@if (canDisable(item)) {
<div
class="pointer icon icon-enable-false primary-color"
(click)="disableClicked(item)"
title="Disable"></div>
}
@if (canEnable(item)) {
<div
class="pointer fa fa-flash primary-color"
(click)="enabledClicked(item)"
title="Enable"></div>
}
@if (canChangeVersion(item)) {
<div
class="pointer fa fa-exchange primary-color"
(click)="changeVersionClicked(item)"
title="Change Version"></div>
}
@if (canDelete(item)) {
<div
class="pointer fa fa-trash primary-color"
(click)="deleteClicked(item, $event)"
title="Delete"></div>
}
@if (canViewState(item)) {
<div
class="pointer fa fa-tasks primary-color"
(click)="viewStateClicked(item)"
title="View State"></div>
}
@if (canManageAccessPolicies()) {
<div
class="pointer fa fa-key primary-color"
(click)="$event.stopPropagation()"
[routerLink]="getPolicyLink(item)"
title="Delete"></div>
}
</div>
} @else {
<div
class="pointer fa fa-long-arrow-right primary-color"
title="Go To"
[routerLink]="getServiceLink(item)"></div>
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -27,10 +27,6 @@
.mat-column-name {
width: 25%;
}
.mat-column-actions {
width: 140px; // only 6 of the 8 action icons can be present at the same time
}
}
}
}

View File

@ -30,6 +30,7 @@ import { ValidationErrorsTip } from '../../tooltips/validation-errors-tip/valida
import { RouterLink } from '@angular/router';
import { FlowConfiguration } from '../../../../state/flow-configuration';
import { CurrentUser } from '../../../../state/current-user';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'controller-service-table',
@ -42,7 +43,10 @@ import { CurrentUser } from '../../../../state/current-user';
MatSortModule,
NgClass,
NifiTooltipDirective,
RouterLink
RouterLink,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
styleUrls: ['./controller-service-table.component.scss']
})
@ -207,8 +211,7 @@ export class ControllerServiceTable {
return this.canRead(entity) && this.canWrite(entity) && this.isDisabled(entity);
}
configureClicked(entity: ControllerServiceEntity, event: MouseEvent): void {
event.stopPropagation();
configureClicked(entity: ControllerServiceEntity): void {
this.configureControllerService.next(entity);
}
@ -216,8 +219,7 @@ export class ControllerServiceTable {
return this.canRead(entity) && !!entity.component.customUiUrl;
}
advancedClicked(entity: ControllerServiceEntity, event: MouseEvent): void {
event.stopPropagation();
advancedClicked(entity: ControllerServiceEntity): void {
this.openAdvancedUi.next(entity);
}

View File

@ -53,7 +53,7 @@
</button>
<mat-divider></mat-divider>
<button mat-menu-item class="global-menu-item" [routerLink]="['/summary']">
<i class="fa fa-fw fa-table primary-color mr-2"></i>
<i class="fa fa-table primary-color mr-2"></i>
Summary
</button>
<button
@ -61,11 +61,11 @@
class="global-menu-item"
[routerLink]="['/counters']"
[disabled]="!user.countersPermissions.canRead">
<i class="icon fa-fw icon-counter primary-color mr-2"></i>
<i class="icon icon-counter primary-color mr-2"></i>
Counter
</button>
<button mat-menu-item class="global-menu-item" [routerLink]="['/bulletins']">
<i class="fa fa-fw fa-sticky-note-o primary-color mr-2"></i>
<i class="fa fa-sticky-note-o primary-color mr-2"></i>
Bulletin Board
</button>
<mat-divider></mat-divider>
@ -74,7 +74,7 @@
class="global-menu-item"
[routerLink]="['/provenance']"
[disabled]="!user.provenancePermissions.canRead">
<i class="icon fa-fw icon-provenance primary-color mr-2"></i>
<i class="icon icon-provenance primary-color mr-2"></i>
Data Provenance
</button>
<mat-divider></mat-divider>
@ -83,11 +83,11 @@
class="global-menu-item"
[routerLink]="['/settings']"
[disabled]="!user.controllerPermissions.canRead">
<i class="fa fa-fw fa-wrench primary-color mr-2"></i>
<i class="fa fa-wrench primary-color 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>
<i class="fa mr-2"></i>
Parameter Contexts
</button>
@if (clusterSummary()?.clustered) {
@ -96,16 +96,16 @@
class="global-menu-item"
[disabled]="!user.controllerPermissions.canRead"
[routerLink]="['/cluster']">
<i class="fa fa-fw fa-cubes primary-color mr-2"></i>
<i class="fa fa-cubes primary-color mr-2"></i>
Cluster
</button>
}
<button mat-menu-item class="global-menu-item" [routerLink]="['/flow-configuration-history']">
<i class="fa fa-fw fa-history primary-color mr-2"></i>
<i class="fa fa-history primary-color 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 primary-color mr-2"></i>
<i class="fa fa-area-chart primary-color mr-2"></i>
Node Status History
</button>
<button
@ -113,7 +113,7 @@
class="global-menu-item"
[disabled]="!user.systemPermissions.canRead"
(click)="viewSystemDiagnostics()">
<i class="fa fa-fw mr-2"></i>
<i class="fa mr-2"></i>
System Diagnostics
</button>
@if (flowConfiguration(); as flowConfig) {
@ -124,7 +124,7 @@
class="global-menu-item"
[routerLink]="['/users']"
[disabled]="!user.tenantsPermissions.canRead">
<i class="fa fa-fw fa-users primary-color mr-2"></i>
<i class="fa fa-users primary-color mr-2"></i>
Users
</button>
<button
@ -136,50 +136,50 @@
!user.policiesPermissions.canRead ||
!user.policiesPermissions.canWrite
">
<i class="fa fa-fw fa-key primary-color mr-2"></i>
<i class="fa fa-key primary-color mr-2"></i>
Policies
</button>
<mat-divider></mat-divider>
}
}
<button mat-menu-item class="global-menu-item" [routerLink]="['/documentation']">
<i class="fa fa-fw fa-question-circle primary-color mr-2"></i>
<i class="fa fa-question-circle primary-color mr-2"></i>
Help
</button>
<button mat-menu-item class="global-menu-item" (click)="viewAbout()">
<i class="fa fa-fw fa-info-circle primary-color mr-2"></i>
<i class="fa fa-info-circle primary-color mr-2"></i>
About
</button>
<button mat-menu-item [matMenuTriggerFor]="theming">
<i class="fa fa-fw mr-2"></i>
<i class="fa mr-2"></i>
Appearance
</button>
</mat-menu>
<mat-menu #theming="matMenu" xPosition="before">
<button mat-menu-item class="global-menu-item" (click)="toggleTheme(LIGHT_THEME)">
@if (theme === LIGHT_THEME) {
<i class="fa fa-fw fa-check primary-color mr-2"></i>
<i class="fa fa-check primary-color mr-2"></i>
}
@if (theme !== LIGHT_THEME) {
<i class="fa fa-fw mr-2"></i>
<i class="fa mr-2"></i>
}
Light
</button>
<button mat-menu-item class="global-menu-item" (click)="toggleTheme(DARK_THEME)">
@if (theme === DARK_THEME) {
<i class="fa fa-fw fa-check primary-color mr-2"></i>
<i class="fa fa-check primary-color mr-2"></i>
}
@if (theme !== DARK_THEME) {
<i class="fa fa-fw mr-2"></i>
<i class="fa mr-2"></i>
}
Dark
</button>
<button mat-menu-item class="global-menu-item" (click)="toggleTheme(OS_SETTING)">
@if (theme === OS_SETTING || theme === null) {
<i class="fa fa-fw fa-check primary-color mr-2"></i>
<i class="fa fa-check primary-color mr-2"></i>
}
@if (theme !== OS_SETTING && theme !== null) {
<i class="fa fa-fw mr-2"></i>
<i class="fa mr-2"></i>
}
Device
</button>

View File

@ -103,38 +103,57 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let item">
<div class="flex items-center justify-end gap-x-2">
@if (canGoToParameter(item)) {
<div
class="pointer fa fa-long-arrow-right primary-color"
(click)="goToParameterClicked(item)"
title="Go to Parameter"></div>
@if (
canGoToParameter(item) ||
canGoToService(item) ||
(!isDisabled
? item.descriptor.identifiesControllerService ||
canConvertToParameter(item) ||
item.type == 'userDefined'
: false)
) {
<button
mat-icon-button
type="button"
[matMenuTriggerFor]="actionMenu"
class="h-16 w-16 flex items-center justify-center icon global-menu">
<i class="fa fa-ellipsis-v"></i>
</button>
}
@if (canGoToService(item)) {
<div
class="pointer fa fa-long-arrow-right primary-color"
(click)="goToServiceClicked(item)"
title="Go to Service"></div>
}
@if (!isDisabled) {
@if (item.descriptor.identifiesControllerService) {
<div
class="pointer fa fa-plus primary-color"
(click)="createNewControllerService(item)"
title="Create new service"></div>
<mat-menu #actionMenu="matMenu" xPosition="before">
@if (canGoToParameter(item)) {
<button mat-menu-item (click)="goToParameterClicked(item)">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go to Parameter
</button>
}
@if (canConvertToParameter(item)) {
<div
class="pointer fa fa-level-up primary-color"
(click)="convertToParameterClicked(item)"
title="Convert to Parameter"></div>
@if (canGoToService(item)) {
<button mat-menu-item (click)="goToServiceClicked(item)">
<i class="fa fa-long-arrow-right primary-color mr-2"></i>
Go to Service
</button>
}
@if (item.type == 'userDefined') {
<div
class="pointer fa fa-trash primary-color"
(click)="deleteProperty(item)"
title="Delete"></div>
@if (!isDisabled) {
@if (item.descriptor.identifiesControllerService) {
<button mat-menu-item (click)="createNewControllerService(item)">
<i class="fa fa-plus primary-color mr-2"></i>
Create new service
</button>
}
@if (canConvertToParameter(item)) {
<button mat-menu-item (click)="convertToParameterClicked(item)">
<i class="fa fa-level-up primary-color mr-2"></i>
Convert to Parameter
</button>
}
@if (item.type == 'userDefined') {
<button mat-menu-item (click)="deleteProperty(item)">
<i class="fa fa-trash primary-color mr-2"></i>
Delete
</button>
}
}
}
</mat-menu>
</div>
</td>
</ng-container>

View File

@ -14,13 +14,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.property-table {
.listing-table {
table {
.mat-column-actions {
width: 74px;
}
}
}
}

View File

@ -60,6 +60,7 @@ import { Observable, take } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { RouterLink } from '@angular/router';
import { ConvertToParameterResponse } from '../../../pages/flow-designer/service/parameter-helper.service';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
export interface PropertyItem extends Property {
id: number;
@ -86,7 +87,10 @@ export interface PropertyItem extends Property {
CdkConnectedOverlay,
ComboEditor,
RouterLink,
AsyncPipe
AsyncPipe,
MatMenu,
MatMenuItem,
MatMenuTrigger
],
styleUrls: ['./property-table.component.scss'],
providers: [

View File

@ -292,6 +292,22 @@
margin: unset;
}
.mat-mdc-menu-panel {
max-width: 420px;
.fa {
width: 14px;
height: 14px;
text-align: center;
}
.icon {
display: inline-block;
width: 14px;
text-align: center;
}
}
.cdk-drop-list {
color: $material-theme-primary-palette-default;
}

View File

@ -36,15 +36,8 @@
cursor: default;
}
.fa {
width: 14px;
height: 14px;
text-align: center;
}
.icon {
width: 14px;
text-align: center;
.mat-column-actions {
width: 52px;
}
}
}