File

src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts

Implements

OnChanges

Metadata

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(entityActionsMenuService: EntityActionsMenuService, viewContext: ViewComponentContext)
Parameters :
Name Type Optional
entityActionsMenuService EntityActionsMenuService No
viewContext ViewComponentContext No

Inputs

entity
Type : Entity
navigateOnDelete
Type : boolean
Default value : false

whether the "delete" action will trigger a navigation back to the parent list. This is useful when the entity is deleted from a fullscreen detail view but not for an overlay.

showExpanded
Type : boolean

Whether some buttons should be displayed directly, outside the three-dot menu in dialog views.

Outputs

actionTriggered
Type : EventEmitter

Methods

Async executeAction
executeAction(action: EntityAction)
Parameters :
Name Type Optional
action EntityAction No
Returns : any

Properties

actions
Type : EntityAction[]

The actions being displayed as menu items.

import {
  Component,
  EventEmitter,
  Input,
  OnChanges,
  Optional,
  Output,
  SimpleChanges,
} from "@angular/core";
import { Entity } from "../../entity/model/entity";
import { MatButtonModule } from "@angular/material/button";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { MatMenuModule } from "@angular/material/menu";
import { Angulartics2Module } from "angulartics2";
import { DisableEntityOperationDirective } from "../../permissions/permission-directive/disable-entity-operation.directive";
import { MatTooltipModule } from "@angular/material/tooltip";
import { ViewComponentContext } from "../../ui/abstract-view/view-component-context";
import { EntityActionsMenuService } from "./entity-actions-menu.service";
import { EntityAction } from "./entity-action.interface";

@Component({
  selector: "app-entity-actions-menu",
  templateUrl: "./entity-actions-menu.component.html",
  styleUrls: ["./entity-actions-menu.component.scss"],
  imports: [
    MatButtonModule,
    FontAwesomeModule,
    MatMenuModule,
    Angulartics2Module,
    DisableEntityOperationDirective,
    MatTooltipModule,
  ],
})
export class EntityActionsMenuComponent implements OnChanges {
  @Input() entity: Entity;

  /**
   * whether the "delete" action will trigger a navigation back to the parent list.
   * This is useful when the entity is deleted from a fullscreen detail view but not for an overlay.
   */
  @Input() navigateOnDelete: boolean = false;

  @Output() actionTriggered = new EventEmitter<string>();

  /**
   * The actions being displayed as menu items.
   */
  actions: EntityAction[];

  /**
   * Whether some buttons should be displayed directly, outside the three-dot menu in dialog views.
   */
  @Input() showExpanded?: boolean;

  constructor(
    private entityActionsMenuService: EntityActionsMenuService,
    @Optional() protected viewContext: ViewComponentContext,
  ) {}

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.entity) {
      this.filterAvailableActions();
    }
  }

  private async filterAvailableActions() {
    if (!this.entity) {
      this.actions = [];
      return;
    }
    const allActions: EntityAction[] = this.entityActionsMenuService.getActions(
      this.entity,
    );

    // check each action’s `visible` property to hide actions not applicable to the current entity
    const visibleActions = (
      await Promise.all(
        allActions.map(async (action) => {
          const isVisible = action.visible
            ? await action.visible(this.entity)
            : true;
          return isVisible ? action : null;
        }),
      )
    ).filter(Boolean) as EntityAction[];

    this.actions = visibleActions;
  }

  async executeAction(action: EntityAction) {
    const result = await action.execute(
      this.entity,
      this.navigateOnDelete && !this.viewContext?.isDialog,
    );
    if (result) {
      this.actionTriggered.emit(action.action);
    }
    setTimeout(() => this.filterAvailableActions());
  }
}
@if (!entity?.isNew) {
  <!-- inline display of primary actions -->
  @for (a of actions; track a.action) {
    @if (showExpanded && viewContext?.isDialog && a.primaryAction) {
      <button
        mat-stroked-button
        (click)="executeAction(a)"
        *appDisabledEntityOperation="{
          operation: a.permission,
          entity: entity,
        }"
        angulartics2On="click"
        [angularticsCategory]="entity?.getType()"
        [angularticsAction]="'entity_' + a.action"
        [matTooltip]="a.tooltip"
      >
        <fa-icon
          class="standard-icon-with-text color-accent"
          [icon]="a.icon"
        ></fa-icon>
        <span>{{ a.label }}</span>
      </button>
    }
  }

  <!-- context menu -->
  <button
    mat-icon-button
    color="primary"
    style="margin-top: -8px; margin-bottom: -8px"
    [matMenuTriggerFor]="additional"
  >
    <fa-icon icon="ellipsis-v" class="standard-icon"></fa-icon>
  </button>

  <!-- context menu -->
  <mat-menu #additional>
    <!-- standard actions -->
    @for (a of actions; track a.action) {
      @if (!a.primaryAction || !showExpanded || !viewContext?.isDialog) {
        <button
          mat-menu-item
          (click)="executeAction(a)"
          *appDisabledEntityOperation="{
            operation: a.permission,
            entity: entity,
          }"
          angulartics2On="click"
          [angularticsCategory]="entity?.getType()"
          [angularticsAction]="'entity_' + a.action"
          [matTooltip]="a.tooltip"
          matTooltipPosition="before"
        >
          <fa-icon
            class="standard-icon-with-text color-accent"
            [icon]="a.icon"
          ></fa-icon>
          <span>{{ a.label }}</span>
        </button>
      }
    }

    <!-- additional actions -->
    <ng-content></ng-content>
  </mat-menu>
}

./entity-actions-menu.component.scss

:host {
  display: flex;
  align-items: center;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""