RED-5873: fix null injector for listing component

This commit is contained in:
Dan Percic 2022-12-22 16:28:12 +02:00
parent d7783cbf02
commit 755404c3a8
8 changed files with 36 additions and 33 deletions

View File

@ -1,6 +1,6 @@
<iqser-page-header <iqser-page-header
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()" (closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
[pageLabel]="'permissions-screen.label' | translate: { targetObject: this.targetObject }" [pageLabel]="'permissions-screen.label' | translate : { targetObject }"
[showCloseButton]="currentUser.isUser && permissionsService.has$(roles.dossiers.read) | async" [showCloseButton]="currentUser.isUser && permissionsService.has$(roles.dossiers.read) | async"
></iqser-page-header> ></iqser-page-header>

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core';
import { import {
getCurrentUser, getCurrentUser,
IqserPermissionsService, IqserPermissionsService,
@ -15,21 +15,19 @@ import { EntityPermissionsService } from '@services/entity-permissions/entity-pe
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { PermissionsMapService } from '@services/entity-permissions/permissions-map.service'; import { PermissionsMapService } from '@services/entity-permissions/permissions-map.service';
import { PermissionsConfigurationMapService } from '@services/entity-permissions/permissions-configuration-map.service'; import { PermissionsConfigurationMapService } from '@services/entity-permissions/permissions-configuration-map.service';
import { firstValueFrom } from 'rxjs'; import { Subscription } from 'rxjs';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import { permissionsTranslations } from '@translations/permissions-translations'; import { permissionsTranslations } from '@translations/permissions-translations';
import { RouterHistoryService } from '@services/router-history.service'; import { RouterHistoryService } from '@services/router-history.service';
import { ROLES } from '@users/roles'; import { ROLES } from '@users/roles';
@UntilDestroy()
@Component({ @Component({
templateUrl: './permissions-screen.component.html', templateUrl: './permissions-screen.component.html',
styleUrls: ['./permissions-screen.component.scss'], styleUrls: ['./permissions-screen.component.scss'],
providers: listingProvidersFactory(PermissionsScreenComponent), providers: listingProvidersFactory(PermissionsScreenComponent),
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class PermissionsScreenComponent extends ListingComponent<PermissionsMapping> { export class PermissionsScreenComponent extends ListingComponent<PermissionsMapping> implements OnDestroy {
readonly roles = ROLES; readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>(); readonly currentUser = getCurrentUser<User>();
readonly translations = permissionsTranslations; readonly translations = permissionsTranslations;
@ -37,6 +35,7 @@ export class PermissionsScreenComponent extends ListingComponent<PermissionsMapp
readonly tableHeaderLabel = _('permissions-screen.table-header.title'); readonly tableHeaderLabel = _('permissions-screen.table-header.title');
readonly targetObject: string; readonly targetObject: string;
readonly mappedPermissions: string[]; readonly mappedPermissions: string[];
readonly #subscription: Subscription;
constructor( constructor(
route: ActivatedRoute, route: ActivatedRoute,
@ -52,21 +51,23 @@ export class PermissionsScreenComponent extends ListingComponent<PermissionsMapp
this.targetObject = route.snapshot.data.permissionsObject; this.targetObject = route.snapshot.data.permissionsObject;
this.tableColumnConfigs = configService.tableConfig(this.targetObject); this.tableColumnConfigs = configService.tableConfig(this.targetObject);
this.mappedPermissions = permissionsConfigurationMapService.getMappedPermissions(this.targetObject); this.mappedPermissions = permissionsConfigurationMapService.getMappedPermissions(this.targetObject);
this.entitiesService.setEntities(this._permissionsMapService.get(this.targetObject));
this.sortingService.setSortingOption({ this.sortingService.setSortingOption({
column: 'sort', column: 'sort',
order: SortingOrders.asc, order: SortingOrders.asc,
}); });
this._permissionsMapService this.#subscription = this._permissionsMapService
.get$(this.targetObject) .get$(this.targetObject)
.pipe(tap(permissions => this.entitiesService.setEntities(permissions))) .pipe(tap(permissions => this.entitiesService.setEntities(permissions)))
.pipe(untilDestroyed(this))
.subscribe(); .subscribe();
} }
async togglePermission(targetPermission: string, changedPermission: string): Promise<void> { async togglePermission(targetPermission: string, changedPermission: string): Promise<void> {
this._loadingService.start(); this._loadingService.start();
await firstValueFrom(this._entityPermissionsService.togglePermission(this.targetObject, targetPermission, changedPermission)); await this._entityPermissionsService.togglePermission(this.targetObject, targetPermission, changedPermission);
this._loadingService.stop(); this._loadingService.stop();
} }
ngOnDestroy(): void {
this.#subscription.unsubscribe();
}
} }

View File

@ -1,17 +1,24 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { SharedModule } from '@shared/shared.module';
import { PermissionsScreenComponent } from './permissions-screen/permissions-screen.component'; import { PermissionsScreenComponent } from './permissions-screen/permissions-screen.component';
import { ConfigService } from './config.service'; import { ConfigService } from './config.service';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { IqserHelpModeModule, IqserListingModule } from '@iqser/common-ui'; import { IqserHelpModeModule, IqserListingModule } from '@iqser/common-ui';
import { MatLegacySlideToggleModule } from '@angular/material/legacy-slide-toggle';
const routes = [{ path: '', component: PermissionsScreenComponent }]; const routes = [{ path: '', component: PermissionsScreenComponent }];
@NgModule({ @NgModule({
declarations: [PermissionsScreenComponent], declarations: [PermissionsScreenComponent],
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, TranslateModule, IqserListingModule, IqserHelpModeModule], imports: [
RouterModule.forChild(routes),
CommonModule,
TranslateModule,
IqserListingModule,
IqserHelpModeModule,
MatLegacySlideToggleModule,
],
providers: [ConfigService], providers: [ConfigService],
}) })
export class PermissionsModule {} export class PermissionsModule {}

View File

@ -1,23 +1,22 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostBinding, Input, OnChanges } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostBinding, Input, OnChanges, OnDestroy } from '@angular/core';
import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { BehaviorSubject, filter } from 'rxjs'; import { BehaviorSubject, filter, Subscription } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators'; import { switchMap, tap } from 'rxjs/operators';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { AnnotationsListingService } from '../../services/annotations-listing.service'; import { AnnotationsListingService } from '../../services/annotations-listing.service';
@UntilDestroy()
@Component({ @Component({
selector: 'redaction-annotation-reference [annotation]', selector: 'redaction-annotation-reference [annotation]',
templateUrl: './annotation-reference.component.html', templateUrl: './annotation-reference.component.html',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class AnnotationReferenceComponent implements OnChanges { export class AnnotationReferenceComponent implements OnChanges, OnDestroy {
@Input() annotation: AnnotationWrapper; @Input() annotation: AnnotationWrapper;
@HostBinding('class.active') isSelected = false; @HostBinding('class.active') isSelected = false;
private readonly _annotationChanged$ = new BehaviorSubject<AnnotationWrapper>(undefined); readonly #annotationChanged$ = new BehaviorSubject<AnnotationWrapper>(undefined);
readonly #subscription: Subscription;
constructor(private readonly _listingService: AnnotationsListingService, private readonly _changeRef: ChangeDetectorRef) { constructor(private readonly _listingService: AnnotationsListingService, private readonly _changeRef: ChangeDetectorRef) {
this._annotationChanged$ this.#subscription = this.#annotationChanged$
.pipe( .pipe(
filter(annotation => !!annotation), filter(annotation => !!annotation),
switchMap(annotation => this._listingService.isSelected$(annotation)), switchMap(annotation => this._listingService.isSelected$(annotation)),
@ -26,11 +25,14 @@ export class AnnotationReferenceComponent implements OnChanges {
this._changeRef.markForCheck(); this._changeRef.markForCheck();
}), }),
) )
.pipe(untilDestroyed(this))
.subscribe(); .subscribe();
} }
ngOnChanges(): void { ngOnChanges(): void {
this._annotationChanged$.next(this.annotation); this.#annotationChanged$.next(this.annotation);
}
ngOnDestroy(): void {
this.#subscription.unsubscribe();
} }
} }

View File

@ -1,7 +1,7 @@
import { inject, Injectable } from '@angular/core'; import { inject, Injectable } from '@angular/core';
import { GenericService, mapEach } from '@iqser/common-ui'; import { GenericService, mapEach } from '@iqser/common-ui';
import { IPermissionsMapping, PermissionsMapping } from '@red/domain'; import { IPermissionsMapping, PermissionsMapping } from '@red/domain';
import { Observable } from 'rxjs'; import { firstValueFrom, Observable } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators'; import { switchMap, tap } from 'rxjs/operators';
import { PermissionsConfigurationMapService } from './permissions-configuration-map.service'; import { PermissionsConfigurationMapService } from './permissions-configuration-map.service';
import { PermissionsMapService } from './permissions-map.service'; import { PermissionsMapService } from './permissions-map.service';
@ -32,7 +32,7 @@ export class EntityPermissionsService extends GenericService<IPermissionsMapping
); );
} }
togglePermission(targetObject: string, targetPermission: string, changedPermission: string): Observable<PermissionsMapping[]> { async togglePermission(targetObject: string, targetPermission: string, changedPermission: string): Promise<PermissionsMapping[]> {
const config = this.#permissionsConfigurationMapService.get(targetObject); const config = this.#permissionsConfigurationMapService.get(targetObject);
const targetPermissionConfig = config.find(p => p.searchKey === targetPermission); const targetPermissionConfig = config.find(p => p.searchKey === targetPermission);
const permissions = this.#permissionsMapService.get(targetObject); const permissions = this.#permissionsMapService.get(targetObject);
@ -44,7 +44,8 @@ export class EntityPermissionsService extends GenericService<IPermissionsMapping
const permission = targetPermissionConfig.mappedPermissions.find(p => p.name === changedPermission); const permission = targetPermissionConfig.mappedPermissions.find(p => p.name === changedPermission);
currentTargetPermissionValues.mappedPermissions.push(permission); currentTargetPermissionValues.mappedPermissions.push(permission);
} }
return this._post(permissions, `${this._defaultModelPath}/${targetObject}`).pipe(switchMap(() => this.loadFor(targetObject))); const request = this._post(permissions, `${this._defaultModelPath}/${targetObject}`);
return firstValueFrom(request.pipe(switchMap(() => this.loadFor(targetObject))));
} }
#addMissingPermissions(mappings: PermissionsMapping[], targetObject: string): void { #addMissingPermissions(mappings: PermissionsMapping[], targetObject: string): void {

