Browse Source

Merge pull request #24689 from abpframework/issue-24684

Angular Aria Implementation for ABP Packages - Issue 24684
pull/24758/head
oykuermann 1 week ago
committed by GitHub
parent
commit
c59db2f5cd
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      npm/ng-packs/packages/feature-management/package.json
  2. 42
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html
  3. 11
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts
  4. 3
      npm/ng-packs/packages/identity/package.json
  5. 72
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.html
  6. 12
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts
  7. 3
      npm/ng-packs/packages/permission-management/package.json
  8. 123
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html
  9. 22
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts
  10. 2
      npm/ng-packs/packages/setting-management/package.json

3
npm/ng-packs/packages/feature-management/package.json

@ -10,6 +10,9 @@
"@abp/ng.theme.shared": "~10.1.0-rc.2",
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/aria": "~21.0.0"
},
"publishConfig": {
"access": "public"
}

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

@ -12,18 +12,26 @@
<ng-template #abpBody>
<div class="row">
@if (groups.length) {
<div class="col-md-4">
<ul
ngbNav
#nav="ngbNav"
[(activeId)]="selectedGroupDisplayName"
class="nav-pills"
orientation="vertical"
>
<div ngTabs orientation="vertical" class="row">
<div class="col-md-4">
<div ngTabList orientation="vertical" selectionMode="follow" [(selectedTab)]="selectedGroupDisplayName" class="nav nav-pills flex-column">
@for (group of groups; track group.name) {
<button ngTab #tab="ngTab" type="button" [value]="group.displayName" class="nav-link text-start" [class.active]="tab.selected()">
{{ group.displayName }}
</button>
}
</div>
</div>
<ng-template #descTmp let-description>
@if (description) {
<small class="d-block form-text text-muted">{{ description }}</small>
}
</ng-template>
<div class="col-md-8">
@for (group of groups; track group.name) {
<li [ngbNavItem]="group.displayName">
<a ngbNavLink>{{ group.displayName }}</a>
<ng-template ngbNavContent>
<div ngTabPanel [value]="group.displayName">
<ng-template ngTabContent>
<h4>{{ selectedGroupDisplayName }}</h4>
<hr class="mt-2 mb-3" />
@ -128,18 +136,10 @@
</div>
}
</ng-template>
</li>
</div>
}
</ul>
</div>
</div>
<ng-template #descTmp let-description>
@if (description) {
<small class="d-block form-text text-muted">{{ description }}</small>
}
</ng-template>
<div class="col-md-8"><div class="py-0" [ngbNavOutlet]="nav"></div></div>
}
@if (!groups.length) {

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

@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, Output, inject, DOCUMENT } from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';
import { NgTemplateOutlet, NgStyle } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ConfigStateService, LocalizationPipe, TrackByService } from '@abp/ng.core';
import {
@ -17,7 +17,7 @@ import {
ModalComponent,
ToasterService,
} from '@abp/ng.theme.shared';
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
import { Tabs, TabList, Tab, TabPanel, TabContent } from '@angular/aria/tabs';
import { finalize } from 'rxjs/operators';
import { FreeTextInputDirective } from '../../directives';
import { FeatureManagement } from '../../models';
@ -36,11 +36,16 @@ const DEFAULT_PROVIDER_NAME = 'D';
exportAs: 'abpFeatureManagement',
imports: [
NgTemplateOutlet,
NgStyle,
ButtonComponent,
ModalComponent,
LocalizationPipe,
FormsModule,
NgbNavModule,
Tabs,
TabList,
Tab,
TabPanel,
TabContent,
FreeTextInputDirective,
ModalCloseDirective,
],

3
npm/ng-packs/packages/identity/package.json

@ -12,6 +12,9 @@
"@abp/ng.theme.shared": "~10.1.0-rc.2",
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/aria": "~21.0.0"
},
"publishConfig": {
"access": "public"
}

72
npm/ng-packs/packages/identity/src/lib/components/users/users.component.html

