[ACS-8959] Introduce new takeUntilDestroyed operator (#4237)

This commit is contained in:
dominikiwanekhyland
2024-11-21 10:49:49 +01:00
committed by GitHub
parent dec6c41e5c
commit adda597f15
52 changed files with 876 additions and 916 deletions

View File

@@ -22,14 +22,13 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, EventEmitter, inject, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { Subject } from 'rxjs';
import { Component, DestroyRef, EventEmitter, inject, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { ContentActionRef } from '@alfresco/adf-extensions';
import { AppExtensionService, AppSettingsService, ToolbarComponent } from '@alfresco/aca-shared';
import { takeUntil } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { RouterModule } from '@angular/router';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
standalone: true,
@@ -39,11 +38,12 @@ import { RouterModule } from '@angular/router';
encapsulation: ViewEncapsulation.None,
host: { class: 'app-sidenav-header' }
})
export class SidenavHeaderComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
export class SidenavHeaderComponent implements OnInit {
private appSettings = inject(AppSettingsService);
private appExtensions = inject(AppExtensionService);
private readonly destroyRef = inject(DestroyRef);
appName = this.appSettings.appName;
logoUrl = this.appSettings.appLogoUrl;
landingPage = this.appSettings.landingPage;
@@ -55,14 +55,9 @@ export class SidenavHeaderComponent implements OnInit, OnDestroy {
ngOnInit() {
this.appExtensions
.getHeaderActions()
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((actions) => {
this.actions = actions;
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -22,11 +22,23 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/
import { AfterContentInit, ContentChildren, Directive, ElementRef, Input, OnInit, Optional, QueryList, Renderer2 } from '@angular/core';
import {
AfterContentInit,
ContentChildren,
DestroyRef,
Directive,
ElementRef,
inject,
Input,
OnInit,
Optional,
QueryList,
Renderer2
} from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { ActionDirective } from './action.directive';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Directive({
standalone: true,
@@ -39,7 +51,7 @@ export class ActiveLinkDirective implements OnInit, AfterContentInit {
links: QueryList<ActionDirective>;
isLinkActive = false;
private onDestroy$: Subject<boolean> = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
constructor(private router: Router, private element: ElementRef, private renderer: Renderer2, @Optional() private action?: ActionDirective) {}
@@ -47,7 +59,7 @@ export class ActiveLinkDirective implements OnInit, AfterContentInit {
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((event: NavigationEnd) => {
this.update(event.urlAfterRedirects);

View File

@@ -25,6 +25,7 @@
import { NavigationEnd } from '@angular/router';
import { ExpansionPanelDirective } from './expansion-panel.directive';
import { Subject } from 'rxjs';
import { TestBed } from '@angular/core/testing';
class RouterStub {
url;
@@ -64,7 +65,10 @@ describe('AcaExpansionPanel', () => {
const item = {
children: [{ url: 'dummy-route-1' }, { url: 'dummy-route-2' }]
};
const directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
let directive: ExpansionPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
});
directive.acaExpansionPanel = item;
@@ -75,7 +79,10 @@ describe('AcaExpansionPanel', () => {
const item = {
children: [{ url: 'dummy-route-1' }, { url: 'dummy-route-2' }]
};
const directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
let directive: ExpansionPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
});
directive.acaExpansionPanel = item;
@@ -93,7 +100,10 @@ describe('AcaExpansionPanel', () => {
mockMatExpansionPanel.expanded = true;
const directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
let directive: ExpansionPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
});
directive.acaExpansionPanel = item;
@@ -109,7 +119,10 @@ describe('AcaExpansionPanel', () => {
children: [{ url: 'dummy-route-1' }, { url: 'dummy-route-2' }]
};
const directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
let directive: ExpansionPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
});
directive.acaExpansionPanel = item;
mockMatExpansionPanel.expanded = true;
@@ -129,7 +142,10 @@ describe('AcaExpansionPanel', () => {
}
};
const directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
let directive: ExpansionPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel);
});
directive.acaExpansionPanel = item;
mockMatExpansionPanel.expanded = true;

View File

@@ -22,24 +22,22 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/
import { Directive, Input, HostListener, OnInit, OnDestroy } from '@angular/core';
import { Router, NavigationEnd, PRIMARY_OUTLET } from '@angular/router';
import { filter, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { DestroyRef, Directive, HostListener, inject, Input, OnInit } from '@angular/core';
import { NavigationEnd, PRIMARY_OUTLET, Router } from '@angular/router';
import { filter } from 'rxjs/operators';
import { MatExpansionPanel } from '@angular/material/expansion';
import { Store } from '@ngrx/store';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Directive({
standalone: true,
selector: '[acaExpansionPanel]',
exportAs: 'acaExpansionPanel'
})
export class ExpansionPanelDirective implements OnInit, OnDestroy {
export class ExpansionPanelDirective implements OnInit {
@Input() acaExpansionPanel;
public hasActiveChildren = false;
private onDestroy$: Subject<boolean> = new Subject<boolean>();
@HostListener('click')
onClick() {
if (this.expansionPanel.expanded && !this.hasActiveLinks() && !this.acaExpansionPanel.data?.canBeInactive) {
@@ -55,6 +53,8 @@ export class ExpansionPanelDirective implements OnInit, OnDestroy {
}
}
private readonly destroyRef = inject(DestroyRef);
constructor(private store: Store<any>, private router: Router, private expansionPanel: MatExpansionPanel) {}
hasActiveLinks() {
@@ -70,18 +70,13 @@ export class ExpansionPanelDirective implements OnInit, OnDestroy {
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {
this.hasActiveChildren = this.hasActiveLinks();
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
private getNavigationCommands(url: string): any[] {
const urlTree = this.router.parseUrl(url);
const urlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET];

View File

@@ -25,6 +25,7 @@
import { NavigationEnd } from '@angular/router';
import { MenuPanelDirective } from './menu-panel.directive';
import { Subject } from 'rxjs';
import { TestBed } from '@angular/core/testing';
class RouterStub {
url;
@@ -64,7 +65,10 @@ describe('MenuPanelDirective', () => {
const item = {
children: [{ url: 'dummy-route-1' }, { url: 'dummy-route-2' }]
};
const directive = new MenuPanelDirective(mockStore, router);
let directive: MenuPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new MenuPanelDirective(mockStore, router);
});
directive.acaMenuPanel = item;
@@ -75,7 +79,10 @@ describe('MenuPanelDirective', () => {
const item = {
children: [{ url: 'dummy-route-1' }, { url: 'dummy-route-2' }]
};
const directive = new MenuPanelDirective(mockStore, router);
let directive: MenuPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new MenuPanelDirective(mockStore, router);
});
directive.acaMenuPanel = item;
@@ -93,7 +100,10 @@ describe('MenuPanelDirective', () => {
mockMatExpansionPanel.expanded = true;
const directive = new MenuPanelDirective(mockStore, router);
let directive: MenuPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new MenuPanelDirective(mockStore, router);
});
directive.acaMenuPanel = item;
@@ -109,7 +119,10 @@ describe('MenuPanelDirective', () => {
children: [{ url: 'dummy-route-1' }, { url: 'dummy-route-2' }]
};
const directive = new MenuPanelDirective(mockStore, router);
let directive: MenuPanelDirective;
TestBed.runInInjectionContext(() => {
directive = new MenuPanelDirective(mockStore, router);
});
directive.acaMenuPanel = item;
mockMatExpansionPanel.expanded = true;

View File

@@ -22,23 +22,21 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/
import { Directive, Input, OnInit, OnDestroy, HostListener } from '@angular/core';
import { Router, NavigationEnd, PRIMARY_OUTLET } from '@angular/router';
import { filter, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { DestroyRef, Directive, HostListener, inject, Input, OnInit } from '@angular/core';
import { NavigationEnd, PRIMARY_OUTLET, Router } from '@angular/router';
import { filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Directive({
standalone: true,
selector: '[acaMenuPanel]',
exportAs: 'acaMenuPanel'
})
export class MenuPanelDirective implements OnInit, OnDestroy {
export class MenuPanelDirective implements OnInit {
@Input() acaMenuPanel;
hasActiveChildren = false;
private onDestroy$: Subject<boolean> = new Subject<boolean>();
@HostListener('menuOpened')
menuOpened() {
if (this.acaMenuPanel.children && !this.hasActiveLinks()) {
@@ -54,6 +52,8 @@ export class MenuPanelDirective implements OnInit, OnDestroy {
}
}
private readonly destroyRef = inject(DestroyRef);
constructor(private store: Store<any>, private router: Router) {}
hasActiveLinks() {
@@ -69,18 +69,13 @@ export class MenuPanelDirective implements OnInit, OnDestroy {
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {
this.hasActiveChildren = this.hasActiveLinks();
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
private getNavigationCommands(url: string): any[] {
const urlTree = this.router.parseUrl(url);
const urlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET];

View File

@@ -22,12 +22,11 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, Input, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
import { Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { DynamicExtensionComponent, NavBarGroupRef, NavBarLinkRef } from '@alfresco/adf-extensions';
import { Store } from '@ngrx/store';
import { AppStore, getSideNavState } from '@alfresco/aca-shared/store';
import { Subject } from 'rxjs';
import { takeUntil, distinctUntilChanged, debounceTime } from 'rxjs/operators';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { AppExtensionService, AppService, NavigationHistoryService } from '@alfresco/aca-shared';
import { SidenavLayoutComponent } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
@@ -35,6 +34,7 @@ import { SidenavHeaderComponent } from './components/sidenav-header.component';
import { MatListModule } from '@angular/material/list';
import { ExpandMenuComponent } from './components/expand-menu.component';
import { NavigationEnd } from '@angular/router';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
standalone: true,
@@ -45,7 +45,7 @@ import { NavigationEnd } from '@angular/router';
encapsulation: ViewEncapsulation.None,
host: { class: 'app-sidenav' }
})
export class SidenavComponent implements OnInit, OnDestroy {
export class SidenavComponent implements OnInit {
@Input()
data: {
layout?: SidenavLayoutComponent;
@@ -53,7 +53,8 @@ export class SidenavComponent implements OnInit, OnDestroy {
} = {};
groups: Array<NavBarGroupRef> = [];
private onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
constructor(
private store: Store<AppStore>,
@@ -65,17 +66,17 @@ export class SidenavComponent implements OnInit, OnDestroy {
ngOnInit() {
this.store
.select(getSideNavState)
.pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.onDestroy$))
.pipe(debounceTime(300), distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.groups = this.extensions.getApplicationNavigation(this.extensions.navbar);
});
this.appService.setAppNavbarMode(this.data.mode);
this.appService.toggleAppNavBar$.pipe(takeUntil(this.onDestroy$)).subscribe(() => this.toggleNavBar());
this.data.layout.expanded.pipe(takeUntil(this.onDestroy$)).subscribe(() => this.setNavBarMode());
this.appService.toggleAppNavBar$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => this.toggleNavBar());
this.data.layout.expanded.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => this.setNavBarMode());
this.navigationHistoryService
.listenToRouteChanges()
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((event: NavigationEnd) => {
this.navigationHistoryService.setHistory(event, 3);
});
@@ -101,9 +102,4 @@ export class SidenavComponent implements OnInit, OnDestroy {
this.data.layout.toggleMenu();
this.setNavBarMode();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}