|
persistPolicyUrl
|
Type : string
|
Default value : ''
|
|
|
Methods
|
copyToClipboard
|
copyToClipboard()
|
|
|
|
|
|
persistPolicy
|
persistPolicy()
|
|
|
|
|
|
removeRule
|
removeRule(index: number)
|
|
|
Parameters :
| Name |
Type |
Optional |
| index |
number
|
No
|
|
|
requestUpdate
|
requestUpdate()
|
|
|
|
|
|
aclIconName
|
Type : unknown
|
Default value : AclIconName
|
|
|
|
mutablePolicy
|
Type : unknown
|
Default value : linkedSignal(() => this.policy())
|
|
|
|
toggleAllState
|
Type : unknown
|
Default value : computed(() => this.hasActiveNonDefaultRules())
|
|
|
import {
ChangeDetectionStrategy,
Component,
computed,
input,
linkedSignal,
output
} from '@angular/core';
import { AclRule, convertRulesToPolicyTxt } from '@allianz/taly-acl';
import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { AclIconName, copyToClipboard } from '@allianz/taly-acl/angular';
@Component({
selector: 'acl-policy-editor',
templateUrl: './policy-editor.component.html',
styleUrls: ['./policy-editor.component.scss'],
standalone: false,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PolicyEditorComponent {
policy = input<AclRule[]>([]);
persistPolicyUrl = input<string>('');
changed = output<AclRule[]>();
mutablePolicy = linkedSignal(() => this.policy());
toggleAllState = computed(() => this.hasActiveNonDefaultRules());
aclIconName = AclIconName;
dropRule(event: CdkDragDrop<AclRule>) {
const policy = [...this.mutablePolicy()];
const draggedRule = policy[event.previousIndex];
if (!draggedRule) {
throw new Error(`Could not move rule with index ${event.previousIndex}`);
}
policy.splice(event.previousIndex, 1);
const indexForFirstDefaultRule = policy.findIndex((rule) => rule.defaultRule);
if (indexForFirstDefaultRule === -1) {
policy.splice(event.currentIndex, 0, draggedRule);
} else {
const currentIndex = Math.min(indexForFirstDefaultRule, event.currentIndex);
policy.splice(currentIndex, 0, draggedRule);
}
this.mutablePolicy.set(policy);
this.requestUpdate();
}
private hasActiveNonDefaultRules() {
const mutablePolicy = this.mutablePolicy();
if (mutablePolicy.length === 0) {
return true;
}
return mutablePolicy.filter((rule) => !rule.defaultRule).some((rule) => rule.active);
}
requestUpdate() {
this.changed.emit(this.mutablePolicy());
}
toggleAll() {
const policy = this.mutablePolicy();
if (policy.length === 0) {
return;
}
const newState = !this.hasActiveNonDefaultRules();
this.mutablePolicy.set(
policy.map((rule) => (rule.defaultRule ? rule : { ...rule, active: newState }))
);
this.requestUpdate();
}
copyToClipboard() {
const policyString = convertRulesToPolicyTxt(this.mutablePolicy());
copyToClipboard(policyString);
}
persistPolicy() {
const policyString = convertRulesToPolicyTxt(this.mutablePolicy());
fetch(this.persistPolicyUrl(), { method: 'POST', body: policyString, credentials: 'include' });
}
createRule() {
this.mutablePolicy.set([
{ active: true, condition: '', path: '*', state: 'visible', defaultRule: false },
...this.mutablePolicy()
]);
this.requestUpdate();
}
duplicateRule(rule: AclRule, index: number) {
const policy = [...this.mutablePolicy()];
const indexForFirstDefaultRule = policy.findIndex((r) => r.defaultRule);
const insertIndex =
indexForFirstDefaultRule === -1 ? index : Math.min(indexForFirstDefaultRule, index);
policy.splice(insertIndex, 0, { ...rule, defaultRule: false });
this.mutablePolicy.set(policy);
this.requestUpdate();
}
removeRule(index: number) {
const newRules = [...this.mutablePolicy()];
newRules.splice(index, 1);
this.mutablePolicy.set(newRules);
this.requestUpdate();
}
}
<div class="inspector-actions">
<button class="btn-icon" (click)="toggleAll()">
@if (toggleAllState()) {
<acl-icon [name]="aclIconName.EyeBig" title="toggle all rules" size="24"></acl-icon>
} @if (!toggleAllState()) {
<acl-icon [name]="aclIconName.EyeBigClosed" title="toggle all rules" size="24"></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>
@if (persistPolicyUrl()) {
<button 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)">
@for (rule of mutablePolicy(); track $index; let index = $index) {
<acl-rule
[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>
@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 with directive