Browse Source

Refactor components to use Angular signal inputs/outputs

Migrates Tree, FeatureManagement, and PermissionManagement components to use Angular's new signal-based input and output APIs. Updates templates and internal logic to access input values as functions, replaces EventEmitter with output signals, and synchronizes internal state using signals and effects. Also updates related model interfaces to use InputSignal and OutputEmitterRef types.
pull/24777/head
Fahri Gedik 8 months ago
parent
commit
0c09657851
  1. 8
      npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html
  2. 121
      npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts
  3. 6
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html
  4. 62
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts
  5. 9
      npm/ng-packs/packages/feature-management/src/lib/models/feature-management.ts
  6. 6
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html
  7. 130
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts
  8. 11
      npm/ng-packs/packages/permission-management/src/lib/models/permission-management.ts

8
npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html

@ -1,8 +1,8 @@
<nz-tree <nz-tree
[nzBeforeDrop]="beforeDrop" [nzBeforeDrop]="beforeDrop"
[nzDraggable]="draggable" [nzDraggable]="draggable()"
[nzCheckStrictly]="checkStrictly" [nzCheckStrictly]="checkStrictly()"
[nzCheckable]="checkable" [nzCheckable]="checkable()"
[nzCheckedKeys]="checkedKeys" [nzCheckedKeys]="checkedKeys"
[nzData]="nodes" [nzData]="nodes"
[nzTreeTemplate]="treeTemplate" [nzTreeTemplate]="treeTemplate"
@ -11,7 +11,7 @@
(nzExpandChange)="onExpandedKeysChange($event)" (nzExpandChange)="onExpandedKeysChange($event)"
(nzCheckboxChange)="onCheckboxChange($event)" (nzCheckboxChange)="onCheckboxChange($event)"
(nzOnDrop)="onDrop($event)" (nzOnDrop)="onDrop($event)"
[nzNoAnimation]="noAnimation" [nzNoAnimation]="noAnimation()"
(nzContextMenu)="onContextMenuChange($event)" (nzContextMenu)="onContextMenuChange($event)"
/> />
<ng-template #treeTemplate let-node> <ng-template #treeTemplate let-node>

121
npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts

