Skip to content

Resource Based Permission - Angular UI Issue 24299 - #24459

Merged
oykuermann merged 15 commits into
devfrom
issue-24299
Dec 26, 2025
Merged

oykuermann merged 15 commits into
devfrom
issue-24299

Conversation

@fahrigedik

@fahrigedik fahrigedik commented Dec 22, 2025 •

Copy link
Copy Markdown
Member

Description

Resolves #24299 (write the related issue number if available)

How to test it?

you have to change test-branch-24299
you have to run dbmigrator and hostwithids on app templates
you have to run dev-app

Introduces ResourcePermissionManagementComponent with UI and logic for managing resource-based permissions. Updates models and service to support resource permission APIs, and exports the new component in the index.
Moved resource-permission-management component files into a dedicated folder and updated imports. Replaced the manual table implementation with the ExtensibleTableComponent for resource permissions, added client-side pagination, and introduced extension points for entity property configuration. Added new defaults, services, and tokens to support extensibility and improved maintainability.
Added new translation keys for 'UpdatePermission', 'NoPermissionsAssigned', 'SelectProvider', 'SearchProviderKey', and 'Provider' across all supported languages in the permission management module. This enhances localization support for new UI features related to provider selection and permission assignment.
Added 'ErrorLoadingPermissions' and 'PleaseSelectProviderAndPermissions' keys to all language JSON files in the permission management module to support new error and prompt messages in the UI.
@fahrigedik fahrigedik added this to the 10.0-patch milestone Dec 22, 2025
Enhances the provider key search input with focus/blur handling and a dropdown for results, improving user experience. Adds a confirmation dialog before deleting a permission, preventing accidental deletions. Refactors related logic for clarity and better state management.
protected readonly confirmationService = inject(ConfirmationService);
readonly list = inject(ListService);

@Input() resourceName!: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to use the latest input and output signal functions instead.

@gizemmutukurt
gizemmutukurt requested review from oykuermann and removed request for yagmurcelk December 24, 2025 06:20
}
}

toggleAllPermissions(selectAll: boolean) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, we can improve the readability here like this

toggleAllPermissions(selectAll: boolean) {
        let toggleAction = selectAll ? this.permissionsWithProvider().map(p => p.name || '') : [];
        if (this.viewMode() === 'add') {
            toggleAction = this.permissionDefinitions().map(p => p.name || '');
        }
        this.selectedPermissions.set(toggleAction);
    }

}
</div>

<div class="position-relative mb-3">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can extract this and create generic component to behave like a lookup search component. You can check this as a reference https://github.com/volosoft/volo/tree/dev/abp/npm/ng-packs/packages/commercial-ui/src/lib/components/lookup

@fahrigedik
fahrigedik marked this pull request as draft December 24, 2025 06:36
</button>
</div>

<ng-template #actionsTemplate let-row>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These buttons does not seem configured to be a dropdown as an action button. We should try the bootstrap dropdown if possible.

sumeyyeKurtulus and others added 4 commits December 24, 2025 09:38
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.
Moved inline templates to separate HTML files for permission-checkbox-list, provider-key-search, resource-permission-form, and resource-permission-list components. Updated component decorators to reference the new template files, improving maintainability and separation of concerns.
this.searchSubject.pipe(
debounceTime(300),
distinctUntilChanged()
).subscribe(filter => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subscription should be unsubscribed when the page is destroyed.

Introduces a generic LookupSearchComponent for reusable lookup/search UI in Angular. Refactors the provider key search in permission management to use the new component, simplifying its logic and improving maintainability. Updates tsconfig paths to include the new lookup component package.
<abp-modal [(visible)]="visible" [busy]="modalBusy()" [options]="{ size: 'xl', scrollable: false }">
<ng-template #abpHeader>
<h5 class="modal-title">
@if (viewMode() === 'edit') {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can define enum for ViewModes instead of using hardcoded string. Example;

export enum ViewModeValues {
  List = 'list',
  Add = 'add',
  Edit = 'edit'
}

Replaced string literals for view modes with the new eResourcePermissionViewModes enum across components and services. This improves type safety and maintainability. Added the enum definition in a new file.
@fahrigedik
fahrigedik marked this pull request as ready for review December 24, 2025 17:04
this.searchSubject.pipe(
debounceTime(this.debounceTime()),
distinctUntilChanged(),
takeUntil(this.destroy$)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use takeUntilDestroyed instead. By this means, we will not need this un-subscription on destroy

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }

The same applies for this component :: npm/ng-packs/packages/permission-management/src/lib/components/resource-permission-management/provider-key-search/provider-key-search.component.ts

Here is a quick reference https://www.reddit.com/r/angular/comments/12vbfbd/angular_16_takeuntildestroyed_operator/

).subscribe({
next: results => {
this.searchResults.set(results);
this.isLoading.set(false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can set the load false on finalize inside pipe to remove the duplication.

private previousVisible = false;

constructor() {
effect(() => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make this effect work more efficiently. Here is a quick example

    effect(() => {
      // Read all input values to track them
      const resourceName = this.resourceName();
      const resourceKey = this.resourceKey();
      const resourceDisplayName = this.resourceDisplayName();

      // Use untracked to prevent this effect from tracking writes to state signals
      // This prevents circular dependencies and reduces unnecessary re-executions
      untracked(() => {
        // Only update if values have actually changed (signals optimize this internally)
        this.state.resourceName.set(resourceName);
        this.state.resourceKey.set(resourceKey);
        this.state.resourceDisplayName.set(resourceDisplayName);
      });
    });


@if (showDropdown() && !disabled()) {
<div class="abp-lookup-dropdown list-group position-absolute w-100 shadow"
style="z-index: 1050; max-height: 200px; overflow-y: auto;">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to use class instead of inline styles

<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"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use string interpolation. it's more readable.

id="perm-{{ idPrefix() }}-{{ perm.name }}"

{{ 'AbpPermissionManagement::GrantAllResourcePermissions' | abpLocalization }}
</label>
</div>
<div class="border rounded p-3" style="max-height: 300px; overflow-y: auto;">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to use class instead of inline styles


readonly visible = model<boolean>(false);

private previousVisible = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use signal for previousVisible

}

ngOnInit() {
this.list.maxResultCount = 10;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can define constant variable for maxResultCount instead of using hardcoded value

Refactored lookup-search and permission-checkbox-list components to use SCSS for dropdown and list container styling. Improved resource permission management component with signals and untracked for state updates, and replaced manual destroy logic with Angular's DestroyRef and takeUntilDestroyed. Updated HTML templates for better readability and accessibility.
@oykuermann
oykuermann merged commit 53c93e7 into dev Dec 26, 2025
2 of 3 checks passed
@oykuermann
oykuermann deleted the issue-24299 branch December 26, 2025 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Angular UI for Resource Based Permission Management

4 participants