mirror of https://github.com/abpframework/abp.git
Browse Source
Introduces ResourcePermissionStateService to centralize and manage state for resource permission management. Refactors resource-permission-management.component and related templates to use the new state service, and extracts form, list, and search UI into dedicated components for improved modularity and maintainability.pull/24459/head
9 changed files with 591 additions and 404 deletions
@ -1,2 +1,6 @@ |
|||
export * from './permission-management.component'; |
|||
export * from './resource-permission-management/resource-permission-management.component'; |
|||
export * from './resource-permission-management/provider-key-search/provider-key-search.component'; |
|||
export * from './resource-permission-management/permission-checkbox-list/permission-checkbox-list.component'; |
|||
export * from './resource-permission-management/resource-permission-list/resource-permission-list.component'; |
|||
export * from './resource-permission-management/resource-permission-form/resource-permission-form.component'; |
|||
|
|||
@ -0,0 +1,57 @@ |
|||
import { Component, input, inject, ChangeDetectionStrategy } from '@angular/core'; |
|||
import { LocalizationPipe } from '@abp/ng.core'; |
|||
import { ResourcePermissionStateService } from '../../../services/resource-permission-state.service'; |
|||
|
|||
interface PermissionItem { |
|||
name?: string | null; |
|||
displayName?: string | null; |
|||
} |
|||
|
|||
@Component({ |
|||
selector: 'abp-permission-checkbox-list', |
|||
template: ` |
|||
<div class="mb-3"> |
|||
@if (showTitle()) { |
|||
<h5>{{ title() | abpLocalization }}</h5> |
|||
} |
|||
<div class="form-check form-switch mb-2"> |
|||
<input |
|||
class="form-check-input" |
|||
type="checkbox" |
|||
[id]="'grantAll-' + idPrefix()" |
|||
[checked]="state.allPermissionsSelected()" |
|||
(change)="state.toggleAllPermissions(!state.allPermissionsSelected())" |
|||
/> |
|||
<label class="form-check-label" [for]="'grantAll-' + idPrefix()"> |
|||
{{ 'AbpPermissionManagement::GrantAllResourcePermissions' | abpLocalization }} |
|||
</label> |
|||
</div> |
|||
<div class="border rounded p-3" style="max-height: 300px; overflow-y: auto;"> |
|||
@for (perm of permissions(); track perm.name) { |
|||
<div class="form-check"> |
|||
<input |
|||
class="form-check-input" |
|||
type="checkbox" |
|||
[id]="'perm-' + idPrefix() + '-' + perm.name" |
|||
[checked]="state.isPermissionSelected(perm.name || '')" |
|||
(change)="state.togglePermission(perm.name || '')" |
|||
/> |
|||
<label class="form-check-label" [for]="'perm-' + idPrefix() + '-' + perm.name"> |
|||
{{ perm.displayName }} |
|||
</label> |
|||
</div> |
|||
} |
|||
</div> |
|||
</div> |
|||
`,
|
|||
imports: [LocalizationPipe], |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
}) |
|||
export class PermissionCheckboxListComponent { |
|||
readonly state = inject(ResourcePermissionStateService); |
|||
|
|||
readonly permissions = input.required<PermissionItem[]>(); |
|||
readonly idPrefix = input<string>('default'); |
|||
readonly title = input<string>('AbpPermissionManagement::ResourcePermissionPermissions'); |
|||
readonly showTitle = input<boolean>(true); |
|||
} |
|||
@ -0,0 +1,105 @@ |
|||
import { Component, input, inject, output, OnInit, OnDestroy, ChangeDetectionStrategy } from '@angular/core'; |
|||
import { FormsModule } from '@angular/forms'; |
|||
import { LocalizationPipe } from '@abp/ng.core'; |
|||
import { PermissionsService, SearchProviderKeyInfo } from '@abp/ng.permission-management/proxy'; |
|||
import { Subject, debounceTime, distinctUntilChanged, takeUntil } from 'rxjs'; |
|||
import { ResourcePermissionStateService } from '../../../services/resource-permission-state.service'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-provider-key-search', |
|||
template: ` |
|||
<div class="position-relative"> |
|||
<label class="form-label">{{ 'AbpPermissionManagement::SearchProviderKey' | abpLocalization }}</label> |
|||
<input |
|||
type="text" |
|||
class="form-control" |
|||
[placeholder]="'AbpPermissionManagement::SearchProviderKey' | abpLocalization" |
|||
[ngModel]="state.searchFilter()" |
|||
(ngModelChange)="onSearchInput($event)" |
|||
(focus)="onSearchFocus()" |
|||
(blur)="onSearchBlur($event)" |
|||
/> |
|||
@if (state.searchResults().length > 0 && state.showDropdown()) { |
|||
<div |
|||
class="list-group position-absolute w-100 shadow" |
|||
style="z-index: 1000; max-height: 200px; overflow-y: auto;" |
|||
> |
|||
@for (result of state.searchResults(); track result.providerKey) { |
|||
<button |
|||
type="button" |
|||
class="list-group-item list-group-item-action" |
|||
(mousedown)="selectProviderKey(result)" |
|||
> |
|||
{{ result.providerDisplayName || result.providerKey }} |
|||
</button> |
|||
} |
|||
</div> |
|||
} |
|||
</div> |
|||
`,
|
|||
imports: [FormsModule, LocalizationPipe], |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
}) |
|||
export class ProviderKeySearchComponent implements OnInit, OnDestroy { |
|||
readonly state = inject(ResourcePermissionStateService); |
|||
private readonly service = inject(PermissionsService); |
|||
|
|||
readonly resourceName = input.required<string>(); |
|||
|
|||
readonly keySelected = output<SearchProviderKeyInfo>(); |
|||
|
|||
private readonly searchSubject = new Subject<string>(); |
|||
private readonly destroy$ = new Subject<void>(); |
|||
|
|||
ngOnInit() { |
|||
this.searchSubject.pipe( |
|||
debounceTime(300), |
|||
distinctUntilChanged(), |
|||
takeUntil(this.destroy$) |
|||
).subscribe(filter => { |
|||
this.loadProviderKeys(filter); |
|||
}); |
|||
} |
|||
|
|||
ngOnDestroy() { |
|||
this.destroy$.next(); |
|||
this.destroy$.complete(); |
|||
} |
|||
|
|||
onSearchInput(filter: string) { |
|||
this.state.searchFilter.set(filter); |
|||
this.state.showDropdown.set(true); |
|||
this.searchSubject.next(filter); |
|||
} |
|||
|
|||
onSearchFocus() { |
|||
this.state.showDropdown.set(true); |
|||
this.loadProviderKeys(this.state.searchFilter() || ''); |
|||
} |
|||
|
|||
onSearchBlur(event: FocusEvent) { |
|||
const relatedTarget = event.relatedTarget as HTMLElement; |
|||
if (!relatedTarget?.closest('.list-group')) { |
|||
this.state.showDropdown.set(false); |
|||
} |
|||
} |
|||
|
|||
selectProviderKey(key: SearchProviderKeyInfo) { |
|||
this.state.selectProviderKey(key); |
|||
this.keySelected.emit(key); |
|||
} |
|||
|
|||
private loadProviderKeys(filter: string) { |
|||
const providerName = this.state.selectedProviderName(); |
|||
if (!providerName) return; |
|||
|
|||
this.service.searchResourceProviderKey( |
|||
this.resourceName(), |
|||
providerName, |
|||
filter, |
|||
1 |
|||
).subscribe(res => { |
|||
this.state.searchResults.set(res.keys || []); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
import { Component, input, inject, output, ChangeDetectionStrategy } from '@angular/core'; |
|||
import { FormsModule } from '@angular/forms'; |
|||
import { LocalizationPipe } from '@abp/ng.core'; |
|||
import { ResourcePermissionStateService } from '../../../services/resource-permission-state.service'; |
|||
import { ProviderKeySearchComponent } from '../provider-key-search/provider-key-search.component'; |
|||
import { PermissionCheckboxListComponent } from '../permission-checkbox-list/permission-checkbox-list.component'; |
|||
|
|||
export type FormMode = 'add' | 'edit'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-resource-permission-form', |
|||
template: ` |
|||
@if (mode() === 'add') { |
|||
<div class="mb-3"> |
|||
<label class="form-label fw-bold"> |
|||
{{ 'AbpPermissionManagement::SelectProvider' | abpLocalization }} |
|||
</label> |
|||
<div class="mb-2"> |
|||
@for (provider of state.providers(); track provider.name; let i = $index) { |
|||
<div class="form-check form-check-inline"> |
|||
<input |
|||
class="form-check-input" |
|||
type="radio" |
|||
[id]="'provider-' + i" |
|||
[value]="provider.name" |
|||
[checked]="state.selectedProviderName() === provider.name" |
|||
(change)="state.onProviderChange(provider.name || '')" |
|||
/> |
|||
<label class="form-check-label" [for]="'provider-' + i"> |
|||
{{ provider.displayName }} |
|||
</label> |
|||
</div> |
|||
} |
|||
</div> |
|||
|
|||
<abp-provider-key-search [resourceName]="resourceName()" /> |
|||
</div> |
|||
|
|||
<abp-permission-checkbox-list |
|||
[permissions]="state.permissionDefinitions()" |
|||
idPrefix="add" |
|||
/> |
|||
} @else { |
|||
<div class="mb-3" id="permissionList"> |
|||
<h4>{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}</h4> |
|||
<abp-permission-checkbox-list |
|||
[permissions]="state.permissionsWithProvider()" |
|||
idPrefix="edit" |
|||
[showTitle]="false" |
|||
/> |
|||
</div> |
|||
} |
|||
`,
|
|||
imports: [ |
|||
FormsModule, |
|||
LocalizationPipe, |
|||
ProviderKeySearchComponent, |
|||
PermissionCheckboxListComponent, |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
}) |
|||
export class ResourcePermissionFormComponent { |
|||
readonly state = inject(ResourcePermissionStateService); |
|||
|
|||
readonly mode = input.required<FormMode>(); |
|||
readonly resourceName = input.required<string>(); |
|||
|
|||
readonly save = output<void>(); |
|||
readonly cancel = output<void>(); |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
import { Component, inject, output, ChangeDetectionStrategy } from '@angular/core'; |
|||
import { ListService, LocalizationPipe } from '@abp/ng.core'; |
|||
import { ExtensibleTableComponent, EXTENSIONS_IDENTIFIER } from '@abp/ng.components/extensible'; |
|||
import { ResourcePermissionGrantInfoDto } from '@abp/ng.permission-management/proxy'; |
|||
import { ResourcePermissionStateService } from '../../../services/resource-permission-state.service'; |
|||
import { ePermissionManagementComponents } from '../../../enums/components'; |
|||
import { configureResourcePermissionExtensions } from '../../../services/extensions.service'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-resource-permission-list', |
|||
template: ` |
|||
<div class="d-grid gap-2 mb-3 d-md-flex justify-content-md-end"> |
|||
<button class="btn btn-sm btn-primary" type="button" (click)="addClicked.emit()"> |
|||
<i class="fa fa-plus me-1"></i> |
|||
{{ 'AbpPermissionManagement::AddResourcePermission' | abpLocalization }} |
|||
</button> |
|||
</div> |
|||
|
|||
<ng-template #actionsTemplate let-row> |
|||
<div class="btn-group btn-group-sm" role="group"> |
|||
<button |
|||
class="btn btn-outline-primary" |
|||
type="button" |
|||
(click)="editClicked.emit(row)" |
|||
[title]="'AbpUi::Edit' | abpLocalization" |
|||
> |
|||
<i class="fa fa-edit"></i> |
|||
</button> |
|||
<button |
|||
class="btn btn-outline-danger" |
|||
type="button" |
|||
(click)="deleteClicked.emit(row)" |
|||
[title]="'AbpUi::Delete' | abpLocalization" |
|||
> |
|||
<i class="fa fa-trash"></i> |
|||
</button> |
|||
</div> |
|||
</ng-template> |
|||
|
|||
@if (state.resourcePermissions().length > 0) { |
|||
<abp-extensible-table |
|||
[data]="state.resourcePermissions()" |
|||
[recordsTotal]="state.totalCount()" |
|||
[list]="list" |
|||
[actionsTemplate]="actionsTemplate" |
|||
actionsText="AbpUi::Actions" |
|||
></abp-extensible-table> |
|||
} @else { |
|||
<div class="alert alert-info"> |
|||
{{ 'AbpPermissionManagement::NoPermissionsAssigned' | abpLocalization }} |
|||
</div> |
|||
} |
|||
`,
|
|||
providers: [ |
|||
ListService, |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: ePermissionManagementComponents.ResourcePermissions, |
|||
}, |
|||
], |
|||
imports: [LocalizationPipe, ExtensibleTableComponent], |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
}) |
|||
export class ResourcePermissionListComponent { |
|||
readonly state = inject(ResourcePermissionStateService); |
|||
readonly list = inject(ListService); |
|||
|
|||
readonly addClicked = output<void>(); |
|||
readonly editClicked = output<ResourcePermissionGrantInfoDto>(); |
|||
readonly deleteClicked = output<ResourcePermissionGrantInfoDto>(); |
|||
|
|||
constructor() { |
|||
configureResourcePermissionExtensions(); |
|||
} |
|||
} |
|||
@ -1,165 +1,60 @@ |
|||
<abp-modal [(visible)]="visible" [busy]="modalBusy()" [options]="{ size: 'xl', scrollable: false }"> |
|||
<abp-modal [(visible)]="visible" [busy]="state.modalBusy()" [options]="{ size: 'xl', scrollable: false }"> |
|||
<ng-template #abpHeader> |
|||
<h5 class="modal-title"> |
|||
@if (viewMode() === 'edit') { |
|||
@switch (state.viewMode()) { |
|||
@case ('edit') { |
|||
{{ 'AbpPermissionManagement::UpdatePermission' | abpLocalization }} |
|||
} @else if (viewMode() === 'add') { |
|||
} |
|||
@case ('add') { |
|||
{{ 'AbpPermissionManagement::AddResourcePermission' | abpLocalization }} |
|||
} @else { |
|||
} |
|||
@default { |
|||
{{ 'AbpPermissionManagement::ResourcePermissions' | abpLocalization }} |
|||
@if (resourceDisplayName) { |
|||
- {{ resourceDisplayName }} |
|||
@if (resourceDisplayName()) { |
|||
- {{ resourceDisplayName() }} |
|||
} |
|||
} |
|||
} |
|||
</h5> |
|||
</ng-template> |
|||
|
|||
<ng-template #abpBody> |
|||
@if (!hasResourcePermission() || !hasProviderKeyLookupService()) { |
|||
@if (!state.hasResourcePermission() || !state.hasProviderKeyLookupService()) { |
|||
<div class="alert alert-warning" role="alert"> |
|||
@if (!hasResourcePermission()) { |
|||
@if (!state.hasResourcePermission()) { |
|||
{{ 'AbpPermissionManagement::NoResourcePermissionFound' | abpLocalization }} |
|||
} @else { |
|||
{{ 'AbpPermissionManagement::NoResourceProviderKeyLookupServiceFound' | abpLocalization }} |
|||
} |
|||
</div> |
|||
} @else { |
|||
<!-- LIST VIEW --> |
|||
@if (viewMode() === 'list') { |
|||
<div class="d-grid gap-2 mb-3 d-md-flex justify-content-md-end"> |
|||
<button class="btn btn-sm btn-primary" type="button" (click)="goToAddMode()"> |
|||
<i class="fa fa-plus me-1"></i> |
|||
{{ 'AbpPermissionManagement::AddResourcePermission' | abpLocalization }} |
|||
</button> |
|||
</div> |
|||
|
|||
<ng-template #actionsTemplate let-row> |
|||
<div class="btn-group btn-group-sm" role="group"> |
|||
<button class="btn btn-outline-primary" type="button" (click)="goToEditMode(row)" |
|||
[title]="'AbpUi::Edit' | abpLocalization"> |
|||
<i class="fa fa-edit"></i> |
|||
</button> |
|||
<button class="btn btn-outline-danger" type="button" (click)="deletePermission(row)" |
|||
[title]="'AbpUi::Delete' | abpLocalization"> |
|||
<i class="fa fa-trash"></i> |
|||
</button> |
|||
</div> |
|||
</ng-template> |
|||
|
|||
@if (resourcePermissions().length > 0) { |
|||
<abp-extensible-table [data]="resourcePermissions()" [recordsTotal]="totalCount()" [list]="list" |
|||
[actionsTemplate]="actionsTemplate" actionsText="AbpUi::Actions"></abp-extensible-table> |
|||
} @else { |
|||
<div class="alert alert-info"> |
|||
{{ 'AbpPermissionManagement::NoPermissionsAssigned' | abpLocalization }} |
|||
</div> |
|||
@switch (state.viewMode()) { |
|||
@case ('list') { |
|||
<abp-resource-permission-list (addClicked)="onAddClicked()" (editClicked)="onEditClicked($event)" |
|||
(deleteClicked)="onDeleteClicked($event)" /> |
|||
} |
|||
@case ('add') { |
|||
<abp-resource-permission-form mode="add" [resourceName]="resourceName()" /> |
|||
} |
|||
|
|||
<!-- ADD VIEW --> |
|||
@if (viewMode() === 'add') { |
|||
<div class="mb-3"> |
|||
<label class="form-label fw-bold">{{ 'AbpPermissionManagement::SelectProvider' | abpLocalization }}</label> |
|||
<div class="mb-2"> |
|||
@for (provider of providers(); track provider.name; let i = $index) { |
|||
<div class="form-check form-check-inline"> |
|||
<input class="form-check-input" type="radio" [id]="'provider-' + i" [value]="provider.name" |
|||
[checked]="selectedProviderName() === provider.name" |
|||
(change)="onProviderChange(provider.name || '')" /> |
|||
<label class="form-check-label" [for]="'provider-' + i"> |
|||
{{ provider.displayName }} |
|||
</label> |
|||
</div> |
|||
} |
|||
</div> |
|||
|
|||
<div class="position-relative mb-3"> |
|||
<label class="form-label">{{ 'AbpPermissionManagement::SearchProviderKey' | abpLocalization }}</label> |
|||
<input type="text" class="form-control" |
|||
[placeholder]="'AbpPermissionManagement::SearchProviderKey' | abpLocalization" |
|||
[ngModel]="searchFilter()" (ngModelChange)="onSearchInput($event)" (focus)="onSearchFocus()" |
|||
(blur)="onSearchBlur()" /> |
|||
@if (searchResults().length > 0 && showDropdown()) { |
|||
<div class="list-group position-absolute w-100 shadow" |
|||
style="z-index: 1000; max-height: 200px; overflow-y: auto;"> |
|||
@for (result of searchResults(); track result.providerKey) { |
|||
<button type="button" class="list-group-item list-group-item-action" |
|||
(mousedown)="selectProviderKey(result)"> |
|||
{{ result.providerDisplayName || result.providerKey }} |
|||
</button> |
|||
} |
|||
</div> |
|||
} |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="mb-3"> |
|||
<h5>{{ 'AbpPermissionManagement::ResourcePermissionPermissions' | abpLocalization }}</h5> |
|||
<div class="form-check form-switch mb-2"> |
|||
<input class="form-check-input" type="checkbox" id="grantAllAdd" [checked]="allPermissionsSelected()" |
|||
(change)="toggleAllPermissions(!allPermissionsSelected())" /> |
|||
<label class="form-check-label" for="grantAllAdd"> |
|||
{{ 'AbpPermissionManagement::GrantAllResourcePermissions' | abpLocalization }} |
|||
</label> |
|||
</div> |
|||
<div class="border rounded p-3" style="max-height: 300px; overflow-y: auto;"> |
|||
@for (perm of permissionDefinitions(); track perm.name) { |
|||
<div class="form-check"> |
|||
<input class="form-check-input" type="checkbox" [id]="'perm-add-' + perm.name" |
|||
[checked]="isPermissionSelected(perm.name || '')" |
|||
(change)="togglePermission(perm.name || '')" /> |
|||
<label class="form-check-label" [for]="'perm-add-' + perm.name"> |
|||
{{ perm.displayName }} |
|||
</label> |
|||
</div> |
|||
} |
|||
</div> |
|||
</div> |
|||
@case ('edit') { |
|||
<abp-resource-permission-form mode="edit" [resourceName]="resourceName()" /> |
|||
} |
|||
|
|||
<!-- EDIT VIEW --> |
|||
@if (viewMode() === 'edit') { |
|||
<div class="mb-3" id="permissionList"> |
|||
<h4>{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}</h4> |
|||
<div class="form-check form-switch mb-2"> |
|||
<input class="form-check-input" type="checkbox" id="grantAllEdit" [checked]="allPermissionsSelected()" |
|||
(change)="toggleAllPermissions(!allPermissionsSelected())" /> |
|||
<label class="form-check-label" for="grantAllEdit"> |
|||
{{ 'AbpPermissionManagement::GrantAllResourcePermissions' | abpLocalization }} |
|||
</label> |
|||
</div> |
|||
@for (perm of permissionsWithProvider(); track perm.name) { |
|||
<div class="form-check"> |
|||
<input class="form-check-input" type="checkbox" [id]="'perm-edit-' + perm.name" |
|||
[checked]="isPermissionSelected(perm.name || '')" (change)="togglePermission(perm.name || '')" /> |
|||
<label class="form-check-label" [for]="'perm-edit-' + perm.name"> |
|||
{{ perm.displayName }} |
|||
</label> |
|||
</div> |
|||
} |
|||
</div> |
|||
} |
|||
} |
|||
</ng-template> |
|||
|
|||
<ng-template #abpFooter> |
|||
@if (viewMode() === 'list') { |
|||
@if (state.isListMode()) { |
|||
<button type="button" class="btn btn-outline-primary" abpClose> |
|||
{{ 'AbpUi::Close' | abpLocalization }} |
|||
</button> |
|||
} @else { |
|||
<button type="button" class="btn btn-outline-secondary" (click)="goToListMode()"> |
|||
<button type="button" class="btn btn-outline-secondary" (click)="state.goToListMode()"> |
|||
{{ 'AbpUi::Cancel' | abpLocalization }} |
|||
</button> |
|||
@if (viewMode() === 'add') { |
|||
<abp-button iconClass="fa fa-check" (click)="saveAddPermission()"> |
|||
<abp-button iconClass="fa fa-check" (click)="savePermission()"> |
|||
{{ 'AbpUi::Save' | abpLocalization }} |
|||
</abp-button> |
|||
} @else { |
|||
<abp-button iconClass="fa fa-check" (click)="saveEditPermission()"> |
|||
{{ 'AbpUi::Save' | abpLocalization }} |
|||
</abp-button> |
|||
} |
|||
} |
|||
</ng-template> |
|||
</abp-modal> |
|||
@ -1 +1,2 @@ |
|||
export * from './extensions.service'; |
|||
export * from './resource-permission-state.service'; |
|||
|
|||
@ -0,0 +1,165 @@ |
|||
import { Injectable, signal, computed } from '@angular/core'; |
|||
import { |
|||
ResourcePermissionGrantInfoDto, |
|||
ResourceProviderDto, |
|||
ResourcePermissionDefinitionDto, |
|||
SearchProviderKeyInfo, |
|||
ResourcePermissionWithProdiverGrantInfoDto, |
|||
} from '@abp/ng.permission-management/proxy'; |
|||
|
|||
export type ViewMode = 'list' | 'add' | 'edit'; |
|||
|
|||
@Injectable() |
|||
export class ResourcePermissionStateService { |
|||
// View state
|
|||
readonly viewMode = signal<ViewMode>('list'); |
|||
readonly modalBusy = signal(false); |
|||
readonly hasResourcePermission = signal(false); |
|||
readonly hasProviderKeyLookupService = signal(false); |
|||
|
|||
// Resource data
|
|||
readonly resourceName = signal(''); |
|||
readonly resourceKey = signal(''); |
|||
readonly resourceDisplayName = signal<string | undefined>(undefined); |
|||
|
|||
// Permissions data
|
|||
readonly allResourcePermissions = signal<ResourcePermissionGrantInfoDto[]>([]); |
|||
readonly resourcePermissions = signal<ResourcePermissionGrantInfoDto[]>([]); |
|||
readonly totalCount = signal(0); |
|||
readonly permissionDefinitions = signal<ResourcePermissionDefinitionDto[]>([]); |
|||
readonly permissionsWithProvider = signal<ResourcePermissionWithProdiverGrantInfoDto[]>([]); |
|||
readonly selectedPermissions = signal<string[]>([]); |
|||
|
|||
// Provider data
|
|||
readonly providers = signal<ResourceProviderDto[]>([]); |
|||
readonly selectedProviderName = signal(''); |
|||
readonly selectedProviderKey = signal(''); |
|||
|
|||
// Edit mode specific
|
|||
readonly editProviderName = signal(''); |
|||
readonly editProviderKey = signal(''); |
|||
|
|||
// Search state
|
|||
readonly searchFilter = signal(''); |
|||
readonly searchResults = signal<SearchProviderKeyInfo[]>([]); |
|||
readonly showDropdown = signal(false); |
|||
|
|||
// Computed properties
|
|||
readonly isAddMode = computed(() => this.viewMode() === 'add'); |
|||
readonly isEditMode = computed(() => this.viewMode() === 'edit'); |
|||
readonly isListMode = computed(() => this.viewMode() === 'list'); |
|||
|
|||
readonly currentPermissionsList = computed(() => |
|||
this.isAddMode() ? this.permissionDefinitions() : this.permissionsWithProvider() |
|||
); |
|||
|
|||
readonly allPermissionsSelected = computed(() => { |
|||
const definitions = this.currentPermissionsList(); |
|||
return definitions.length > 0 && |
|||
definitions.every(p => this.selectedPermissions().includes(p.name || '')); |
|||
}); |
|||
|
|||
readonly canSave = computed(() => { |
|||
if (this.isAddMode()) { |
|||
return !!this.selectedProviderKey() && this.selectedPermissions().length > 0; |
|||
} |
|||
return this.selectedPermissions().length >= 0; |
|||
}); |
|||
|
|||
// State transition methods
|
|||
goToListMode() { |
|||
this.viewMode.set('list'); |
|||
this.selectedPermissions.set([]); |
|||
} |
|||
|
|||
goToAddMode() { |
|||
this.viewMode.set('add'); |
|||
this.selectedPermissions.set([]); |
|||
this.selectedProviderKey.set(''); |
|||
this.searchResults.set([]); |
|||
this.searchFilter.set(''); |
|||
} |
|||
|
|||
prepareEditMode(grant: ResourcePermissionGrantInfoDto) { |
|||
this.editProviderName.set(grant.providerName || ''); |
|||
this.editProviderKey.set(grant.providerKey || ''); |
|||
} |
|||
|
|||
setEditModePermissions(permissions: ResourcePermissionWithProdiverGrantInfoDto[]) { |
|||
this.permissionsWithProvider.set(permissions); |
|||
this.selectedPermissions.set( |
|||
permissions.filter(p => p.isGranted).map(p => p.name || '') |
|||
); |
|||
this.viewMode.set('edit'); |
|||
} |
|||
|
|||
// Permission selection methods
|
|||
togglePermission(permissionName: string) { |
|||
const current = this.selectedPermissions(); |
|||
if (current.includes(permissionName)) { |
|||
this.selectedPermissions.set(current.filter(p => p !== permissionName)); |
|||
} else { |
|||
this.selectedPermissions.set([...current, permissionName]); |
|||
} |
|||
} |
|||
|
|||
toggleAllPermissions(selectAll: boolean) { |
|||
const permissions = this.currentPermissionsList(); |
|||
this.selectedPermissions.set( |
|||
selectAll ? permissions.map(p => p.name || '') : [] |
|||
); |
|||
} |
|||
|
|||
isPermissionSelected(permissionName: string): boolean { |
|||
return this.selectedPermissions().includes(permissionName); |
|||
} |
|||
|
|||
// Provider search methods
|
|||
onProviderChange(providerName: string) { |
|||
this.selectedProviderName.set(providerName); |
|||
this.selectedProviderKey.set(''); |
|||
this.searchResults.set([]); |
|||
this.searchFilter.set(''); |
|||
} |
|||
|
|||
selectProviderKey(key: SearchProviderKeyInfo) { |
|||
this.selectedProviderKey.set(key.providerKey || ''); |
|||
this.searchFilter.set(key.providerDisplayName || key.providerKey || ''); |
|||
this.searchResults.set([]); |
|||
this.showDropdown.set(false); |
|||
} |
|||
|
|||
// Reset all state
|
|||
reset() { |
|||
this.viewMode.set('list'); |
|||
this.allResourcePermissions.set([]); |
|||
this.resourcePermissions.set([]); |
|||
this.totalCount.set(0); |
|||
this.selectedProviderName.set(''); |
|||
this.selectedProviderKey.set(''); |
|||
this.searchFilter.set(''); |
|||
this.selectedPermissions.set([]); |
|||
this.searchResults.set([]); |
|||
this.editProviderName.set(''); |
|||
this.editProviderKey.set(''); |
|||
} |
|||
|
|||
// Data loading helpers
|
|||
setResourceData(permissions: ResourcePermissionGrantInfoDto[]) { |
|||
this.allResourcePermissions.set(permissions); |
|||
this.totalCount.set(permissions.length); |
|||
} |
|||
|
|||
setProviders(providers: ResourceProviderDto[]) { |
|||
this.providers.set(providers); |
|||
this.hasProviderKeyLookupService.set(providers.length > 0); |
|||
if (providers.length) { |
|||
this.selectedProviderName.set(providers[0].name || ''); |
|||
} |
|||
} |
|||
|
|||
setDefinitions(permissions: ResourcePermissionDefinitionDto[]) { |
|||
this.permissionDefinitions.set(permissions); |
|||
this.hasResourcePermission.set(permissions.length > 0); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue