File

libs/acl/angular/src/lib/policy-editor/policy-editor.component.ts

Implements

OnInit

Metadata

Index

Properties
Methods
Inputs
Outputs

Inputs

persistPolicyUrl
Type : string
policy
Type : AclRule[]
Default value : []

Outputs

changed
Type : EventEmitter

Methods

copyToClipboard
copyToClipboard()
Returns : void
createRule
createRule()
Returns : void
dropRule
dropRule(event: CdkDragDrop<AclRule>)
Parameters :
Name Type Optional
event CdkDragDrop<AclRule> No
Returns : void
duplicateRule
duplicateRule(rule: AclRule, index: number)
Parameters :
Name Type Optional
rule AclRule No
index number No
Returns : void
persistPolicy
persistPolicy()
Returns : void
removeRule
removeRule(index: number)
Parameters :
Name Type Optional
index number No
Returns : void
requestUpdate
requestUpdate()
Returns : void
toggleAll
toggleAll()
Returns : void

Properties

aclIconName
Default value : AclIconName
toggleAllState
Type : boolean
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { AclRule, convertRulesToPolicyTxt } from '@allianz/taly-acl';
import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { AclIconName } from '../acl-icon/acl-icon.interface';
import { copyToClipboard } from '../util/copy-clipboard';

@Component({
  selector: 'acl-policy-editor',
  templateUrl: './policy-editor.component.html',
  styleUrls: ['./policy-editor.component.scss'],
  standalone: false
})
export class PolicyEditorComponent implements OnInit {
  @Input() policy: AclRule[] = [];
  @Input() persistPolicyUrl!: string;
  @Output() changed = new EventEmitter<AclRule[]>();

  toggleAllState!: boolean;
  aclIconName = AclIconName;

  ngOnInit() {
    this.toggleAllState = this.hasActiveNonDefaultRules();
  }

  dropRule(event: CdkDragDrop<AclRule>) {
    const draggedRule = this.policy[event.previousIndex];
    if (!draggedRule) {
      throw new Error(`Could not move rule with index ${event.previousIndex}`);
    }

    this.policy.splice(event.previousIndex, 1);

    const indexForFirstDefaultRule = this.policy.findIndex((rule) => rule.defaultRule);

    if (indexForFirstDefaultRule === -1) {
      this.policy.splice(event.currentIndex, 0, draggedRule);
    } else {
      const currentIndex = Math.min(indexForFirstDefaultRule, event.currentIndex);
      this.policy.splice(currentIndex, 0, draggedRule);
    }

    this.requestUpdate();
  }

  private hasActiveNonDefaultRules() {
    if (this.policy.length === 0) {
      return true;
    }

    return this.policy.filter((rule) => !rule.defaultRule).some((rule) => rule.active);
  }

  requestUpdate() {
    this.toggleAllState = this.hasActiveNonDefaultRules();
    this.changed.emit(this.policy);
  }

  toggleAll() {
    if (this.policy.length === 0) {
      return;
    }

    this.toggleAllState = !this.hasActiveNonDefaultRules();
    this.policy
      .filter((rule) => !rule.defaultRule)
      .forEach((rule) => (rule.active = this.toggleAllState));

    this.requestUpdate();
  }

  copyToClipboard() {
    const policyString = convertRulesToPolicyTxt(this.policy);

    copyToClipboard(policyString);
  }

  persistPolicy() {
    const policyString = convertRulesToPolicyTxt(this.policy);

    fetch(this.persistPolicyUrl, { method: 'POST', body: policyString, credentials: 'include' });
  }

  createRule() {
    this.policy.unshift({
      active: true,
      condition: '',
      path: '*',
      state: 'visible',
      defaultRule: false
    });
    this.requestUpdate();
  }

  duplicateRule(rule: AclRule, index: number) {
    const indexForFirstDefaultRule = this.policy.findIndex((rule) => rule.defaultRule);

    if (indexForFirstDefaultRule === -1) {
      this.policy.splice(index, 0, { ...rule, defaultRule: false });
    } else {
      index = Math.min(indexForFirstDefaultRule, index);
      this.policy.splice(index, 0, { ...rule, defaultRule: false });
    }

    this.requestUpdate();
  }

  removeRule(index: number) {
    this.policy.splice(index, 1);
    this.requestUpdate();
  }
}
<div class="inspector-actions">
  <button class="btn-icon" (click)="toggleAll()">
    <acl-icon
      [name]="aclIconName.EyeBig"
      title="toggle all rules"
      size="24"
      *ngIf="toggleAllState"
    ></acl-icon>
    <acl-icon
      [name]="aclIconName.EyeBigClosed"
      title="toggle all rules"
      size="24"
      *ngIf="!toggleAllState"
    ></acl-icon>
  </button>
  <button class="btn-icon" (click)="createRule()">
    <acl-icon [name]="aclIconName.Plus" title="create rule" size="24"></acl-icon>
  </button>
  <button class="btn-icon" (click)="copyToClipboard()">
    <acl-icon [name]="aclIconName.Copy" title="copy to clipboard" size="24"></acl-icon>
  </button>
  <button
    *ngIf="persistPolicyUrl"
    class="btn-icon persist-policy"
    (click)="persistPolicy()"
    title="persist policy"
  >
    <acl-icon [name]="aclIconName.Save" title="persist policy" size="24"></acl-icon>
    <span>Persist Policy</span>
  </button>
  <button class="btn-icon" (click)="this.requestUpdate()">
    <acl-icon [name]="aclIconName.Reload" title="refresh component" size="24"></acl-icon>
  </button>
</div>

<div class="list" cdkDropList (cdkDropListDropped)="dropRule($event)">
  <acl-rule
    *ngFor="let rule of policy; let index = index"
    [rule]="rule"
    [index]="index + 1"
    (duplicated)="duplicateRule($event, index)"
    (removed)="removeRule(index)"
    (changed)="requestUpdate()"
    cdkDrag
    [cdkDragData]="rule"
    [attr.data-testid]="'rule-' + (index + 1)"
  >
    <acl-icon
      cdkDragHandle
      [name]="aclIconName.DragVertical"
      title="drag rule"
      size="28"
    ></acl-icon>
  </acl-rule>
</div>

./policy-editor.component.scss

@use '../inspector.shared' as *;

:host {
  display: grid;
  grid-template-rows: auto 1fr;
}

.persist-policy {
  width: auto !important;
  padding: 0 5px !important;

  span {
    vertical-align: middle;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""