Browse Source

docs: remove ngxs from angular docs

pull/10010/head
Mehmet Erim 5 years ago
parent
commit
8e634ea703
  1. 67
      docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md
  2. 276
      docs/en/UI/Angular/Permission-Management-Component-Replacement.md

67
docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md

@ -17,30 +17,18 @@ yarn ng generate component my-roles/my-roles --flat --export
Open the generated `src/app/my-roles/my-roles.component.ts` file and replace its content with the following: Open the generated `src/app/my-roles/my-roles.component.ts` file and replace its content with the following:
```js ```js
import { ListService, PagedAndSortedResultRequestDto } from '@abp/ng.core'; import { ListService, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
import { import { eIdentityComponents, IdentityRoleDto, IdentityRoleService, RolesComponent } from '@abp/ng.identity';
CreateRole,
DeleteRole,
eIdentityComponents,
GetRoleById,
GetRoles,
IdentityRoleDto,
IdentityState,
RolesComponent,
UpdateRole,
} from '@abp/ng.identity';
import { ePermissionManagementComponents } from '@abp/ng.permission-management'; import { ePermissionManagementComponents } from '@abp/ng.permission-management';
import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared'; import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared';
import { import {
EXTENSIONS_IDENTIFIER, EXTENSIONS_IDENTIFIER,
FormPropData, FormPropData,
generateFormFromProps, generateFormFromProps
} from '@abp/ng.theme.shared/extensions'; } from '@abp/ng.theme.shared/extensions';
import { Component, Injector, OnInit } from '@angular/core'; import { Component, Injector, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { Select, Store } from '@ngxs/store'; import { finalize } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { finalize, pluck } from 'rxjs/operators';
@Component({ @Component({
selector: 'app-my-roles', selector: 'app-my-roles',
@ -51,15 +39,14 @@ import { finalize, pluck } from 'rxjs/operators';
provide: EXTENSIONS_IDENTIFIER, provide: EXTENSIONS_IDENTIFIER,
useValue: eIdentityComponents.Roles, useValue: eIdentityComponents.Roles,
}, },
{ provide: RolesComponent, useExisting: MyRolesComponent }, {
provide: RolesComponent,
useExisting: MyRolesComponent
}
], ],
}) })
export class MyRolesComponent implements OnInit { export class MyRolesComponent implements OnInit {
@Select(IdentityState.getRoles) data: PagedResultDto<IdentityRoleDto> = { items: [], totalCount: 0 };
data$: Observable<IdentityRoleDto[]>;
@Select(IdentityState.getRolesTotalCount)
totalCount$: Observable<number>;
form: FormGroup; form: FormGroup;
@ -82,8 +69,8 @@ export class MyRolesComponent implements OnInit {
constructor( constructor(
public readonly list: ListService<PagedAndSortedResultRequestDto>, public readonly list: ListService<PagedAndSortedResultRequestDto>,
protected confirmationService: ConfirmationService, protected confirmationService: ConfirmationService,
protected store: Store, protected injector: Injector,
protected injector: Injector protected service: IdentityRoleService,
) {} ) {}
ngOnInit() { ngOnInit() {
@ -106,25 +93,21 @@ export class MyRolesComponent implements OnInit {
} }
edit(id: string) { edit(id: string) {
this.store this.service.get(id).subscribe(res => {
.dispatch(new GetRoleById(id)) this.selected = res;
.pipe(pluck('IdentityState', 'selectedRole')) this.openModal();
.subscribe(selectedRole => { });
this.selected = selectedRole;
this.openModal();
});
} }
save() { save() {
if (!this.form.valid) return; if (!this.form.valid) return;
this.modalBusy = true; this.modalBusy = true;
this.store const { id } = this.selected;
.dispatch( (id
this.selected.id ? this.service.update(id, { ...this.selected, ...this.form.value })
? new UpdateRole({ ...this.selected, ...this.form.value, id: this.selected.id }) : this.service.create(this.form.value)
: new CreateRole(this.form.value) )
)
.pipe(finalize(() => (this.modalBusy = false))) .pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => { .subscribe(() => {
this.isModalVisible = false; this.isModalVisible = false;
@ -139,13 +122,13 @@ export class MyRolesComponent implements OnInit {
}) })
.subscribe((status: Confirmation.Status) => { .subscribe((status: Confirmation.Status) => {
if (status === Confirmation.Status.confirm) { if (status === Confirmation.Status.confirm) {
this.store.dispatch(new DeleteRole(id)).subscribe(() => this.list.get()); this.service.delete(id).subscribe(() => this.list.get());
} }
}); });
} }
private hookToQuery() { private hookToQuery() {
this.list.hookToQuery(query => this.store.dispatch(new GetRoles(query))).subscribe(); this.list.hookToQuery(query => this.service.getList(query)).subscribe(res => (this.data = res));
} }
openPermissionsModal(providerKey: string) { openPermissionsModal(providerKey: string) {
@ -189,15 +172,15 @@ Open the generated `src/app/my-role/my-role.component.html` file and replace its
<h5 class="card-title">My Roles</h5> <h5 class="card-title">My Roles</h5>
</div> </div>
<div class="text-right col col-md-6"> <div class="text-right col col-md-6">
<abp-page-toolbar [record]="data$ | async"></abp-page-toolbar> <abp-page-toolbar [record]="data.items"></abp-page-toolbar>
</div> </div>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<abp-extensible-table <abp-extensible-table
[data]="data$ | async" [data]="data.items"
[recordsTotal]="totalCount$ | async" [recordsTotal]="data.totalCount"
[list]="list" [list]="list"
></abp-extensible-table> ></abp-extensible-table>
</div> </div>

276
docs/en/UI/Angular/Permission-Management-Component-Replacement.md

@ -5,37 +5,27 @@
Run the following command in `angular` folder to create a new component called `PermissionManagementComponent`. Run the following command in `angular` folder to create a new component called `PermissionManagementComponent`.
```bash ```bash
yarn ng generate component permission-management --entryComponent --inlineStyle yarn ng generate component permission-management --inlineStyle
# You don't need the --entryComponent option in Angular 9
``` ```
Open the generated `permission-management.component.ts` in `src/app/permission-management` folder and replace the content with the following: Open the generated `permission-management.component.ts` in `src/app/permission-management` folder and replace the content with the following:
```js ```js
import { ConfigStateService, CurrentUserDto, ReplaceableComponents } from '@abp/ng.core';
import {
GetPermissionListResultDto,
PermissionGrantInfoDto, PermissionGroupDto, PermissionManagement, PermissionsService, ProviderInfoDto, UpdatePermissionDto
} from '@abp/ng.permission-management';
import { LocaleDirection } from '@abp/ng.theme.shared';
import { import {
Component, Component,
EventEmitter, EventEmitter, Inject, Input, Optional, Output, TrackByFunction
Input,
Output,
Renderer2,
TrackByFunction,
Inject,
Optional,
} from '@angular/core'; } from '@angular/core';
import { ReplaceableComponents } from '@abp/ng.core'; import { of } from 'rxjs';
import { Select, Store } from '@ngxs/store'; import { finalize, switchMap, tap } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { finalize, map, pluck, take, tap } from 'rxjs/operators';
import {
GetPermissions,
UpdatePermissions,
PermissionManagement,
PermissionManagementState,
} from '@abp/ng.permission-management';
type PermissionWithMargin = PermissionManagement.Permission & { type PermissionWithStyle = PermissionGrantInfoDto & {
margin: number; style: string;
}; };
@Component({ @Component({
@ -52,8 +42,8 @@ type PermissionWithMargin = PermissionManagement.Permission & {
}) })
export class PermissionManagementComponent export class PermissionManagementComponent
implements implements
PermissionManagement.PermissionManagementComponentInputs, PermissionManagement.PermissionManagementComponentInputs,
PermissionManagement.PermissionManagementComponentOutputs { PermissionManagement.PermissionManagementComponentOutputs {
protected _providerName: string; protected _providerName: string;
@Input() @Input()
get providerName(): string { get providerName(): string {
@ -115,15 +105,11 @@ export class PermissionManagementComponent
@Output() readonly visibleChange = new EventEmitter<boolean>(); @Output() readonly visibleChange = new EventEmitter<boolean>();
@Select(PermissionManagementState.getPermissionGroups) data: GetPermissionListResultDto = { groups: [], entityDisplayName: null };
groups$: Observable<PermissionManagement.Group[]>;
@Select(PermissionManagementState.getEntityDisplayName) selectedGroup: PermissionGroupDto;
entityName$: Observable<string>;
selectedGroup: PermissionManagement.Group; permissions: PermissionGrantInfoDto[] = [];
permissions: PermissionManagement.Permission[] = [];
selectThisTab = false; selectThisTab = false;
@ -131,25 +117,26 @@ export class PermissionManagementComponent
modalBusy = false; modalBusy = false;
trackByFn: TrackByFunction<PermissionManagement.Group> = (_, item) => item.name; trackByFn: TrackByFunction<PermissionGroupDto> = (_, item) => item.name;
get selectedGroupPermissions$(): Observable<PermissionWithMargin[]> { get selectedGroupPermissions(): PermissionWithStyle[] {
return this.groups$.pipe( if (!this.selectedGroup) return [];
map((groups) =>
this.selectedGroup const margin = `margin-${
? groups.find((group) => group.name === this.selectedGroup.name).permissions (document.body.dir as LocaleDirection) === 'rtl' ? 'right' : 'left'
: [] }.px`;
),
map<PermissionManagement.Permission[], PermissionWithMargin[]>((permissions) => const permissions = this.data.groups.find(
permissions.map( group => group.name === this.selectedGroup.name,
(permission) => ).permissions;
(({
...permission, return permissions.map(
margin: findMargin(permissions, permission), permission =>
isGranted: this.permissions.find((per) => per.name === permission.name).isGranted, ({
} as any) as PermissionWithMargin) ...permission,
) style: { [margin]: findMargin(permissions, permission) },
) isGranted: this.permissions.find(per => per.name === permission.name).isGranted,
} as unknown as PermissionWithStyle),
); );
} }
@ -166,21 +153,22 @@ export class PermissionManagementComponent
PermissionManagement.PermissionManagementComponentInputs, PermissionManagement.PermissionManagementComponentInputs,
PermissionManagement.PermissionManagementComponentOutputs PermissionManagement.PermissionManagementComponentOutputs
>, >,
private store: Store private service: PermissionsService,
private configState: ConfigStateService
) {} ) {}
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;
} }
isGrantedByOtherProviderName(grantedProviders: PermissionManagement.GrantedProvider[]): 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;
} }
onClickCheckbox(clickedPermission: PermissionManagement.Permission, value) { onClickCheckbox(clickedPermission: PermissionGrantInfoDto, value) {
if ( if (
clickedPermission.isGranted && clickedPermission.isGranted &&
this.isGrantedByOtherProviderName(clickedPermission.grantedProviders) this.isGrantedByOtherProviderName(clickedPermission.grantedProviders)
@ -188,7 +176,7 @@ export class PermissionManagementComponent
return; return;
setTimeout(() => { setTimeout(() => {
this.permissions = this.permissions.map((per) => { this.permissions = this.permissions.map(per => {
if (clickedPermission.name === per.name) { if (clickedPermission.name === per.name) {
return { ...per, isGranted: !per.isGranted }; return { ...per, isGranted: !per.isGranted };
} else if (clickedPermission.name === per.parentName && clickedPermission.isGranted) { } else if (clickedPermission.name === per.parentName && clickedPermission.isGranted) {
@ -206,24 +194,22 @@ export class PermissionManagementComponent
} }
setTabCheckboxState() { setTabCheckboxState() {
this.selectedGroupPermissions$.pipe(take(1)).subscribe((permissions) => { const selectedPermissions = this.selectedGroupPermissions.filter(per => per.isGranted);
const selectedPermissions = permissions.filter((per) => per.isGranted); const element = document.querySelector('#select-all-in-this-tabs') as any;
const element = document.querySelector('#select-all-in-this-tabs') as any;
if (selectedPermissions.length === this.selectedGroupPermissions.length) {
if (selectedPermissions.length === permissions.length) { element.indeterminate = false;
element.indeterminate = false; this.selectThisTab = true;
this.selectThisTab = true; } else if (selectedPermissions.length === 0) {
} else if (selectedPermissions.length === 0) { element.indeterminate = false;
element.indeterminate = false; this.selectThisTab = false;
this.selectThisTab = false; } else {
} else { element.indeterminate = true;
element.indeterminate = true; }
}
});
} }
setGrantCheckboxState() { setGrantCheckboxState() {
const selectedAllPermissions = this.permissions.filter((per) => per.isGranted); const selectedAllPermissions = this.permissions.filter(per => per.isGranted);
const checkboxElement = document.querySelector('#select-all-in-all-tabs') as any; const checkboxElement = document.querySelector('#select-all-in-all-tabs') as any;
if (selectedAllPermissions.length === this.permissions.length) { if (selectedAllPermissions.length === this.permissions.length) {
@ -238,26 +224,24 @@ export class PermissionManagementComponent
} }
onClickSelectThisTab() { onClickSelectThisTab() {
this.selectedGroupPermissions$.pipe(take(1)).subscribe((permissions) => { this.selectedGroupPermissions.forEach(permission => {
permissions.forEach((permission) => { if (permission.isGranted && this.isGrantedByOtherProviderName(permission.grantedProviders))
if (permission.isGranted && this.isGrantedByOtherProviderName(permission.grantedProviders)) return;
return;
const index = this.permissions.findIndex(per => per.name === permission.name);
const index = this.permissions.findIndex((per) => per.name === permission.name);
this.permissions = [
this.permissions = [ ...this.permissions.slice(0, index),
...this.permissions.slice(0, index), { ...this.permissions[index], isGranted: !this.selectThisTab },
{ ...this.permissions[index], isGranted: !this.selectThisTab }, ...this.permissions.slice(index + 1),
...this.permissions.slice(index + 1), ];
];
});
}); });
this.setGrantCheckboxState(); this.setGrantCheckboxState();
} }
onClickSelectAll() { onClickSelectAll() {
this.permissions = this.permissions.map((permission) => ({ this.permissions = this.permissions.map(permission => ({
...permission, ...permission,
isGranted: isGranted:
this.isGrantedByOtherProviderName(permission.grantedProviders) || !this.selectAllTab, this.isGrantedByOtherProviderName(permission.grantedProviders) || !this.selectAllTab,
@ -266,43 +250,41 @@ export class PermissionManagementComponent
this.selectThisTab = !this.selectAllTab; this.selectThisTab = !this.selectAllTab;
} }
onChangeGroup(group: PermissionManagement.Group) { onChangeGroup(group: PermissionGroupDto) {
this.selectedGroup = group; this.selectedGroup = group;
this.setTabCheckboxState(); this.setTabCheckboxState();
} }
submit() { submit() {
this.modalBusy = true; const unchangedPermissions = getPermissions(this.data.groups);
const unchangedPermissions = getPermissions(
this.store.selectSnapshot(PermissionManagementState.getPermissionGroups)
);
const changedPermissions: PermissionManagement.MinimumPermission[] = this.permissions const changedPermissions: UpdatePermissionDto[] = this.permissions
.filter((per) => .filter(per =>
unchangedPermissions.find((unchanged) => unchanged.name === per.name).isGranted === unchangedPermissions.find(unchanged => unchanged.name === per.name).isGranted ===
per.isGranted per.isGranted
? false ? false
: true : true,
) )
.map(({ name, isGranted }) => ({ name, isGranted })); .map(({ name, isGranted }) => ({ name, isGranted }));
if (changedPermissions.length) { if (!changedPermissions.length) {
this.store
.dispatch(
new UpdatePermissions({
providerKey: this.providerKey,
providerName: this.providerName,
permissions: changedPermissions,
})
)
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => {
this.visible = false;
});
} else {
this.modalBusy = false;
this.visible = false; this.visible = false;
return;
} }
this.modalBusy = true;
this.service
.update(this.providerName, this.providerKey, { permissions: changedPermissions })
.pipe(
switchMap(() =>
this.shouldFetchAppConfig() ? this.configState.refreshAppState() : of(null),
),
finalize(() => (this.modalBusy = false)),
)
.subscribe(() => {
this.visible = false;
});
} }
openModal() { openModal() {
@ -310,20 +292,13 @@ export class PermissionManagementComponent
throw new Error('Provider Key and Provider Name are required.'); throw new Error('Provider Key and Provider Name are required.');
} }
return this.store return this.service.get(this.providerName, this.providerKey).pipe(
.dispatch( tap((permissionRes: GetPermissionListResultDto) => {
new GetPermissions({ this.data = permissionRes;
providerKey: this.providerKey, this.selectedGroup = permissionRes.groups[0];
providerName: this.providerName, this.permissions = getPermissions(permissionRes.groups);
}) }),
) );
.pipe(
pluck('PermissionManagementState', 'permissionRes'),
tap((permissionRes: PermissionManagement.Response) => {
this.selectedGroup = permissionRes.groups[0];
this.permissions = getPermissions(permissionRes.groups);
})
);
} }
initModal() { initModal() {
@ -331,6 +306,13 @@ export class PermissionManagementComponent
this.setGrantCheckboxState(); this.setGrantCheckboxState();
} }
getAssignedCount(groupName: string) {
return this.permissions.reduce(
(acc, val) => (val.name.split('.')[0] === groupName && val.isGranted ? acc + 1 : acc),
0,
);
}
onVisibleChange(visible: boolean) { onVisibleChange(visible: boolean) {
this.visible = visible; this.visible = visible;
@ -339,13 +321,20 @@ export class PermissionManagementComponent
this.replaceableData.outputs.visibleChange(visible); this.replaceableData.outputs.visibleChange(visible);
} }
} }
shouldFetchAppConfig() {
const currentUser = this.configState.getOne('currentUser') as CurrentUserDto;
if (this.providerName === 'R') return currentUser.roles.some(role => role === this.providerKey);
if (this.providerName === 'U') return currentUser.id === this.providerKey;
return false;
}
} }
function findMargin( function findMargin(permissions: PermissionGrantInfoDto[], permission: PermissionGrantInfoDto) {
permissions: PermissionManagement.Permission[], const parentPermission = permissions.find(per => per.name === permission.parentName);
permission: PermissionManagement.Permission
) {
const parentPermission = permissions.find((per) => per.name === permission.parentName);
if (parentPermission && parentPermission.parentName) { if (parentPermission && parentPermission.parentName) {
let margin = 20; let margin = 20;
@ -355,7 +344,7 @@ function findMargin(
return parentPermission ? 20 : 0; return parentPermission ? 20 : 0;
} }
function getPermissions(groups: PermissionManagement.Group[]): PermissionManagement.Permission[] { function getPermissions(groups: PermissionGroupDto[]): PermissionGrantInfoDto[] {
return groups.reduce((acc, val) => [...acc, ...val.permissions], []); return groups.reduce((acc, val) => [...acc, ...val.permissions], []);
} }
``` ```
@ -363,16 +352,12 @@ function getPermissions(groups: PermissionManagement.Group[]): PermissionManagem
Open the generated `permission-management.component.html` in `src/app/permission-management` folder and replace the content with the below: Open the generated `permission-management.component.html` in `src/app/permission-management` folder and replace the content with the below:
```html ```html
<abp-modal <abp-modal [visible]="isVisible" (visibleChange)="onVisibleChange($event)" [busy]="modalBusy">
[visible]="isVisible" <ng-container *ngIf="data.entityDisplayName">
(visibleChange)="onVisibleChange($event)"
(init)="initModal()"
[busy]="modalBusy"
>
<ng-container *ngIf="{ entityName: entityName$ | async } as data">
<ng-template #abpHeader> <ng-template #abpHeader>
<h4> <h4>
{%{{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}}%} - {%{{{ data.entityName }}}%} {%{{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}}%} -
{%{{{ data.entityDisplayName }}}%}
</h4> </h4>
</ng-template> </ng-template>
<ng-template #abpBody> <ng-template #abpBody>
@ -394,13 +379,18 @@ Open the generated `permission-management.component.html` in `src/app/permission
<div class="row"> <div class="row">
<div class="overflow-scroll col-md-4"> <div class="overflow-scroll col-md-4">
<ul class="nav nav-pills flex-column"> <ul class="nav nav-pills flex-column">
<li *ngFor="let group of groups$ | async; trackBy: trackByFn" class="nav-item"> <li *ngFor="let group of data.groups; trackBy: trackByFn" class="nav-item">
<a <a
*ngIf="{ assignedCount: getAssignedCount(group.name) } as count"
class="nav-link pointer" class="nav-link pointer"
[class.active]="selectedGroup?.name === group?.name" [class.active]="selectedGroup?.name === group?.name"
(click)="onChangeGroup(group)" (click)="onChangeGroup(group)"
>{%{{{ group?.displayName }}}%}</a
> >
<div [class.font-weight-bold]="count.assignedCount">
{%{{{ group?.displayName }}}%}
<span>({%{{{ count.assignedCount }}}%})</span>
</div>
</a>
</li> </li>
</ul> </ul>
</div> </div>
@ -423,12 +413,8 @@ Open the generated `permission-management.component.html` in `src/app/permission
</div> </div>
<hr class="mb-3" /> <hr class="mb-3" />
<div <div
*ngFor=" *ngFor="let permission of selectedGroupPermissions; let i = index; trackBy: trackByFn"
let permission of selectedGroupPermissions$ | async; [ngStyle]="permission.style"
let i = index;
trackBy: trackByFn
"
[style.margin-left]="permission.margin + 'px'"
class="custom-checkbox custom-control mb-2" class="custom-checkbox custom-control mb-2"
> >
<input <input

Loading…
Cancel
Save