@ -3,13 +3,14 @@ import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ContentChild, ContentChild,
EventEmitter,
inject, inject,
Input,
OnInit, OnInit,
Output,
TemplateRef, TemplateRef,
ViewEncapsulation, ViewEncapsulation,
input,
output,
signal,
effect
} from '@angular/core'; } from '@angular/core';
import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'; import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap';
import { import {
@ -56,32 +57,66 @@ export class TreeComponent implements OnInit {
private cdr = inject(ChangeDetectorRef); private cdr = inject(ChangeDetectorRef);
private disableTreeStyleLoading = inject(DISABLE_TREE_STYLE_LOADING_TOKEN, { optional: true }); private disableTreeStyleLoading = inject(DISABLE_TREE_STYLE_LOADING_TOKEN, { optional: true });
dropPosition: number; dropPosition!: number;
dropdowns = {} as { [key: string]: NgbDropdown }; dropdowns = {} as { [key: string]: NgbDropdown };
@ContentChild('menu') menu: TemplateRef<any>; @ContentChild('menu') menu!: TemplateRef<any>;
@ContentChild(TreeNodeTemplateDirective) customNodeTemplate: TreeNodeTemplateDirective; @ContentChild(TreeNodeTemplateDirective) customNodeTemplate!: TreeNodeTemplateDirective;
@ContentChild(ExpandedIconTemplateDirective) expandedIconTemplate: ExpandedIconTemplateDirective; @ContentChild(ExpandedIconTemplateDirective) expandedIconTemplate!: ExpandedIconTemplateDirective;
@Output() readonly checkedKeysChange = new EventEmitter();
@Output() readonly expandedKeysChange = new EventEmitter<string[]>(); // Output signals
@Output() readonly selectedNodeChange = new EventEmitter(); readonly checkedKeysChange = output<any>();
@Output() readonly dropOver = new EventEmitter<DropEvent>(); readonly expandedKeysChange = output<string[]>();
@Output() readonly nzExpandChange = new EventEmitter<NzFormatEmitEvent>(); readonly selectedNodeChange = output<any>();
@Input() noAnimation = true; readonly dropOver = output<DropEvent>();
@Input() draggable: boolean; readonly nzExpandChange = output<NzFormatEmitEvent>();
@Input() checkable: boolean;
@Input() checkStrictly: boolean; // Input signals
@Input() checkedKeys = []; readonly noAnimation = input(true);
@Input() nodes = []; readonly draggable = input<boolean | undefined>(undefined);
@Input() expandedKeys: string[] = []; readonly checkable = input<boolean | undefined>(undefined);
@Input() selectedNode: any; readonly checkStrictly = input<boolean | undefined>(undefined);
@Input() changeCheckboxWithNode: boolean; readonly checkedKeysInput = input<any[]>([], { alias: 'checkedKeys' });
@Input() isNodeSelected = node => this.selectedNode?.id === node.key; readonly nodesInput = input<any[]>([], { alias: 'nodes' });
@Input() beforeDrop = (event: NzFormatBeforeDropEvent) => { readonly expandedKeysInput = input<string[]>([], { alias: 'expandedKeys' });
this.dropPosition = event.pos; readonly selectedNodeInput = input<any>(undefined, { alias: 'selectedNode' });
return of(false); readonly changeCheckboxWithNode = input<boolean | undefined>(undefined);
}; readonly isNodeSelectedFn = input<(node: any) => boolean>(
(node) => this._selectedNode() === node.key,
{ alias: 'isNodeSelected' }
);
readonly beforeDropFn = input<(event: NzFormatBeforeDropEvent) => any>(
(event: NzFormatBeforeDropEvent) => {
this.dropPosition = event.pos;
return of(false);
},
{ alias: 'beforeDrop' }
);
// Internal signals for two-way binding
protected readonly _checkedKeys = signal<any[]>([]);
protected readonly _expandedKeys = signal<string[]>([]);
protected readonly _selectedNode = signal<any>(undefined);
protected readonly _nodes = signal<any[]>([]);
// Getters for template access
get checkedKeys() { return this._checkedKeys(); }
get expandedKeys() { return this._expandedKeys(); }
get selectedNode() { return this._selectedNode(); }
get nodes() { return this._nodes(); }
get isNodeSelected() { return this.isNodeSelectedFn(); }
get beforeDrop() { return this.beforeDropFn(); }
constructor() {
// Sync input signals to internal signals
effect(() => {
this._checkedKeys.set(this.checkedKeysInput());
this._expandedKeys.set(this.expandedKeysInput());
this._selectedNode.set(this.selectedNodeInput());
this._nodes.set(this.nodesInput());
});
}
ngOnInit() { ngOnInit() {
this.loadStyle(); this.loadStyle();
@ -97,13 +132,13 @@ export class TreeComponent implements OnInit {
this.subscriptionService.addOne(loaded$); this.subscriptionService.addOne(loaded$);
} }
private findNode(target: any, nodes: any[]) { private findNode(target: any, nodes: any[]): any {
for (const node of nodes) { for (const node of nodes) {
if (node.key === target.id) { if (node.key === target.id) {
return node; return node;
} }
if (node.children) { if (node.children) {
const res = this.findNode(target, node.children); const res: any = this.findNode(target, node.children);
if (res) { if (res) {
return res; return res;
} }
@ -113,36 +148,36 @@ export class TreeComponent implements OnInit {
} }
onSelectedNodeChange(node: NzTreeNode) { onSelectedNodeChange(node: NzTreeNode) {
this.selectedNode = node.origin.entity; this._selectedNode.set(node.origin.entity);
if (this.changeCheckboxWithNode) { if (this.changeCheckboxWithNode()) {
let newVal; let newVal;
if (node.isChecked) { if (node.isChecked) {
newVal = this.checkedKeys.filter(x => x !== node.key); newVal = this._checkedKeys().filter(x => x !== node.key);
} else { } else {
newVal = [...this.checkedKeys, node.key]; newVal = [...this._checkedKeys(), node.key];
} }
this.selectedNodeChange.emit(node); this.selectedNodeChange.emit(node);
this.checkedKeys = newVal; this._checkedKeys.set(newVal);
this.checkedKeysChange.emit(newVal); this.checkedKeysChange.emit(newVal);
} else { } else {
this.selectedNodeChange.emit(node.origin.entity); this.selectedNodeChange.emit(node.origin.entity);
} }
} }
onCheckboxChange(event) { onCheckboxChange(event: { keys: any[] }) {
this.checkedKeys = [...event.keys]; this._checkedKeys.set([...event.keys]);
this.checkedKeysChange.emit(event.keys); this.checkedKeysChange.emit(event.keys);
} }
onExpandedKeysChange(event) { onExpandedKeysChange(event: { keys: string[] } & NzFormatEmitEvent) {
this.expandedKeys = [...event.keys]; this._expandedKeys.set([...event.keys]);
this.expandedKeysChange.emit(event.keys); this.expandedKeysChange.emit(event.keys);
this.nzExpandChange.emit(event); this.nzExpandChange.emit(event);
} }
onDrop(event: DropEvent) { onDrop(event: DropEvent) {
event.event.stopPropagation(); event.event?.stopPropagation();
event.event.preventDefault(); event.event?.preventDefault();
event.pos = this.dropPosition; event.pos = this.dropPosition;
this.dropOver.emit(event); this.dropOver.emit(event);
@ -160,12 +195,14 @@ export class TreeComponent implements OnInit {
dropdown.close(); dropdown.close();
} }
}); });
this.dropdowns[dropdownKey]?.toggle(); if (dropdownKey) {
this.dropdowns[dropdownKey]?.toggle();
}
} }
setSelectedNode(node: any) { setSelectedNode(node: any) {
const newSelectedNode = this.findNode(node, this.nodes); const newSelectedNode = this.findNode(node, this._nodes());
this.selectedNode = { ...newSelectedNode }; this._selectedNode.set({ ...newSelectedNode });
this.cdr.markForCheck(); this.cdr.markForCheck();
} }
} }

6
npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html

@ -3,8 +3,8 @@
<ng-template #abpHeader> <ng-template #abpHeader>
<h3> <h3>
{{ 'AbpFeatureManagement::Features' | abpLocalization }} {{ 'AbpFeatureManagement::Features' | abpLocalization }}
@if (providerTitle) { @if (providerTitle()) {
- {{ providerTitle }} - {{ providerTitle() }}
} }
</h3> </h3>
</ng-template> </ng-template>
@ -38,7 +38,7 @@
@for (feature of features[group.name]; track feature.id || i; let i = $index) { @for (feature of features[group.name]; track feature.id || i; let i = $index) {
@let provider = feature.provider.name; @let provider = feature.provider.name;
@let isFeatureDisabled = !feature.parentName ? isParentDisabled(feature.name, group.name, provider) : @let isFeatureDisabled = !feature.parentName ? isParentDisabled(feature.name, group.name, provider) :
(provider !== providerName && provider !== defaultProviderName); (provider !== providerName() && provider !== defaultProviderName);
<div class="mt-2" [style]="feature.style" (keyup.enter)="save()"> <div class="mt-2" [style]="feature.style" (keyup.enter)="save()">
@switch (feature.valueType?.name) { @switch (feature.valueType?.name) {

62
npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts

@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, Output, inject, DOCUMENT } from '@angular/core'; import { Component, inject, DOCUMENT, input, output, signal, effect } from '@angular/core';
import { NgTemplateOutlet } from '@angular/common'; import { NgTemplateOutlet } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { ConfigStateService, LocalizationPipe, TrackByService } from '@abp/ng.core'; import { ConfigStateService, LocalizationPipe, TrackByService } from '@abp/ng.core';
@ -61,14 +61,17 @@ export class FeatureManagementComponent
protected readonly confirmationService = inject(ConfirmationService); protected readonly confirmationService = inject(ConfirmationService);
private document = inject(DOCUMENT); private document = inject(DOCUMENT);
@Input() // Signal inputs
providerKey: string; readonly providerKey = input<string | undefined>(undefined);
readonly providerName = input<string | undefined>(undefined);
readonly providerTitle = input<string | undefined>(undefined);
readonly visibleInput = input(false, { alias: 'visible' });
@Input() // Output signals
providerName: string; readonly visibleChange = output<boolean>();
@Input({ required: false }) // Internal state
providerTitle: string; protected readonly _visible = signal(false);
selectedGroupDisplayName: string; selectedGroupDisplayName: string;
@ -82,33 +85,41 @@ export class FeatureManagementComponent
defaultProviderName = DEFAULT_PROVIDER_NAME; defaultProviderName = DEFAULT_PROVIDER_NAME;
protected _visible; modalBusy = false;
@Input() // Getter/setter for backward compatibility
get visible(): boolean { get visible(): boolean {
return this._visible; return this._visible();
} }
set visible(value: boolean) { set visible(value: boolean) {
if (this._visible === value) { if (this._visible() === value) {
return; return;
} }
this._visible = value; this._visible.set(value);
this.visibleChange.emit(value); this.visibleChange.emit(value);
if (value) { if (value) {
this.openModal(); this.openModal();
return;
} }
} }
@Output() readonly visibleChange = new EventEmitter<boolean>(); constructor() {
// Sync visible input to internal signal
modalBusy = false; effect(() => {
const inputValue = this.visibleInput();
if (this._visible() !== inputValue) {
this._visible.set(inputValue);
if (inputValue) {
this.openModal();
}
}
});
}
openModal() { openModal() {
if (!this.providerName) { if (!this.providerName()) {
throw new Error('providerName is required.'); throw new Error('providerName is required.');
} }
@ -116,7 +127,7 @@ export class FeatureManagementComponent
} }
getFeatures() { getFeatures() {
this.service.get(this.providerName, this.providerKey).subscribe(res => { this.service.get(this.providerName()!, this.providerKey()).subscribe(res => {
if (!res.groups?.length) return; if (!res.groups?.length) return;
this.groups = res.groups.map(({ name, displayName }) => ({ name, displayName })); this.groups = res.groups.map(({ name, displayName }) => ({ name, displayName }));
this.selectedGroupDisplayName = this.groups[0].displayName; this.selectedGroupDisplayName = this.groups[0].displayName;
@ -149,13 +160,13 @@ export class FeatureManagementComponent
this.modalBusy = true; this.modalBusy = true;
this.service this.service
.update(this.providerName, this.providerKey, { features: changedFeatures }) .update(this.providerName()!, this.providerKey(), { features: changedFeatures })
.pipe(finalize(() => (this.modalBusy = false))) .pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => { .subscribe(() => {
this.visible = false; this.visible = false;
this.toasterService.success('AbpUi::SavedSuccessfully'); this.toasterService.success('AbpUi::SavedSuccessfully');
if (!this.providerKey) { if (!this.providerKey()) {
// to refresh host's features // to refresh host's features
this.configState.refreshAppState().subscribe(); this.configState.refreshAppState().subscribe();
} }
@ -167,11 +178,11 @@ export class FeatureManagementComponent
.warn('AbpFeatureManagement::AreYouSureToResetToDefault', 'AbpFeatureManagement::AreYouSure') .warn('AbpFeatureManagement::AreYouSureToResetToDefault', 'AbpFeatureManagement::AreYouSure')
.subscribe((status: Confirmation.Status) => { .subscribe((status: Confirmation.Status) => {
if (status === Confirmation.Status.confirm) { if (status === Confirmation.Status.confirm) {
this.service.delete(this.providerName, this.providerKey).subscribe(() => { this.service.delete(this.providerName()!, this.providerKey()).subscribe(() => {
this.toasterService.success('AbpFeatureManagement::ResetedToDefault'); this.toasterService.success('AbpFeatureManagement::ResetedToDefault');
this.visible = false; this.visible = false;
if (!this.providerKey) { if (!this.providerKey()) {
// to refresh host's features // to refresh host's features
this.configState.refreshAppState().subscribe(); this.configState.refreshAppState().subscribe();
} }
@ -190,17 +201,18 @@ export class FeatureManagementComponent
isParentDisabled(parentName: string, groupName: string, provider: string): boolean { isParentDisabled(parentName: string, groupName: string, provider: string): boolean {
const children = this.features[groupName]?.filter(f => f.parentName === parentName); const children = this.features[groupName]?.filter(f => f.parentName === parentName);
const providerNameValue = this.providerName();
if (children?.length) { if (children?.length) {
return children.some(child => { return children.some(child => {
const childProvider = child.provider?.name; const childProvider = child.provider?.name;
return ( return (
(childProvider !== this.providerName && childProvider !== this.defaultProviderName) || (childProvider !== providerNameValue && childProvider !== this.defaultProviderName) ||
(provider !== this.providerName && provider !== this.defaultProviderName) (provider !== providerNameValue && provider !== this.defaultProviderName)
); );
}); });
} else { } else {
return provider !== this.providerName && provider !== this.defaultProviderName; return provider !== providerNameValue && provider !== this.defaultProviderName;
} }
} }

9
npm/ng-packs/packages/feature-management/src/lib/models/feature-management.ts

@ -1,13 +1,14 @@
import { EventEmitter } from '@angular/core'; import { InputSignal, OutputEmitterRef } from '@angular/core';
export namespace FeatureManagement { export namespace FeatureManagement {
export interface FeatureManagementComponentInputs { export interface FeatureManagementComponentInputs {
visible: boolean; visible: boolean;
readonly providerName: string; readonly providerName: InputSignal<string | undefined>;
readonly providerKey: string; readonly providerKey: InputSignal<string | undefined>;
} }
export interface FeatureManagementComponentOutputs { export interface FeatureManagementComponentOutputs {
readonly visibleChange: EventEmitter<boolean>; readonly visibleChange: OutputEmitterRef<boolean>;
} }
} }

6
npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html

@ -1,9 +1,9 @@
<abp-modal [(visible)]="visible" [busy]="modalBusy" [options]="{ size: 'lg', scrollable: false }"> <abp-modal [(visible)]="visible" [busy]="modalBusy" [options]="{ size: 'lg', scrollable: false }">
@if (data.entityDisplayName || entityDisplayName) { @if (data.entityDisplayName || entityDisplayName()) {
<ng-template #abpHeader> <ng-template #abpHeader>
<h4> <h4>
{{ 'AbpPermissionManagement::Permissions' | abpLocalization }} - {{ 'AbpPermissionManagement::Permissions' | abpLocalization }} -
{{ entityDisplayName || data.entityDisplayName }} {{ entityDisplayName() || data.entityDisplayName }}
</h4> </h4>
</ng-template> </ng-template>
<ng-template #abpBody> <ng-template #abpBody>
@ -115,7 +115,7 @@
/> />
<label class="form-check-label" [attr.for]="permission.name" <label class="form-check-label" [attr.for]="permission.name"
>{{ permission.displayName }} >{{ permission.displayName }}
@if (!hideBadges) { @if (!hideBadges()) {
@for (provider of permission.grantedProviders; track $index) { @for (provider of permission.grantedProviders; track $index) {
<span class="badge bg-primary text-dark" <span class="badge bg-primary text-dark"
>{{ provider.providerName }}: {{ provider.providerKey }}</span >{{ provider.providerName }}: {{ provider.providerKey }}</span

130
npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts

@ -19,14 +19,14 @@ import {
computed, computed,
DOCUMENT, DOCUMENT,
ElementRef, ElementRef,
EventEmitter,
inject, inject,
Input, input,
Output, output,
QueryList, QueryList,
signal, signal,
TrackByFunction, TrackByFunction,
ViewChildren, ViewChildren,
effect,
} from '@angular/core'; } from '@angular/core';
import { concat, of } from 'rxjs'; import { concat, of } from 'rxjs';
import { finalize, switchMap, take, tap } from 'rxjs/operators'; import { finalize, switchMap, take, tap } from 'rxjs/operators';
@ -118,49 +118,18 @@ export class PermissionManagementComponent
protected readonly toasterService = inject(ToasterService); protected readonly toasterService = inject(ToasterService);
private document = inject(DOCUMENT); private document = inject(DOCUMENT);
@Input() // Signal inputs
readonly providerName!: string; readonly providerName = input.required<string>();
readonly providerKey = input.required<string>();
readonly hideBadges = input(false);
readonly entityDisplayName = input<string | undefined>(undefined);
readonly visibleInput = input(false, { alias: 'visible' });
@Input() // Output signals
readonly providerKey!: string; readonly visibleChange = output<boolean>();
@Input() // Internal state
readonly hideBadges = false; protected readonly _visible = signal(false);
protected _visible = false;
@Input()
entityDisplayName: string | undefined;
@Input()
get visible(): boolean {
return this._visible;
}
set visible(value: boolean) {
if (value === this._visible) {
return;
}
if (value) {
this.openModal().subscribe(() => {
this._visible = true;
this.visibleChange.emit(true);
concat(this.selectAllInAllTabsRef.changes, this.selectAllInThisTabsRef.changes)
.pipe(take(1))
.subscribe(() => {
this.initModal();
});
});
} else {
this.setSelectedGroup(null);
this._visible = false;
this.visibleChange.emit(false);
this.filter.set('');
}
}
@Output() readonly visibleChange = new EventEmitter<boolean>();
@ViewChildren('selectAllInThisTabsRef') @ViewChildren('selectAllInThisTabsRef')
selectAllInThisTabsRef!: QueryList<ElementRef<HTMLInputElement>>; selectAllInThisTabsRef!: QueryList<ElementRef<HTMLInputElement>>;
@ -216,6 +185,59 @@ export class PermissionManagementComponent
trackByFn: TrackByFunction<PermissionGroupDto> = (_, item) => item.name; trackByFn: TrackByFunction<PermissionGroupDto> = (_, item) => item.name;
// Getter/setter for backward compatibility
get visible(): boolean {
return this._visible();
}
set visible(value: boolean) {
if (value === this._visible()) {
return;
}
if (value) {
this.openModal().subscribe(() => {
this._visible.set(true);
this.visibleChange.emit(true);
concat(this.selectAllInAllTabsRef.changes, this.selectAllInThisTabsRef.changes)
.pipe(take(1))
.subscribe(() => {
this.initModal();
});
});
} else {
this.setSelectedGroup(null);
this._visible.set(false);
this.visibleChange.emit(false);
this.filter.set('');
}
}
constructor() {
// Sync visible input to internal signal
effect(() => {
const inputValue = this.visibleInput();
if (this._visible() !== inputValue) {
if (inputValue) {
this.openModal().subscribe(() => {
this._visible.set(true);
this.visibleChange.emit(true);
concat(this.selectAllInAllTabsRef.changes, this.selectAllInThisTabsRef.changes)
.pipe(take(1))
.subscribe(() => {
this.initModal();
});
});
} else {
this.setSelectedGroup(null);
this._visible.set(false);
this.visibleChange.emit(false);
this.filter.set('');
}
}
});
}
getChecked(name: string) { getChecked(name: string) {
return (this.permissions.find(per => per.name === name) || { isGranted: false }).isGranted; return (this.permissions.find(per => per.name === name) || { isGranted: false }).isGranted;
} }
@ -249,7 +271,7 @@ export class PermissionManagementComponent
this.disableSelectAllTab = permissions.every( this.disableSelectAllTab = permissions.every(
permission => permission =>
permission.isGranted && permission.isGranted &&
permission.grantedProviders?.every(p => p.providerName !== this.providerName), permission.grantedProviders?.every(p => p.providerName !== this.providerName()),
); );
} else { } else {
this.disableSelectAllTab = false; this.disableSelectAllTab = false;
@ -258,7 +280,7 @@ export class PermissionManagementComponent
isGrantedByOtherProviderName(grantedProviders: ProviderInfoDto[]): boolean { isGrantedByOtherProviderName(grantedProviders: ProviderInfoDto[]): boolean {
if (grantedProviders.length) { if (grantedProviders.length) {
return grantedProviders.findIndex(p => p.providerName !== this.providerName) > -1; return grantedProviders.findIndex(p => p.providerName !== this.providerName()) > -1;
} }
return false; return false;
} }
@ -348,7 +370,7 @@ export class PermissionManagementComponent
setTabCheckboxState() { setTabCheckboxState() {
const selectablePermissions = this.selectedGroupPermissions.filter(per => const selectablePermissions = this.selectedGroupPermissions.filter(per =>
per.grantedProviders.every(p => p.providerName === this.providerName), per.grantedProviders.every(p => p.providerName === this.providerName()),
); );
const selectedPermissions = selectablePermissions.filter(per => per.isGranted); const selectedPermissions = selectablePermissions.filter(per => per.isGranted);
@ -370,7 +392,7 @@ export class PermissionManagementComponent
setGrantCheckboxState() { setGrantCheckboxState() {
const selectablePermissions = this.permissions.filter(per => const selectablePermissions = this.permissions.filter(per =>
per.grantedProviders.every(p => p.providerName === this.providerName), per.grantedProviders.every(p => p.providerName === this.providerName()),
); );
const selectedAllPermissions = selectablePermissions.filter(per => per.isGranted); const selectedAllPermissions = selectablePermissions.filter(per => per.isGranted);
const checkboxElement = this.document.querySelector('#select-all-in-all-tabs') as any; const checkboxElement = this.document.querySelector('#select-all-in-all-tabs') as any;
@ -456,7 +478,7 @@ export class PermissionManagementComponent
this.modalBusy = true; this.modalBusy = true;
this.service this.service
.update(this.providerName, this.providerKey, { permissions: changedPermissions }) .update(this.providerName(), this.providerKey(), { permissions: changedPermissions })
.pipe( .pipe(
switchMap(() => switchMap(() =>
this.shouldFetchAppConfig() ? this.configState.refreshAppState() : of(null), this.shouldFetchAppConfig() ? this.configState.refreshAppState() : of(null),
@ -470,11 +492,11 @@ export class PermissionManagementComponent
} }
openModal() { openModal() {
if (!this.providerKey || !this.providerName) { if (!this.providerKey() || !this.providerName()) {
throw new Error('Provider Key and Provider Name are required.'); throw new Error('Provider Key and Provider Name are required.');
} }
return this.service.get(this.providerName, this.providerKey).pipe( return this.service.get(this.providerName(), this.providerKey()).pipe(
tap((permissionRes: GetPermissionListResultDto) => { tap((permissionRes: GetPermissionListResultDto) => {
const { groups } = permissionRes || {}; const { groups } = permissionRes || {};
@ -486,7 +508,7 @@ export class PermissionManagementComponent
this.disabledSelectAllInAllTabs = this.permissions.every( this.disabledSelectAllInAllTabs = this.permissions.every(
per => per =>
per.isGranted && per.isGranted &&
per.grantedProviders.every(provider => provider.providerName !== this.providerName), per.grantedProviders.every(provider => provider.providerName !== this.providerName()),
); );
}), }),
); );
@ -511,9 +533,9 @@ export class PermissionManagementComponent
shouldFetchAppConfig() { shouldFetchAppConfig() {
const currentUser = this.configState.getOne('currentUser') as CurrentUserDto; const currentUser = this.configState.getOne('currentUser') as CurrentUserDto;
if (this.providerName === 'R') return currentUser.roles.some(role => role === this.providerKey); if (this.providerName() === 'R') return currentUser.roles.some(role => role === this.providerKey());
if (this.providerName === 'U') return currentUser.id === this.providerKey; if (this.providerName() === 'U') return currentUser.id === this.providerKey();
return false; return false;
} }

11
npm/ng-packs/packages/permission-management/src/lib/models/permission-management.ts

@ -1,5 +1,5 @@
import { GetPermissionListResultDto } from '@abp/ng.permission-management/proxy'; import { GetPermissionListResultDto } from '@abp/ng.permission-management/proxy';
import { EventEmitter } from '@angular/core'; import { InputSignal, OutputEmitterRef } from '@angular/core';
export namespace PermissionManagement { export namespace PermissionManagement {
export interface State { export interface State {
@ -8,12 +8,13 @@ export namespace PermissionManagement {
export interface PermissionManagementComponentInputs { export interface PermissionManagementComponentInputs {
visible: boolean; visible: boolean;
readonly providerName: string; readonly providerName: InputSignal<string>;
readonly providerKey: string; readonly providerKey: InputSignal<string>;
readonly hideBadges: boolean; readonly hideBadges: InputSignal<boolean>;
} }
export interface PermissionManagementComponentOutputs { export interface PermissionManagementComponentOutputs {
readonly visibleChange: EventEmitter<boolean>; readonly visibleChange: OutputEmitterRef<boolean>;
} }
} }

Loading…
Cancel
Save