@ -28,39 +28,47 @@
<ng-template #abpBody>
@if (form) {
<form [formGroup]="form" (ngSubmit)="save()">
<ul ngbNav #nav="ngbNav" class="nav-tabs">
<li ngbNavItem>
<a ngbNavLink>{{ 'AbpIdentity::UserInformations' | abpLocalization }}</a>
<ng-template ngbNavContent>
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</ng-template>
</li>
<div ngTabs selectionMode="follow">
<div ngTabList [(selectedTab)]="selectedTab" class="nav nav-tabs">
<button ngTab #tabInfo="ngTab" [value]="'user-info'" class="nav-link" [class.active]="tabInfo.selected()" type="button">
{{ 'AbpIdentity::UserInformations' | abpLocalization }}
</button>
<button ngTab #tabRoles="ngTab" [value]="'roles'" class="nav-link" [class.active]="tabRoles.selected()" type="button">
{{ 'AbpIdentity::Roles' | abpLocalization }}
</button>
</div>
<li ngbNavItem>
<a ngbNavLink>{{ 'AbpIdentity::Roles' | abpLocalization }}</a>
<ng-template ngbNavContent>
@for (roleGroup of roleGroups; track $index; let i = $index) {
<div class="form-check mb-2">
<abp-checkbox
*abpReplaceableTemplate="{
inputs: {
checkboxId: 'roles-' + i,
label: roles[i].name,
formControl: roleGroup.controls[roles[i].name]
},
componentKey: inputKey
}"
[checkboxId]="'roles-' + i"
[formControl]="roleGroup.controls[roles[i].name]"
[label]="roles[i].name"
>
</abp-checkbox>
</div>
}
</ng-template>
</li>
</ul>
<div class="mt-2 fade-in-top" [ngbNavOutlet]="nav"></div>
<div class="mt-2 fade-in-top">
<div ngTabPanel [value]="'user-info'">
<ng-template ngTabContent>
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</ng-template>
</div>
<div ngTabPanel [value]="'roles'">
<ng-template ngTabContent>
@for (roleGroup of roleGroups; track $index; let i = $index) {
<div class="form-check mb-2">
<abp-checkbox
*abpReplaceableTemplate="{
inputs: {
checkboxId: 'roles-' + i,
label: roles[i].name,
formControl: roleGroup.controls[roles[i].name]
},
componentKey: inputKey
}"
[checkboxId]="'roles-' + i"
[formControl]="roleGroup.controls[roles[i].name]"
[label]="roles[i].name"
>
</abp-checkbox>
</div>
}
</ng-template>
</div>
</div>
</div>
</form>
} @else {
<div class="text-center"><i class="fa fa-pulse fa-spinner" aria-hidden="true"></i></div>

12
npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts

@ -52,7 +52,8 @@ import {
import { finalize, switchMap, tap } from 'rxjs/operators';
import { eIdentityComponents } from '../../enums/components';
import { PageComponent } from '@abp/ng.components/page';
import { NgbDropdownModule, NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { Tabs, TabList, Tab, TabPanel, TabContent } from '@angular/aria/tabs';
import { NgxValidateCoreModule } from '@ngx-validate/core';
@Component({
@ -70,7 +71,11 @@ import { NgxValidateCoreModule } from '@ngx-validate/core';
FormsModule,
PermissionManagementComponent,
PageComponent,
NgbNavModule,
Tabs,
TabList,
Tab,
TabPanel,
TabContent,
NgbDropdownModule,
NgxValidateCoreModule,
LocalizationPipe,
@ -101,6 +106,8 @@ export class UsersComponent implements OnInit {
selected?: IdentityUserDto;
selectedTab = 'user-info';
selectedUserRoles?: IdentityRoleDto[];
roles?: IdentityRoleDto[];
@ -159,6 +166,7 @@ export class UsersComponent implements OnInit {
}
openModal() {
this.selectedTab = 'user-info';
this.buildForm();
this.isModalVisible = true;
}

3
npm/ng-packs/packages/permission-management/package.json

@ -10,6 +10,9 @@
"@abp/ng.theme.shared": "~10.1.0-rc.2",
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/aria": "~21.0.0"
},
"publishConfig": {
"access": "public"
},

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

@ -43,18 +43,27 @@
<legend class="px-1 h5 mb-0">
{{ 'AbpPermissionManagement::PermissionGroup' | abpLocalization }}
</legend>
<div class="row">
<div class="row" ngTabs orientation="vertical">
<div class="col-md-4">
<div class="overflow-auto lpx-scroll-pills-container scroll-in-modal">
<ul class="nav nav-pills flex-column">
<div
class="overflow-auto lpx-scroll-pills-container scroll-in-modal"
ngTabList
orientation="vertical"
selectionMode="follow"
[selectedTab]="selectedGroup?.name"
(selectedTabChange)="onTabChange($event)"
>
<div class="nav nav-pills flex-column">
@for (group of permissionGroups(); track $index) {
<li class="border nav-item">
<div class="border nav-item">
@if ({ assignedCount: getAssignedCount(group.name) }; as count) {
<a
class="nav-link pointer"
[class.active]="selectedGroup?.name === group?.name"
(click)="onChangeGroup(group)"
(select)="setDisabled(group.permissions)"
<button
ngTab
[value]="group.name"
class="nav-link pointer text-start w-100"
#tab="ngTab"
[class.active]="tab.selected()"
type="button"
>
<div [class.font-weight-bold]="count.assignedCount">
{{ group?.displayName }}
@ -62,59 +71,65 @@
<span>({{ count.assignedCount }})</span>
}
</div>
</a>
</button>
}
</li>
</div>
}
</ul>
</div>
</div>
</div>
<div class="col-md-8 scroll-in-modal">
<div class="ps-1">
@if (selectedGroupPermissions.length) {
<div class="form-check mb-2">
<input
#selectAllInThisTabsRef
type="checkbox"
id="select-all-in-this-tabs"
name="select-all-in-this-tabs"
class="form-check-input"
[(ngModel)]="selectThisTab"
[disabled]="disableSelectAllTab"
(click)="onClickSelectThisTab()"
/>
<label class="form-check-label" for="select-all-in-this-tabs">{{
'AbpPermissionManagement::SelectAllInThisTab' | abpLocalization
}}</label>
</div>
<hr class="my-2" />
@for (permission of selectedGroupPermissions; track $index; let i = $index) {
<div [ngStyle]="permission.style" class="form-check mb-2">
<input
#permissionCheckbox
type="checkbox"
[checked]="getChecked(permission.name)"
[value]="getChecked(permission.name)"
[attr.id]="permission.name"
class="form-check-input"
[disabled]="isGrantedByOtherProviderName(permission.grantedProviders)"
(click)="onClickCheckbox(permission, permissionCheckbox.value)"
/>
<label class="form-check-label" [attr.for]="permission.name"
>{{ permission.displayName }}
@if (!hideBadges) {
@for (provider of permission.grantedProviders; track $index) {
<span class="badge bg-primary text-dark"
>{{ provider.providerName }}: {{ provider.providerKey }}</span
>
}
@for (group of permissionGroups(); track $index) {
<div ngTabPanel [value]="group.name">
<ng-template ngTabContent>
<div class="ps-1">
@if (selectedGroupPermissions.length) {
<div class="form-check mb-2">
<input
#selectAllInThisTabsRef
type="checkbox"
id="select-all-in-this-tabs"
name="select-all-in-this-tabs"
class="form-check-input"
[(ngModel)]="selectThisTab"
[disabled]="disableSelectAllTab"
(click)="onClickSelectThisTab()"
/>
<label class="form-check-label" for="select-all-in-this-tabs">{{
'AbpPermissionManagement::SelectAllInThisTab' | abpLocalization
}}</label>
</div>
<hr class="my-2" />
@for (permission of selectedGroupPermissions; track $index; let i = $index) {
<div [ngStyle]="permission.style" class="form-check mb-2">
<input
#permissionCheckbox
type="checkbox"
[checked]="getChecked(permission.name)"
[value]="getChecked(permission.name)"
[attr.id]="permission.name"
class="form-check-input"
[disabled]="isGrantedByOtherProviderName(permission.grantedProviders)"
(click)="onClickCheckbox(permission, permissionCheckbox.value)"
/>
<label class="form-check-label" [attr.for]="permission.name"
>{{ permission.displayName }}
@if (!hideBadges) {
@for (provider of permission.grantedProviders; track $index) {
<span class="badge bg-primary text-dark"
>{{ provider.providerName }}: {{ provider.providerKey }}</span
>
}
}
</label>
</div>
}
</label>
}
</div>
}
}
</div>
</ng-template>
</div>
}
</div>
</div>
</fieldset>

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

@ -34,6 +34,8 @@ import { PermissionManagement } from '../models';
import { NgStyle } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Tabs, TabList, Tab, TabPanel, TabContent } from '@angular/aria/tabs';
type PermissionWithStyle = PermissionGrantInfoDto & {
style: string;
};
@ -56,7 +58,7 @@ type PermissionWithGroupName = PermissionGrantInfoDto & {
max-height: calc(100vh - 23.1rem);
}
.lpx-scroll-pills-container ul {
.lpx-scroll-pills-container .nav-pills {
display: block;
overflow-y: auto;
}
@ -66,7 +68,7 @@ type PermissionWithGroupName = PermissionGrantInfoDto & {
.scroll-in-modal {
max-height: calc(100vh - 15rem);
}
.lpx-scroll-pills-container ul {
.lpx-scroll-pills-container .nav-pills {
max-height: 500px;
}
}
@ -81,12 +83,12 @@ type PermissionWithGroupName = PermissionGrantInfoDto & {
padding-bottom: 0 !important;
}
.lpx-scroll-pills-container ul li {
.lpx-scroll-pills-container .nav-item {
margin-bottom: 10px;
border-radius: 10px;
}
.lpx-scroll-pills-container ul li a.active {
.lpx-scroll-pills-container .nav-item .nav-link.active {
color: #fff !important;
border-color: #6c5dd3 !important;
background-color: #6c5dd3 !important;
@ -100,6 +102,11 @@ type PermissionWithGroupName = PermissionGrantInfoDto & {
LocalizationPipe,
ButtonComponent,
ModalCloseDirective,
Tabs,
TabList,
Tab,
TabPanel,
TabContent,
],
})
export class PermissionManagementComponent
@ -418,6 +425,13 @@ export class PermissionManagementComponent
this.onChangeGroup(this.selectedGroup);
}
onTabChange(groupName: string) {
const group = this.permissionGroups().find(g => g.name === groupName);
if (group) {
this.onChangeGroup(group);
}
}
onChangeGroup(group: PermissionGroupDto) {
this.setDisabled(group.permissions);
this.setSelectedGroup(group);

2
npm/ng-packs/packages/setting-management/package.json

@ -12,7 +12,7 @@
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/aria": "21.0.0"
"@angular/aria": "~21.0.0"
},
"publishConfig": {
"access": "public"

Loading…
Cancel
Save