Browse Source

update: some upgrade enhancements for the permission-management

pull/25690/head
sumeyye 4 months ago
parent
commit
7522836c0c
  1. 16
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html
  2. 434
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts
  3. 63
      npm/ng-packs/packages/permission-management/src/lib/components/resource-permission-management/resource-permission-management.component.ts

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

@ -2,7 +2,7 @@
[(visible)]="modalVisible" [(visible)]="modalVisible"
(visibleChange)="onModalVisibleChange($event)" (visibleChange)="onModalVisibleChange($event)"
(disappear)="onModalDisappear()" (disappear)="onModalDisappear()"
[busy]="modalBusy" [busy]="modalBusy()"
[suppressUnsavedChangesWarning]="true" [suppressUnsavedChangesWarning]="true"
[options]="{ size: 'lg', scrollable: false }" [options]="{ size: 'lg', scrollable: false }"
> >
@ -36,9 +36,10 @@
id="select-all-in-all-tabs" id="select-all-in-all-tabs"
name="select-all-in-all-tabs" name="select-all-in-all-tabs"
class="form-check-input" class="form-check-input"
[checked]="selectAllTab" [checked]="selectAllTabState().checked"
[indeterminate]="selectAllTabState().indeterminate"
(change)="onSelectAllChange($event)" (change)="onSelectAllChange($event)"
[disabled]="disabledSelectAllInAllTabs" [disabled]="disabledSelectAllInAllTabs()"
/> />
<label class="form-check-label" for="select-all-in-all-tabs">{{ <label class="form-check-label" for="select-all-in-all-tabs">{{
'AbpPermissionManagement::SelectAllInAllTabs' | abpLocalization 'AbpPermissionManagement::SelectAllInAllTabs' | abpLocalization
@ -91,7 +92,7 @@
<div ngTabPanel [value]="group.name"> <div ngTabPanel [value]="group.name">
<ng-template ngTabContent> <ng-template ngTabContent>
<div class="ps-1"> <div class="ps-1">
@if (selectedGroupPermissions.length) { @if (selectedGroup?.name === group.name && selectedGroupPermissions().length) {
<div class="form-check mb-2"> <div class="form-check mb-2">
<input <input
#selectAllInThisTabsRef #selectAllInThisTabsRef
@ -99,8 +100,9 @@
id="select-all-in-this-tabs" id="select-all-in-this-tabs"
name="select-all-in-this-tabs" name="select-all-in-this-tabs"
class="form-check-input" class="form-check-input"
[checked]="selectThisTab" [checked]="selectThisTabState().checked"
[disabled]="disableSelectAllTab" [indeterminate]="selectThisTabState().indeterminate"
[disabled]="disableSelectAllTab()"
(change)="onSelectThisTabChange($event)" (change)="onSelectThisTabChange($event)"
/> />
<label class="form-check-label" for="select-all-in-this-tabs">{{ <label class="form-check-label" for="select-all-in-this-tabs">{{
@ -108,7 +110,7 @@
}}</label> }}</label>
</div> </div>
<hr class="my-2" /> <hr class="my-2" />
@for (permission of selectedGroupPermissions; track $index; let i = $index) { @for (permission of selectedGroupPermissions(); track $index; let i = $index) {
<div [ngStyle]="permission.style" class="form-check mb-2"> <div [ngStyle]="permission.style" class="form-check mb-2">
<input <input
#permissionCheckbox #permissionCheckbox

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

@ -1,4 +1,20 @@
import {
ChangeDetectionStrategy,
Component,
computed,
DOCUMENT,
inject,
input,
output,
signal,
TrackByFunction,
} from '@angular/core';
import { NgStyle } from '@angular/common'; import { NgStyle } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Tabs, TabList, Tab, TabPanel, TabContent } from '@angular/aria/tabs';
import { of } from 'rxjs';
import { finalize, switchMap, tap } from 'rxjs/operators';
import { ConfigStateService, CurrentUserDto, LocalizationPipe } from '@abp/ng.core'; import { ConfigStateService, CurrentUserDto, LocalizationPipe } from '@abp/ng.core';
import { import {
ButtonComponent, ButtonComponent,
@ -15,27 +31,6 @@ import {
ProviderInfoDto, ProviderInfoDto,
UpdatePermissionDto, UpdatePermissionDto,
} from '@abp/ng.permission-management/proxy'; } from '@abp/ng.permission-management/proxy';
import {
afterNextRender,
Component,
computed,
DOCUMENT,
ElementRef,
inject,
Injector,
input,
output,
signal,
TrackByFunction,
viewChildren,
} from '@angular/core';
import { of } from 'rxjs';
import { finalize, switchMap, tap } from 'rxjs/operators';
import { PermissionManagement } from '../models';
import { FormsModule } from '@angular/forms';
import { Tabs, TabList, Tab, TabPanel, TabContent } from '@angular/aria/tabs';
type PermissionWithStyle = PermissionGrantInfoDto & { type PermissionWithStyle = PermissionGrantInfoDto & {
style: Record<string, number>; style: Record<string, number>;
@ -45,7 +40,13 @@ type PermissionWithGroupName = PermissionGrantInfoDto & {
groupName: string; groupName: string;
}; };
type SelectAllCheckboxState = {
checked: boolean;
indeterminate: boolean;
};
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'abp-permission-management', selector: 'abp-permission-management',
templateUrl: './permission-management.component.html', templateUrl: './permission-management.component.html',
exportAs: 'abpPermissionManagement', exportAs: 'abpPermissionManagement',
@ -114,10 +115,8 @@ export class PermissionManagementComponent {
protected readonly service = inject(PermissionsService); protected readonly service = inject(PermissionsService);
protected readonly configState = inject(ConfigStateService); protected readonly configState = inject(ConfigStateService);
protected readonly toasterService = inject(ToasterService); protected readonly toasterService = inject(ToasterService);
private readonly injector = inject(Injector);
private document = inject(DOCUMENT); private document = inject(DOCUMENT);
readonly providerNameInput = input('', { alias: 'providerName' }); readonly providerNameInput = input('', { alias: 'providerName' });
readonly providerKeyInput = input('', { alias: 'providerKey' }); readonly providerKeyInput = input('', { alias: 'providerKey' });
readonly hideBadgesInput = input(false, { alias: 'hideBadges' }); readonly hideBadgesInput = input(false, { alias: 'hideBadges' });
@ -127,9 +126,10 @@ export class PermissionManagementComponent {
readonly visibleChange = output<boolean>(); readonly visibleChange = output<boolean>();
protected readonly modalVisible = signal(false); protected readonly modalVisible = signal(false);
protected readonly modalBusy = signal(false);
protected readonly filter = signal<string>('');
private isOpening = false; private isOpening = false;
private isClosingModal = false; private isClosingModal = false;
// Backward-compatible getters/setters for ReplaceableTemplateDirective. // Backward-compatible getters/setters for ReplaceableTemplateDirective.
@ -157,30 +157,48 @@ export class PermissionManagementComponent {
this._hideBadgesOverride = value; this._hideBadgesOverride = value;
} }
selectAllInThisTabsRef = viewChildren<ElementRef<HTMLInputElement>>('selectAllInThisTabsRef');
selectAllInAllTabsRef = viewChildren<ElementRef<HTMLInputElement>>('selectAllInAllTabsRef');
data: GetPermissionListResultDto = { groups: [], entityDisplayName: '' }; data: GetPermissionListResultDto = { groups: [], entityDisplayName: '' };
selectedGroup?: PermissionGroupDto | null; private readonly permissionsState = signal<PermissionWithGroupName[]>([]);
private readonly selectedGroupState = signal<PermissionGroupDto | null>(null);
private readonly permissionGroupSignal = signal<PermissionGroupDto[]>([]);
permissions: PermissionWithGroupName[] = []; protected readonly selectedGroupPermissions = computed(() => {
const group = this.selectedGroupState();
selectThisTab = false; if (!group) {
return [] as PermissionWithStyle[];
}
selectAllTab = false; const margin = `margin-${
(this.document.body?.dir as LocaleDirection) === 'rtl' ? 'right' : 'left'
}.px`;
disableSelectAllTab = false; const groupPermissions =
this.permissionGroupSignal().find(item => item.name === group.name)?.permissions || [];
const permissions = this.permissionsState();
disabledSelectAllInAllTabs = false; return groupPermissions.map(permission => ({
...permission,
style: { [margin]: findMargin(groupPermissions, permission) },
isGranted: (permissions.find(per => per.name === permission.name) || {}).isGranted,
})) as PermissionWithStyle[];
});
modalBusy = false; protected readonly selectThisTabState = computed(() =>
getSelectAllCheckboxState(this.selectedGroupPermissions(), this.providerName),
);
filter = signal<string>(''); protected readonly selectAllTabState = computed(() =>
getSelectAllCheckboxState(this.permissionsState(), this.providerName),
);
selectedGroupPermissions: PermissionWithStyle[] = []; // Disabled state is based on the API snapshot (not live edits) so select-all stays toggleable.
protected readonly disableSelectAllTab = computed(() =>
isSelectAllDisabled(this.selectedGroupState()?.permissions, this.providerName),
);
permissionGroupSignal = signal<PermissionGroupDto[]>([]); private readonly disabledSelectAllInAllTabsState = signal(false);
protected readonly disabledSelectAllInAllTabs = this.disabledSelectAllInAllTabsState.asReadonly();
permissionGroups = computed(() => { permissionGroups = computed(() => {
const search = this.filter().toLowerCase().trim(); const search = this.filter().toLowerCase().trim();
@ -200,7 +218,7 @@ export class PermissionManagementComponent {
trackByFn: TrackByFunction<PermissionGroupDto> = (_, item) => item.name; trackByFn: TrackByFunction<PermissionGroupDto> = (_, item) => item.name;
// Backward-compatible getter/setter for ReplaceableTemplateDirective. // Backward-compatible getters/setters for ReplaceableTemplateDirective.
get visible(): boolean { get visible(): boolean {
return this.modalVisible(); return this.modalVisible();
} }
@ -221,6 +239,26 @@ export class PermissionManagementComponent {
} }
} }
get permissions(): PermissionWithGroupName[] {
return this.permissionsState();
}
set permissions(value: PermissionWithGroupName[]) {
this.permissionsState.set(value);
}
get selectedGroup(): PermissionGroupDto | null | undefined {
return this.selectedGroupState();
}
get selectThisTab(): boolean {
return this.selectThisTabState().checked;
}
get selectAllTab(): boolean {
return this.selectAllTabState().checked;
}
onModalVisibleChange(value: boolean) { onModalVisibleChange(value: boolean) {
this.visibleChange.emit(value); this.visibleChange.emit(value);
} }
@ -246,9 +284,6 @@ export class PermissionManagementComponent {
.subscribe(() => { .subscribe(() => {
this.modalVisible.set(true); this.modalVisible.set(true);
this.visibleChange.emit(true); this.visibleChange.emit(true);
afterNextRender(() => {
this.initModal();
}, { injector: this.injector });
}); });
} }
@ -265,45 +300,16 @@ export class PermissionManagementComponent {
private resetModalState() { private resetModalState() {
this.setSelectedGroup(null); this.setSelectedGroup(null);
this.filter.set(''); this.filter.set('');
this.selectAllTab = false; this.disabledSelectAllInAllTabsState.set(false);
this.selectThisTab = false;
} }
getChecked(name: string) { getChecked(name: string) {
return (this.permissions.find(per => per.name === name) || { isGranted: false }).isGranted; return (this.permissionsState().find(per => per.name === name) || { isGranted: false })
.isGranted;
} }
setSelectedGroup(group: PermissionGroupDto) { setSelectedGroup(group: PermissionGroupDto | null) {
this.selectedGroup = group; this.selectedGroupState.set(group);
if (!this.selectedGroup) {
this.selectedGroupPermissions = [];
return;
}
const margin = `margin-${
(this.document.body?.dir as LocaleDirection) === 'rtl' ? 'right' : 'left'
}.px`;
const permissions =
(this.data.groups.find(group => group.name === this.selectedGroup?.name) || {}).permissions ||
[];
this.selectedGroupPermissions = permissions.map(permission => ({
...permission,
style: { [margin]: findMargin(permissions, permission) },
isGranted: (this.permissions.find(per => per.name === permission.name) || {}).isGranted,
}));
}
setDisabled(permissions: PermissionGrantInfoDto[]) {
if (permissions.length) {
this.disableSelectAllTab = permissions.every(
permission =>
permission.isGranted &&
permission.grantedProviders?.every(p => p.providerName !== this.providerName),
);
} else {
this.disableSelectAllTab = false;
}
} }
isGrantedByOtherProviderName(grantedProviders?: ProviderInfoDto[]): boolean { isGrantedByOtherProviderName(grantedProviders?: ProviderInfoDto[]): boolean {
@ -319,178 +325,126 @@ export class PermissionManagementComponent {
return; return;
} }
this.setSelectedGroup(this.selectedGroup);
setTimeout(() => { setTimeout(() => {
this.updatePermissionStatus(clickedPermission); this.updatePermissionStatus(clickedPermission);
this.updateSelectedGroupPermissions(clickedPermission);
this.setParentClicked(clickedPermission); this.setParentClicked(clickedPermission);
this.setTabCheckboxState();
this.setGrantCheckboxState();
}, 0); }, 0);
} }
updatePermissionStatus(clickedPermission: PermissionGrantInfoDto) { updatePermissionStatus(clickedPermission: PermissionGrantInfoDto) {
this.permissions = this.permissions.map(permission => { this.permissionsState.update(permissions =>
const isExactMatch = clickedPermission.name == permission.name; permissions.map(permission => {
const isParentOfPermission = clickedPermission.parentName === permission.name; const isExactMatch = clickedPermission.name == permission.name;
const isChildOfPermission = clickedPermission.name === permission.parentName; const isParentOfPermission = clickedPermission.parentName === permission.name;
const isChildOfPermission = clickedPermission.name === permission.parentName;
if (isExactMatch) {
return { ...permission, isGranted: !permission.isGranted }; if (isExactMatch) {
} return { ...permission, isGranted: !permission.isGranted };
}
if (isChildOfPermission && permission.isGranted) { if (isChildOfPermission && permission.isGranted) {
return { ...permission, isGranted: false }; return { ...permission, isGranted: false };
} }
if (isParentOfPermission && !permission.isGranted) { if (isParentOfPermission && !permission.isGranted) {
return { ...permission, isGranted: true }; return { ...permission, isGranted: true };
} }
return permission; return permission;
}); }),
);
} }
setParentClicked(clickedPermission: PermissionGrantInfoDto) { setParentClicked(clickedPermission: PermissionGrantInfoDto) {
if (clickedPermission.parentName) { if (clickedPermission.parentName) {
const parentPermissions = findParentPermissions(this.permissions, clickedPermission); const parentPermissions = findParentPermissions(this.permissionsState(), clickedPermission);
if (parentPermissions.length > 0) { if (parentPermissions.length > 0) {
const parentNames = new Set(parentPermissions.map(parent => parent.name)); const parentNames = new Set(parentPermissions.map(parent => parent.name));
this.permissions = this.permissions.map(per => { this.permissionsState.update(permissions =>
let updatedIsGranted = per.isGranted; permissions.map(per => {
let updatedIsGranted = per.isGranted;
if (per.parentName === clickedPermission.name && !clickedPermission.isGranted) { if (per.parentName === clickedPermission.name && !clickedPermission.isGranted) {
updatedIsGranted = false; updatedIsGranted = false;
} }
if (parentNames.has(per.name)) { if (parentNames.has(per.name)) {
updatedIsGranted = true; updatedIsGranted = true;
} }
return { ...per, isGranted: updatedIsGranted }; return { ...per, isGranted: updatedIsGranted };
}); }),
);
} }
return; return;
} }
this.permissions = this.permissions.map(per => { this.permissionsState.update(permissions =>
const parents = findParentPermissions(this.permissions, per); permissions.map(per => {
if (parents.length > 0) { const parents = findParentPermissions(permissions, per);
const rootParent = parents[parents.length - 1]; if (parents.length > 0) {
const rootParent = parents[parents.length - 1];
if (rootParent.name === clickedPermission.name && !rootParent.isGranted) { if (rootParent.name === clickedPermission.name && !rootParent.isGranted) {
return { ...per, isGranted: false }; return { ...per, isGranted: false };
}
} }
} return per;
return per; }),
});
}
updateSelectedGroupPermissions(clickedPermissions: PermissionGrantInfoDto) {
this.selectedGroupPermissions = this.selectedGroupPermissions.map(per => {
if (per.name === clickedPermissions.name) {
per.isGranted = !per.isGranted;
}
return per;
});
}
setTabCheckboxState() {
const providerName = this.providerName;
const selectablePermissions = this.selectedGroupPermissions.filter(per =>
(per.grantedProviders ?? []).every(p => p.providerName === providerName),
); );
const selectedPermissions = selectablePermissions.filter(per => per.isGranted);
const element = this.document.querySelector(
'#select-all-in-this-tabs',
) as HTMLInputElement | null;
if (!element) {
return;
}
if (selectedPermissions.length === selectablePermissions.length) {
element.indeterminate = false;
this.selectThisTab = true;
} else if (selectedPermissions.length === 0) {
element.indeterminate = false;
this.selectThisTab = false;
} else {
element.indeterminate = true;
}
} }
setGrantCheckboxState() { onSelectThisTabChange(event: Event) {
const providerName = this.providerName; if (this.disableSelectAllTab()) {
const selectablePermissions = this.permissions.filter(per =>
(per.grantedProviders ?? []).every(p => p.providerName === providerName),
);
const selectedAllPermissions = selectablePermissions.filter(per => per.isGranted);
const checkboxElement = this.document.querySelector(
'#select-all-in-all-tabs',
) as HTMLInputElement | null;
if (!checkboxElement) {
return; return;
} }
if (selectedAllPermissions.length === selectablePermissions.length) { const state = this.selectThisTabState();
checkboxElement.indeterminate = false; const checked = !state.checked || state.indeterminate;
this.selectAllTab = true;
} else if (selectedAllPermissions.length === 0) {
checkboxElement.indeterminate = false;
this.selectAllTab = false;
} else {
checkboxElement.indeterminate = true;
}
}
onSelectThisTabChange(event: Event) { this.permissionsState.update(permissions => {
const checked = (event.target as HTMLInputElement).checked; let updatedPermissions = [...permissions];
this.selectThisTab = checked;
this.selectedGroupPermissions.forEach(permission => { this.selectedGroupPermissions().forEach(permission => {
if (permission.isGranted && this.isGrantedByOtherProviderName(permission.grantedProviders)) { if (this.isGrantedByOtherProviderName(permission.grantedProviders)) {
return; return;
} }
const index = this.permissions.findIndex(per => per.name === permission.name); const index = updatedPermissions.findIndex(per => per.name === permission.name);
if (index < 0) {
return;
}
this.permissions = [ updatedPermissions = [
...this.permissions.slice(0, index), ...updatedPermissions.slice(0, index),
{ ...this.permissions[index], isGranted: checked }, { ...updatedPermissions[index], isGranted: checked },
...this.permissions.slice(index + 1), ...updatedPermissions.slice(index + 1),
]; ];
}); });
this.onChangeGroup(this.selectedGroup!); return updatedPermissions;
this.setGrantCheckboxState(); });
} }
onSelectAllChange(event: Event) { onSelectAllChange(event: Event) {
const checked = (event.target as HTMLInputElement).checked; if (this.disabledSelectAllInAllTabs()) {
this.selectAllTab = checked; return;
if (this.filter()) {
this.onFilterChange('');
} }
this.permissions = this.permissions.map(permission => ({ const state = this.selectAllTabState();
...permission, const checked = !state.checked || state.indeterminate;
isGranted: this.isGrantedByOtherProviderName(permission.grantedProviders) || checked,
}));
if (!this.disableSelectAllTab) {
this.selectThisTab = checked;
this.setTabCheckboxState();
}
if (this.selectedGroup) { if (this.filter()) {
this.onChangeGroup(this.selectedGroup); this.onFilterChange('');
} }
this.setGrantCheckboxState(); this.permissionsState.update(permissions =>
permissions.map(permission => ({
...permission,
isGranted: this.isGrantedByOtherProviderName(permission.grantedProviders) || checked,
})),
);
} }
onFilterChange(value: string) { onFilterChange(value: string) {
@ -506,7 +460,7 @@ export class PermissionManagementComponent {
return; return;
} }
if (!groups.some(group => group.name === this.selectedGroup?.name)) { if (!groups.some(group => group.name === this.selectedGroupState()?.name)) {
this.onChangeGroup(groups[0]); this.onChangeGroup(groups[0]);
} }
} }
@ -519,19 +473,17 @@ export class PermissionManagementComponent {
} }
onChangeGroup(group: PermissionGroupDto) { onChangeGroup(group: PermissionGroupDto) {
this.setDisabled(group.permissions);
this.setSelectedGroup(group); this.setSelectedGroup(group);
this.setTabCheckboxState();
} }
submit() { submit() {
if (this.modalBusy) { if (this.modalBusy()) {
return; return;
} }
const unchangedPermissions = getPermissions(this.data.groups); const unchangedPermissions = getPermissions(this.data.groups);
const changedPermissions: UpdatePermissionDto[] = this.permissions const changedPermissions: UpdatePermissionDto[] = this.permissionsState()
.filter(per => .filter(per =>
(unchangedPermissions.find(unchanged => unchanged.name === per.name) || {}).isGranted === (unchangedPermissions.find(unchanged => unchanged.name === per.name) || {}).isGranted ===
per.isGranted per.isGranted
@ -545,7 +497,7 @@ export class PermissionManagementComponent {
return; return;
} }
this.modalBusy = true; this.modalBusy.set(true);
this.service this.service
.update(this.providerName, this.providerKey, { permissions: changedPermissions }) .update(this.providerName, this.providerKey, { permissions: changedPermissions })
.pipe( .pipe(
@ -553,11 +505,7 @@ export class PermissionManagementComponent {
switchMap(() => switchMap(() =>
this.shouldFetchAppConfig() ? this.configState.refreshAppState() : of(null), this.shouldFetchAppConfig() ? this.configState.refreshAppState() : of(null),
), ),
finalize(() => { finalize(() => this.modalBusy.set(false)),
if (this.modalBusy) {
this.modalBusy = false;
}
}),
) )
.subscribe(() => { .subscribe(() => {
this.toasterService.success('AbpUi::SavedSuccessfully'); this.toasterService.success('AbpUi::SavedSuccessfully');
@ -578,29 +526,16 @@ export class PermissionManagementComponent {
this.data = permissionRes; this.data = permissionRes;
this.permissionGroupSignal.set(groups); this.permissionGroupSignal.set(groups);
this.permissions = getPermissions(groups); const permissions = getPermissions(groups);
this.setSelectedGroup(groups[0]); this.permissionsState.set(permissions);
this.disabledSelectAllInAllTabsState.set(isSelectAllDisabled(permissions, providerName));
this.disabledSelectAllInAllTabs = this.permissions.every( this.setSelectedGroup(groups[0] ?? null);
per =>
per.isGranted &&
(per.grantedProviders ?? []).every(provider => provider.providerName !== providerName),
);
}), }),
); );
} }
initModal() {
// TODO: Refactor
setTimeout(() => {
this.setDisabled(this.selectedGroup?.permissions || []);
this.setTabCheckboxState();
this.setGrantCheckboxState();
});
}
getAssignedCount(groupName: string) { getAssignedCount(groupName: string) {
return this.permissions.reduce( return this.permissionsState().reduce(
(acc, val) => (val.groupName === groupName && val.isGranted ? acc + 1 : acc), (acc, val) => (val.groupName === groupName && val.isGranted ? acc + 1 : acc),
0, 0,
); );
@ -619,6 +554,41 @@ export class PermissionManagementComponent {
} }
} }
function isSelectAllDisabled(
permissions: PermissionGrantInfoDto[] | undefined,
providerName: string,
): boolean {
if (!permissions?.length) {
return false;
}
return permissions.every(
permission =>
permission.isGranted &&
permission.grantedProviders?.every(p => p.providerName !== providerName),
);
}
function getSelectAllCheckboxState(
permissions: PermissionGrantInfoDto[],
providerName: string,
): SelectAllCheckboxState {
const selectablePermissions = permissions.filter(permission =>
(permission.grantedProviders ?? []).every(p => p.providerName === providerName),
);
const selectedPermissions = selectablePermissions.filter(permission => permission.isGranted);
if (!selectablePermissions.length || selectedPermissions.length === 0) {
return { checked: false, indeterminate: false };
}
if (selectedPermissions.length === selectablePermissions.length) {
return { checked: true, indeterminate: false };
}
return { checked: false, indeterminate: true };
}
function findParentPermissions( function findParentPermissions(
permissions: PermissionGrantInfoDto[], permissions: PermissionGrantInfoDto[],
permission: PermissionGrantInfoDto, permission: PermissionGrantInfoDto,

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

@ -11,7 +11,17 @@ import {
PermissionsService, PermissionsService,
ResourcePermissionGrantInfoDto, ResourcePermissionGrantInfoDto,
} from '@abp/ng.permission-management/proxy'; } from '@abp/ng.permission-management/proxy';
import { Component, inject, input, model, OnInit, effect, untracked, signal } from '@angular/core'; import {
Component,
effect,
inject,
input,
model,
signal,
untracked,
ChangeDetectionStrategy,
} from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { finalize, switchMap, of } from 'rxjs'; import { finalize, switchMap, of } from 'rxjs';
import { ResourcePermissionStateService } from '../../services/resource-permission-state.service'; import { ResourcePermissionStateService } from '../../services/resource-permission-state.service';
import { ResourcePermissionListComponent } from './resource-permission-list/resource-permission-list.component'; import { ResourcePermissionListComponent } from './resource-permission-list/resource-permission-list.component';
@ -22,6 +32,7 @@ import { eResourcePermissionViewModes } from '../../enums/view-modes';
const DEFAULT_MAX_RESULT_COUNT = 10; const DEFAULT_MAX_RESULT_COUNT = 10;
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'abp-resource-permission-management', selector: 'abp-resource-permission-management',
templateUrl: './resource-permission-management.component.html', templateUrl: './resource-permission-management.component.html',
exportAs: 'abpResourcePermissionManagement', exportAs: 'abpResourcePermissionManagement',
@ -35,14 +46,14 @@ const DEFAULT_MAX_RESULT_COUNT = 10;
ResourcePermissionFormComponent, ResourcePermissionFormComponent,
], ],
}) })
export class ResourcePermissionManagementComponent implements OnInit { export class ResourcePermissionManagementComponent {
readonly eResourcePermissionViewModes = eResourcePermissionViewModes; readonly eResourcePermissionViewModes = eResourcePermissionViewModes;
protected readonly service = inject(PermissionsService); protected readonly service = inject(PermissionsService);
protected readonly toasterService = inject(ToasterService); protected readonly toasterService = inject(ToasterService);
protected readonly confirmationService = inject(ConfirmationService); protected readonly confirmationService = inject(ConfirmationService);
protected readonly state = inject(ResourcePermissionStateService); protected readonly state = inject(ResourcePermissionStateService);
private readonly list = inject(ListService); protected readonly list = inject(ListService);
readonly resourceName = input.required<string>(); readonly resourceName = input.required<string>();
readonly resourceKey = input.required<string>(); readonly resourceKey = input.required<string>();
@ -52,7 +63,31 @@ export class ResourcePermissionManagementComponent implements OnInit {
private readonly previousVisible = signal(false); private readonly previousVisible = signal(false);
private readonly listData = toSignal(
this.list.hookToQuery(query => {
const allData = this.state.allResourcePermissions();
const skipCount = query.skipCount || 0;
const maxResultCount = query.maxResultCount || DEFAULT_MAX_RESULT_COUNT;
const paginatedData = allData.slice(skipCount, skipCount + maxResultCount);
return of({
items: paginatedData,
totalCount: allData.length,
});
}),
{ initialValue: { items: [] as ResourcePermissionGrantInfoDto[], totalCount: 0 } },
);
constructor() { constructor() {
effect(() => {
const result = this.listData();
untracked(() => {
this.state.resourcePermissions.set(result.items);
this.state.totalCount.set(result.totalCount);
});
});
effect(() => { effect(() => {
const resourceName = this.resourceName(); const resourceName = this.resourceName();
const resourceKey = this.resourceKey(); const resourceKey = this.resourceKey();
@ -77,28 +112,6 @@ export class ResourcePermissionManagementComponent implements OnInit {
}); });
} }
ngOnInit() {
this.list.maxResultCount = DEFAULT_MAX_RESULT_COUNT;
this.list
.hookToQuery(query => {
const allData = this.state.allResourcePermissions();
const skipCount = query.skipCount || 0;
const maxResultCount = query.maxResultCount || DEFAULT_MAX_RESULT_COUNT;
const paginatedData = allData.slice(skipCount, skipCount + maxResultCount);
return of({
items: paginatedData,
totalCount: allData.length,
});
})
.subscribe(result => {
this.state.resourcePermissions.set(result.items);
this.state.totalCount.set(result.totalCount);
});
}
openModal() { openModal() {
this.state.modalBusy.set(true); this.state.modalBusy.set(true);

Loading…
Cancel
Save