@ -1 +1 @@
Subproject commit bf325c2c09da901aebafa7794997a3d3cfb8765d Subproject commit 36c74bd8a2a04bcfdf487668910eac386ae2e4eb

View File

@ -36,7 +36,6 @@
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0", "@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
"@materia-ui/ngx-monaco-editor": "^6.0.0", "@materia-ui/ngx-monaco-editor": "^6.0.0",
"@messageformat/core": "^3.0.1", "@messageformat/core": "^3.0.1",
"@ngneat/until-destroy": "^9.2.0",
"@ngx-translate/core": "^14.0.0", "@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^7.0.0", "@ngx-translate/http-loader": "^7.0.0",
"@nrwl/angular": "15.3.3", "@nrwl/angular": "15.3.3",

View File

@ -2722,13 +2722,6 @@
dependencies: dependencies:
make-plural "^7.0.0" make-plural "^7.0.0"
"@ngneat/until-destroy@^9.2.0":
version "9.2.2"
resolved "https://registry.yarnpkg.com/@ngneat/until-destroy/-/until-destroy-9.2.2.tgz#ac6f954610fc7ea5d4a094ed4de9db59513b810f"
integrity sha512-pD5idTgUdF0XZMuaV1n0BZTnE2BvxymutoXhwfZbO3uxjh63wS6Pzzzwv+pkXalKhuSwdf6uA1gRx7DOvlj/Kw==
dependencies:
tslib "^2.3.0"
"@ngtools/webpack@15.0.4": "@ngtools/webpack@15.0.4":
version "15.0.4" version "15.0.4"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-15.0.4.tgz#c1fe2feeab9f7933ef3e76682b26e11d8cd02423" resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-15.0.4.tgz#c1fe2feeab9f7933ef3e76682b26e11d8cd02423"