mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-4745] memory leak fixes (#4931)
* fix app-layout component * fix card-view component * fix cloud-layout service * code fixes * code fixes * even more fixes * even more fixes * lint fixes * test fixes * fix code * remove useless pipes * fix code owners * enable spellcheck for cloud components * update test * update test
This commit is contained in:
committed by
Eugenio Romano
parent
e2311ab045
commit
1abb9bfc89
@@ -58,7 +58,7 @@ describe('Breadcrumb', () => {
|
||||
it('should root be present as default node if the path is null', () => {
|
||||
component.root = 'default';
|
||||
component.folderNode = fakeNodeWithCreatePermission;
|
||||
component.ngOnChanges(null);
|
||||
component.ngOnChanges();
|
||||
|
||||
expect(component.route[0].name).toBe('default');
|
||||
});
|
||||
@@ -215,7 +215,7 @@ describe('Breadcrumb', () => {
|
||||
return transformNode;
|
||||
});
|
||||
component.folderNode = node;
|
||||
component.ngOnChanges(null);
|
||||
component.ngOnChanges();
|
||||
expect(component.route.length).toBe(4);
|
||||
expect(component.route[3].id).toBe('test-id');
|
||||
expect(component.route[3].name).toBe('test-name');
|
||||
|
@@ -22,13 +22,15 @@ import {
|
||||
OnChanges,
|
||||
OnInit,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
ViewChild,
|
||||
ViewEncapsulation
|
||||
ViewEncapsulation,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
import { MatSelect } from '@angular/material';
|
||||
import { Node, PathElementEntity } from '@alfresco/js-api';
|
||||
import { DocumentListComponent } from '../document-list';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-breadcrumb',
|
||||
@@ -39,7 +41,7 @@ import { DocumentListComponent } from '../document-list';
|
||||
'class': 'adf-breadcrumb'
|
||||
}
|
||||
})
|
||||
export class BreadcrumbComponent implements OnInit, OnChanges {
|
||||
export class BreadcrumbComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
/** Active node, builds UI based on folderNode.path.elements collection. */
|
||||
@Input()
|
||||
@@ -84,6 +86,8 @@ export class BreadcrumbComponent implements OnInit, OnChanges {
|
||||
|
||||
route: PathElementEntity[] = [];
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
get hasRoot(): boolean {
|
||||
return !!this.root;
|
||||
}
|
||||
@@ -96,14 +100,16 @@ export class BreadcrumbComponent implements OnInit, OnChanges {
|
||||
this.transform = this.transform ? this.transform : null;
|
||||
|
||||
if (this.target) {
|
||||
this.target.$folderNode.subscribe((folderNode: Node) => {
|
||||
this.folderNode = folderNode;
|
||||
this.recalculateNodes();
|
||||
});
|
||||
this.target.$folderNode
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((folderNode: Node) => {
|
||||
this.folderNode = folderNode;
|
||||
this.recalculateNodes();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
ngOnChanges(): void {
|
||||
this.recalculateNodes();
|
||||
}
|
||||
|
||||
@@ -184,4 +190,9 @@ export class BreadcrumbComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ describe('DropdownBreadcrumb', () => {
|
||||
|
||||
function triggerComponentChange(fakeNodeData) {
|
||||
component.folderNode = fakeNodeData;
|
||||
component.ngOnChanges(null);
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import {
|
||||
HighlightDirective,
|
||||
UserPreferencesService,
|
||||
@@ -29,9 +29,10 @@ import { DocumentListComponent } from '../document-list/components/document-list
|
||||
import { RowFilter } from '../document-list/data/row-filter.model';
|
||||
import { ImageResolver } from '../document-list/data/image-resolver.model';
|
||||
import { ContentNodeSelectorService } from './content-node-selector.service';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
import { CustomResourcesService } from '../document-list/services/custom-resources.service';
|
||||
import { ShareDataRow } from '../document-list';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
export type ValidationFunction = (entry: Node) => boolean;
|
||||
|
||||
@@ -44,7 +45,7 @@ const defaultValidation = () => true;
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: { 'class': 'adf-content-node-selector-panel' }
|
||||
})
|
||||
export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
|
||||
DEFAULT_PAGINATION: Pagination = new Pagination({
|
||||
maxItems: 25,
|
||||
@@ -166,21 +167,11 @@ export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
|
||||
target: PaginatedComponent;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private contentNodeSelectorService: ContentNodeSelectorService,
|
||||
private customResourcesService: CustomResourcesService,
|
||||
private userPreferencesService: UserPreferencesService) {
|
||||
this.searchInput.valueChanges
|
||||
.pipe(
|
||||
debounceTime(this.debounceSearch)
|
||||
)
|
||||
.subscribe((searchValue) => {
|
||||
this.search(searchValue);
|
||||
});
|
||||
|
||||
this.userPreferencesService.select(UserPreferenceValues.PaginationSize).subscribe((pagSize) => {
|
||||
this.pageSize = pagSize;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
set chosenNode(value: Node) {
|
||||
@@ -197,6 +188,18 @@ export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.searchInput.valueChanges
|
||||
.pipe(
|
||||
debounceTime(this.debounceSearch),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe(searchValue => this.search(searchValue));
|
||||
|
||||
this.userPreferencesService
|
||||
.select(UserPreferenceValues.PaginationSize)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(pagSize => this.pageSize = pagSize);
|
||||
|
||||
this.target = this.documentList;
|
||||
this.folderIdToShow = this.currentFolderId;
|
||||
|
||||
@@ -204,6 +207,11 @@ export class ContentNodeSelectorPanelComponent implements OnInit {
|
||||
this.isSelectionValid = this.isSelectionValid ? this.isSelectionValid : defaultValidation;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
private createRowFilter(filter?: RowFilter) {
|
||||
if (!filter) {
|
||||
filter = () => true;
|
||||
|
@@ -25,12 +25,13 @@ import {
|
||||
} from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef, MatDialog, MatSlideToggleChange } from '@angular/material';
|
||||
import { FormGroup, FormControl } from '@angular/forms';
|
||||
import { Subscription, Observable, throwError } from 'rxjs';
|
||||
import { Observable, throwError, Subject } from 'rxjs';
|
||||
import {
|
||||
skip,
|
||||
distinctUntilChanged,
|
||||
mergeMap,
|
||||
catchError
|
||||
catchError,
|
||||
takeUntil
|
||||
} from 'rxjs/operators';
|
||||
import {
|
||||
SharedLinksApiService,
|
||||
@@ -52,7 +53,6 @@ import { ContentNodeShareSettings } from './content-node-share.settings';
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ShareDialogComponent implements OnInit, OnDestroy {
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
||||
minDate = moment().add(1, 'd');
|
||||
sharedId: string;
|
||||
@@ -75,6 +75,8 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('dateTimePickerInput')
|
||||
dateTimePickerInput;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(
|
||||
private appConfigService: AppConfigService,
|
||||
private sharedLinksApiService: SharedLinksApiService,
|
||||
@@ -93,21 +95,20 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
|
||||
this.form.controls['time'].disable();
|
||||
}
|
||||
|
||||
this.subscriptions.push(
|
||||
this.form.controls.time.valueChanges
|
||||
.pipe(
|
||||
skip(1),
|
||||
distinctUntilChanged(),
|
||||
mergeMap(
|
||||
(updates) => this.updateNode(updates),
|
||||
(formUpdates) => formUpdates
|
||||
),
|
||||
catchError((error) => {
|
||||
return throwError(error);
|
||||
})
|
||||
)
|
||||
.subscribe((updates) => this.updateEntryExpiryDate(updates))
|
||||
);
|
||||
this.form.controls.time.valueChanges
|
||||
.pipe(
|
||||
skip(1),
|
||||
distinctUntilChanged(),
|
||||
mergeMap(
|
||||
(updates) => this.updateNode(updates),
|
||||
(formUpdates) => formUpdates
|
||||
),
|
||||
catchError((error) => {
|
||||
return throwError(error);
|
||||
}),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe(updates => this.updateEntryExpiryDate(updates));
|
||||
|
||||
if (this.data.node && this.data.node.entry) {
|
||||
this.fileName = this.data.node.entry.name;
|
||||
@@ -126,7 +127,8 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach((subscription) => subscription.unsubscribe);
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
removeShare() {
|
||||
|
@@ -15,19 +15,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Directive, Input, HostListener, OnChanges, NgZone } from '@angular/core';
|
||||
import { Directive, Input, HostListener, OnChanges, NgZone, OnDestroy } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material';
|
||||
import { NodeEntry, Node } from '@alfresco/js-api';
|
||||
|
||||
import { ShareDialogComponent } from './content-node-share.dialog';
|
||||
import { Observable, from } from 'rxjs';
|
||||
import { Observable, from, Subject } from 'rxjs';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Directive({
|
||||
selector: '[adf-share]',
|
||||
exportAs: 'adfShare'
|
||||
})
|
||||
export class NodeSharedDirective implements OnChanges {
|
||||
export class NodeSharedDirective implements OnChanges, OnDestroy {
|
||||
|
||||
isFile: boolean = false;
|
||||
isShared: boolean = false;
|
||||
@@ -41,12 +42,7 @@ export class NodeSharedDirective implements OnChanges {
|
||||
@Input()
|
||||
baseShareUrl: string;
|
||||
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
if (this.node) {
|
||||
this.shareNode(this.node);
|
||||
}
|
||||
}
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(
|
||||
private dialog: MatDialog,
|
||||
@@ -54,6 +50,11 @@ export class NodeSharedDirective implements OnChanges {
|
||||
private alfrescoApiService: AlfrescoApiService) {
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
shareNode(nodeEntry: NodeEntry) {
|
||||
if (nodeEntry && nodeEntry.entry && nodeEntry.entry.isFile) {
|
||||
// shared and favorite
|
||||
@@ -89,11 +90,20 @@ export class NodeSharedDirective implements OnChanges {
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.zone.onStable.subscribe(() => {
|
||||
if (this.node && this.node.entry) {
|
||||
this.isFile = this.node.entry.isFile;
|
||||
this.isShared = this.node.entry.properties ? this.node.entry.properties['qshare:sharedId'] : false;
|
||||
}
|
||||
});
|
||||
this.zone.onStable
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => {
|
||||
if (this.node && this.node.entry) {
|
||||
this.isFile = this.node.entry.isFile;
|
||||
this.isShared = this.node.entry.properties ? this.node.entry.properties['qshare:sharedId'] : false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
if (this.node) {
|
||||
this.shareNode(this.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ import {
|
||||
} from '@alfresco/adf-core';
|
||||
|
||||
import { Node, NodeEntry, NodePaging, Pagination } from '@alfresco/js-api';
|
||||
import { Subject, BehaviorSubject, Subscription, of } from 'rxjs';
|
||||
import { Subject, BehaviorSubject, of } from 'rxjs';
|
||||
import { ShareDataRow } from './../data/share-data-row.model';
|
||||
import { ShareDataTableAdapter } from './../data/share-datatable-adapter';
|
||||
import { presetsDefaultModel } from '../models/preset.model';
|
||||
@@ -58,6 +58,7 @@ import { NavigableComponentInterface } from '../../breadcrumb/navigable-componen
|
||||
import { RowFilter } from '../data/row-filter.model';
|
||||
import { DocumentListService } from '../services/document-list.service';
|
||||
import { DocumentLoaderNode } from '../models/document-folder.model';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-document-list',
|
||||
@@ -314,9 +315,9 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
pagination: BehaviorSubject<PaginationModel> = new BehaviorSubject<PaginationModel>(this.DEFAULT_PAGINATION);
|
||||
|
||||
private layoutPresets = {};
|
||||
private subscriptions: Subscription[] = [];
|
||||
private rowMenuCache: { [key: string]: ContentActionModel[] } = {};
|
||||
private loadingTimeout;
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private documentListService: DocumentListService,
|
||||
private ngZone: NgZone,
|
||||
@@ -327,10 +328,6 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
private thumbnailService: ThumbnailService,
|
||||
private alfrescoApiService: AlfrescoApiService,
|
||||
private lockService: LockService) {
|
||||
|
||||
this.userPreferencesService.select(UserPreferenceValues.PaginationSize).subscribe((pagSize) => {
|
||||
this.maxItems = this._pagination.maxItems = pagSize;
|
||||
});
|
||||
}
|
||||
|
||||
getContextActions(node: NodeEntry) {
|
||||
@@ -375,6 +372,13 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.userPreferencesService
|
||||
.select(UserPreferenceValues.PaginationSize)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(pagSize => {
|
||||
this.maxItems = this._pagination.maxItems = pagSize;
|
||||
});
|
||||
|
||||
this.rowMenuCache = {};
|
||||
this.loadLayoutPresets();
|
||||
this.data = new ShareDataTableAdapter(this.thumbnailService, this.contentService, null, this.getDefaultSorting(), this.sortingMode);
|
||||
@@ -389,20 +393,18 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
this.data.setImageResolver(this.imageResolver);
|
||||
}
|
||||
|
||||
this.subscriptions.push(
|
||||
this.contextActionHandler.subscribe((val) => this.contextActionCallback(val))
|
||||
);
|
||||
this.contextActionHandler
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(val => this.contextActionCallback(val));
|
||||
|
||||
this.enforceSingleClickNavigationForMobile();
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
if (this.columnList) {
|
||||
this.subscriptions.push(
|
||||
this.columnList.columns.changes.subscribe(() => {
|
||||
this.setTableSchema();
|
||||
})
|
||||
);
|
||||
this.columnList.columns.changes
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => this.setTableSchema());
|
||||
}
|
||||
this.setTableSchema();
|
||||
}
|
||||
@@ -598,9 +600,9 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
}
|
||||
|
||||
if (typeof action.execute === 'function' && handlerSub) {
|
||||
handlerSub.subscribe(() => {
|
||||
action.execute(node);
|
||||
});
|
||||
handlerSub
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => action.execute(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -834,8 +836,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach((s) => s.unsubscribe());
|
||||
this.subscriptions = [];
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
private handleError(err: any) {
|
||||
|
@@ -24,10 +24,11 @@ import {
|
||||
ElementRef,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
import { NodeEntry, Node, Site } from '@alfresco/js-api';
|
||||
import { NodeEntry, Site } from '@alfresco/js-api';
|
||||
import { ShareDataRow } from '../../data/share-data-row.model';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-library-name-column',
|
||||
@@ -50,7 +51,7 @@ export class LibraryNameColumnComponent implements OnInit, OnDestroy {
|
||||
displayText$ = new BehaviorSubject<string>('');
|
||||
node: NodeEntry;
|
||||
|
||||
private sub: Subscription;
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(
|
||||
private element: ElementRef,
|
||||
@@ -60,8 +61,9 @@ export class LibraryNameColumnComponent implements OnInit, OnDestroy {
|
||||
ngOnInit() {
|
||||
this.updateValue();
|
||||
|
||||
this.sub = this.alfrescoApiService.nodeUpdated.subscribe(
|
||||
(node: Node) => {
|
||||
this.alfrescoApiService.nodeUpdated
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(node => {
|
||||
const row: ShareDataRow = this.context.row;
|
||||
if (row) {
|
||||
const { entry } = row.node;
|
||||
@@ -71,8 +73,7 @@ export class LibraryNameColumnComponent implements OnInit, OnDestroy {
|
||||
this.updateValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
protected updateValue() {
|
||||
@@ -119,9 +120,7 @@ export class LibraryNameColumnComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.sub) {
|
||||
this.sub.unsubscribe();
|
||||
this.sub = null;
|
||||
}
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
}
|
||||
|
@@ -23,10 +23,11 @@ import {
|
||||
ViewEncapsulation,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
import { Subscription, BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { Node, SiteEntry, Site } from '@alfresco/js-api';
|
||||
import { SiteEntry, Site } from '@alfresco/js-api';
|
||||
import { ShareDataRow } from '../../data/share-data-row.model';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-library-role-column',
|
||||
@@ -45,24 +46,26 @@ export class LibraryRoleColumnComponent implements OnInit, OnDestroy {
|
||||
|
||||
displayText$ = new BehaviorSubject<string>('');
|
||||
|
||||
private sub: Subscription;
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private api: AlfrescoApiService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.updateValue();
|
||||
|
||||
this.sub = this.api.nodeUpdated.subscribe((node: Node) => {
|
||||
const row: ShareDataRow = this.context.row;
|
||||
if (row) {
|
||||
const { entry } = row.node;
|
||||
this.api.nodeUpdated
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(node => {
|
||||
const row: ShareDataRow = this.context.row;
|
||||
if (row) {
|
||||
const { entry } = row.node;
|
||||
|
||||
if (entry === node) {
|
||||
row.node = { entry };
|
||||
this.updateValue();
|
||||
if (entry === node) {
|
||||
row.node = { entry };
|
||||
this.updateValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected updateValue() {
|
||||
@@ -90,9 +93,7 @@ export class LibraryRoleColumnComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.sub) {
|
||||
this.sub.unsubscribe();
|
||||
this.sub = null;
|
||||
}
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
}
|
||||
|
@@ -17,9 +17,10 @@
|
||||
|
||||
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { Subscription, BehaviorSubject } from 'rxjs';
|
||||
import { Node, Site, SiteEntry } from '@alfresco/js-api';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { Site, SiteEntry } from '@alfresco/js-api';
|
||||
import { ShareDataRow } from '../../data/share-data-row.model';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-library-status-column',
|
||||
@@ -36,24 +37,26 @@ export class LibraryStatusColumnComponent implements OnInit, OnDestroy {
|
||||
|
||||
displayText$ = new BehaviorSubject<string>('');
|
||||
|
||||
private sub: Subscription;
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private api: AlfrescoApiService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.updateValue();
|
||||
|
||||
this.sub = this.api.nodeUpdated.subscribe((node: Node) => {
|
||||
const row: ShareDataRow = this.context.row;
|
||||
if (row) {
|
||||
const { entry } = row.node;
|
||||
this.api.nodeUpdated
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(node => {
|
||||
const row: ShareDataRow = this.context.row;
|
||||
if (row) {
|
||||
const { entry } = row.node;
|
||||
|
||||
if (entry === node) {
|
||||
row.node = { entry };
|
||||
this.updateValue();
|
||||
if (entry === node) {
|
||||
row.node = { entry };
|
||||
this.updateValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected updateValue() {
|
||||
@@ -79,9 +82,7 @@ export class LibraryStatusColumnComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.sub) {
|
||||
this.sub.unsubscribe();
|
||||
this.sub = null;
|
||||
}
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
}
|
||||
|
@@ -25,10 +25,10 @@ import {
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { ShareDataRow } from '../../data/share-data-row.model';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-name-column',
|
||||
@@ -48,24 +48,26 @@ export class NameColumnComponent implements OnInit, OnDestroy {
|
||||
displayText$ = new BehaviorSubject<string>('');
|
||||
node: NodeEntry;
|
||||
|
||||
private sub: Subscription;
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private element: ElementRef, private alfrescoApiService: AlfrescoApiService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.updateValue();
|
||||
|
||||
this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => {
|
||||
const row: ShareDataRow = this.context.row;
|
||||
if (row) {
|
||||
const { entry } = row.node;
|
||||
this.alfrescoApiService.nodeUpdated
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(node => {
|
||||
const row: ShareDataRow = this.context.row;
|
||||
if (row) {
|
||||
const { entry } = row.node;
|
||||
|
||||
if (entry === node) {
|
||||
row.node = { entry };
|
||||
this.updateValue();
|
||||
if (entry === node) {
|
||||
row.node = { entry };
|
||||
this.updateValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected updateValue() {
|
||||
@@ -88,9 +90,7 @@ export class NameColumnComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.sub) {
|
||||
this.sub.unsubscribe();
|
||||
this.sub = null;
|
||||
}
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
}
|
||||
|
@@ -89,7 +89,7 @@ export class PermissionListComponent implements OnInit {
|
||||
saveNewRole(event: any, permissionRow: PermissionDisplayModel) {
|
||||
const updatedPermissionRole: PermissionElement = this.buildUpdatedPermission(event.value, permissionRow);
|
||||
this.nodePermissionService.updatePermissionRole(this.actualNode, updatedPermissionRole)
|
||||
.subscribe((node: Node) => {
|
||||
.subscribe(() => {
|
||||
this.update.emit(updatedPermissionRole);
|
||||
});
|
||||
}
|
||||
@@ -103,9 +103,12 @@ export class PermissionListComponent implements OnInit {
|
||||
}
|
||||
|
||||
removePermission(permissionRow: PermissionDisplayModel) {
|
||||
this.nodePermissionService.removePermission(this.actualNode, permissionRow).subscribe((node) => {
|
||||
this.update.emit(node);
|
||||
}, (error) => this.error.emit(error));
|
||||
this.nodePermissionService
|
||||
.removePermission(this.actualNode, permissionRow)
|
||||
.subscribe(
|
||||
node => this.update.emit(node),
|
||||
error => this.error.emit(error)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -108,19 +108,24 @@ export class SearchControlComponent implements OnInit, OnDestroy {
|
||||
private userPreferencesService: UserPreferencesService
|
||||
) {
|
||||
|
||||
this.toggleSearch.asObservable().pipe(debounceTime(200)).subscribe(() => {
|
||||
if (this.expandable) {
|
||||
this.subscriptAnimationState = this.toggleAnimation();
|
||||
this.toggleSearch
|
||||
.pipe(
|
||||
debounceTime(200),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe(() => {
|
||||
if (this.expandable) {
|
||||
this.subscriptAnimationState = this.toggleAnimation();
|
||||
|
||||
if (this.subscriptAnimationState.value === 'inactive') {
|
||||
this.searchTerm = '';
|
||||
this.searchAutocomplete.resetResults();
|
||||
if ( document.activeElement.id === this.searchInput.nativeElement.id) {
|
||||
this.searchInput.nativeElement.blur();
|
||||
if (this.subscriptAnimationState.value === 'inactive') {
|
||||
this.searchTerm = '';
|
||||
this.searchAutocomplete.resetResults();
|
||||
if ( document.activeElement.id === this.searchInput.nativeElement.id) {
|
||||
this.searchInput.nativeElement.blur();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
applySearchFocus(animationDoneEvent) {
|
||||
@@ -252,12 +257,12 @@ export class SearchControlComponent implements OnInit, OnDestroy {
|
||||
|
||||
private setupFocusEventHandlers() {
|
||||
const focusEvents: Observable<FocusEvent> = this.focusSubject
|
||||
.asObservable()
|
||||
.pipe(
|
||||
debounceTime(50),
|
||||
filter(($event: any) => {
|
||||
return this.isSearchBarActive() && ($event.type === 'blur' || $event.type === 'focusout');
|
||||
})
|
||||
}),
|
||||
takeUntil(this.onDestroy$)
|
||||
);
|
||||
|
||||
focusEvents.subscribe(() => {
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { OnInit, Component, ViewEncapsulation } from '@angular/core';
|
||||
import { OnInit, Component, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { FormControl, Validators, FormGroup } from '@angular/forms';
|
||||
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
|
||||
import { MomentDateAdapter, MOMENT_DATE_FORMATS } from '@alfresco/adf-core';
|
||||
@@ -26,6 +26,8 @@ import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
||||
import { LiveErrorStateMatcher } from '../../forms/live-error-state-matcher';
|
||||
import { Moment } from 'moment';
|
||||
import { UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
declare let moment: any;
|
||||
|
||||
@@ -42,7 +44,7 @@ const DEFAULT_FORMAT_DATE: string = 'DD/MM/YYYY';
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: { class: 'adf-search-date-range' }
|
||||
})
|
||||
export class SearchDateRangeComponent implements SearchWidget, OnInit {
|
||||
export class SearchDateRangeComponent implements SearchWidget, OnInit, OnDestroy {
|
||||
|
||||
from: FormControl;
|
||||
to: FormControl;
|
||||
@@ -56,6 +58,8 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
|
||||
maxDate: any;
|
||||
datePickerDateFormat = DEFAULT_FORMAT_DATE;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private dateAdapter: DateAdapter<Moment>,
|
||||
private userPreferencesService: UserPreferencesService) {
|
||||
}
|
||||
@@ -82,9 +86,10 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
|
||||
const theCustomDateAdapter = <MomentDateAdapter> <any> this.dateAdapter;
|
||||
theCustomDateAdapter.overrideDisplayFormat = this.datePickerDateFormat;
|
||||
|
||||
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
|
||||
this.setLocale(locale);
|
||||
});
|
||||
this.userPreferencesService
|
||||
.select(UserPreferenceValues.Locale)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(locale => this.setLocale(locale));
|
||||
|
||||
const validators = Validators.compose([
|
||||
Validators.required
|
||||
@@ -101,6 +106,11 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
|
||||
this.maxDate = this.dateAdapter.today().startOf('day');
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
apply(model: { from: string, to: string }, isValid: boolean) {
|
||||
if (isValid && this.id && this.context && this.settings && this.settings.field) {
|
||||
const start = moment(model.from).startOf('day').format();
|
||||
|
@@ -22,8 +22,9 @@ import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
||||
import { FacetFieldBucket } from '../../facet-field-bucket.interface';
|
||||
import { FacetField } from '../../facet-field.interface';
|
||||
import { SearchFilterList } from './models/search-filter-list.model';
|
||||
import { takeWhile } from 'rxjs/operators';
|
||||
import { ResultSetPaging, GenericBucket, GenericFacetResponse, ResultSetContext } from '@alfresco/js-api';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { GenericBucket, GenericFacetResponse, ResultSetContext } from '@alfresco/js-api';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-filter',
|
||||
@@ -36,8 +37,6 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
|
||||
|
||||
private DEFAULT_PAGE_SIZE = 5;
|
||||
|
||||
isAlive = true;
|
||||
|
||||
/** All facet field items to be displayed in the component. These are updated according to the response.
|
||||
* When a new search is performed, the already existing items are updated with the new bucket count values and
|
||||
* the newly received items are added to the responseFacets.
|
||||
@@ -52,6 +51,8 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
|
||||
displayResetButton: boolean;
|
||||
selectedBuckets: Array<{ field: FacetField, bucket: FacetFieldBucket }> = [];
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(public queryBuilder: SearchQueryBuilderService,
|
||||
private searchService: SearchService,
|
||||
private translationService: TranslationService) {
|
||||
@@ -68,26 +69,25 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
this.displayResetButton = this.queryBuilder.config && !!this.queryBuilder.config.resetButton;
|
||||
|
||||
this.queryBuilder.updated.pipe(
|
||||
takeWhile(() => this.isAlive)
|
||||
).subscribe(() => {
|
||||
this.queryBuilder.execute();
|
||||
});
|
||||
this.queryBuilder.updated
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => this.queryBuilder.execute());
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.queryBuilder) {
|
||||
this.queryBuilder.executed.pipe(
|
||||
takeWhile(() => this.isAlive)
|
||||
).subscribe((resultSetPaging: ResultSetPaging) => {
|
||||
this.onDataLoaded(resultSetPaging);
|
||||
this.searchService.dataLoaded.next(resultSetPaging);
|
||||
});
|
||||
this.queryBuilder.executed
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(resultSetPaging => {
|
||||
this.onDataLoaded(resultSetPaging);
|
||||
this.searchService.dataLoaded.next(resultSetPaging);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.isAlive = false;
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
private updateSelectedBuckets() {
|
||||
|
@@ -27,11 +27,12 @@ import {
|
||||
Output,
|
||||
TemplateRef,
|
||||
ViewChild,
|
||||
ViewEncapsulation
|
||||
ViewEncapsulation,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
import { NodePaging } from '@alfresco/js-api';
|
||||
import { Subject } from 'rxjs';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search',
|
||||
@@ -44,7 +45,7 @@ import { debounceTime } from 'rxjs/operators';
|
||||
'class': 'adf-search'
|
||||
}
|
||||
})
|
||||
export class SearchComponent implements AfterContentInit, OnChanges {
|
||||
export class SearchComponent implements AfterContentInit, OnChanges, OnDestroy {
|
||||
|
||||
@ViewChild('panel')
|
||||
panel: ElementRef;
|
||||
@@ -99,25 +100,27 @@ export class SearchComponent implements AfterContentInit, OnChanges {
|
||||
}
|
||||
|
||||
_isOpen: boolean = false;
|
||||
|
||||
keyPressedStream: Subject<string> = new Subject();
|
||||
|
||||
keyPressedStream = new Subject<string>();
|
||||
_classList: { [key: string]: boolean } = {};
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private searchService: SearchService,
|
||||
private _elementRef: ElementRef) {
|
||||
this.keyPressedStream.asObservable()
|
||||
this.keyPressedStream
|
||||
.pipe(
|
||||
debounceTime(200)
|
||||
debounceTime(200),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe((searchedWord: string) => {
|
||||
.subscribe(searchedWord => {
|
||||
this.loadSearchResults(searchedWord);
|
||||
});
|
||||
|
||||
searchService.dataLoaded.subscribe(
|
||||
(nodePaging: NodePaging) => this.onSearchDataLoaded(nodePaging),
|
||||
(error) => this.onSearchDataError(error)
|
||||
);
|
||||
searchService.dataLoaded
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(
|
||||
nodePaging => this.onSearchDataLoaded(nodePaging),
|
||||
error => this.onSearchDataError(error)
|
||||
);
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
@@ -130,6 +133,11 @@ export class SearchComponent implements AfterContentInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
resetResults() {
|
||||
this.cleanResults();
|
||||
this.setVisibility();
|
||||
|
@@ -15,10 +15,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { SitesService, LogService } from '@alfresco/adf-core';
|
||||
import { SitePaging, SiteEntry } from '@alfresco/js-api';
|
||||
import { MatSelect } from '@angular/material';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
export enum Relations {
|
||||
Members = 'members',
|
||||
@@ -32,7 +34,7 @@ export enum Relations {
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: { 'class': 'adf-sites-dropdown' }
|
||||
})
|
||||
export class DropdownSitesComponent implements OnInit {
|
||||
export class DropdownSitesComponent implements OnInit, OnDestroy {
|
||||
|
||||
/** Hide the "My Files" option. */
|
||||
@Input()
|
||||
@@ -77,27 +79,34 @@ export class DropdownSitesComponent implements OnInit {
|
||||
private readonly MAX_ITEMS = 50;
|
||||
private readonly ITEM_HEIGHT = 45;
|
||||
private readonly ITEM_HEIGHT_TO_WAIT_BEFORE_LOAD_NEXT = (this.ITEM_HEIGHT * (this.MAX_ITEMS / 2));
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
selected: SiteEntry = null;
|
||||
|
||||
public MY_FILES_VALUE = '-my-';
|
||||
MY_FILES_VALUE = '-my-';
|
||||
|
||||
constructor(private sitesService: SitesService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.siteSelect.openedChange.subscribe(() => {
|
||||
if (this.siteSelect.panelOpen) {
|
||||
this.siteSelect.panel.nativeElement.addEventListener('scroll', (event) => this.loadAllOnScroll(event));
|
||||
}
|
||||
});
|
||||
this.siteSelect.openedChange
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => {
|
||||
if (this.siteSelect.panelOpen) {
|
||||
this.siteSelect.panel.nativeElement.addEventListener('scroll', (event) => this.loadAllOnScroll(event));
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.siteList) {
|
||||
this.loadSiteList();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
loadAllOnScroll(event) {
|
||||
if (this.isInfiniteScrollingEnabled() && this.isScrollInNextFetchArea(event)) {
|
||||
this.loading = true;
|
||||
|
@@ -18,8 +18,9 @@
|
||||
import { TranslationService } from '@alfresco/adf-core';
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation, OnDestroy, OnInit } from '@angular/core';
|
||||
import { TagService } from './services/tag.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Subject } from 'rxjs';
|
||||
import { TagPaging } from '@alfresco/js-api';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -55,17 +56,15 @@ export class TagActionsComponent implements OnChanges, OnInit, OnDestroy {
|
||||
errorMsg: string;
|
||||
disableAddTag: boolean = true;
|
||||
|
||||
private subscriptions: Subscription[] = [];
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private tagService: TagService, private translateService: TranslationService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.subscriptions.push(
|
||||
this.tagService.refresh.subscribe(() => {
|
||||
this.refreshTag();
|
||||
})
|
||||
);
|
||||
this.tagService.refresh
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => this.refreshTag());
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
@@ -73,8 +72,8 @@ export class TagActionsComponent implements OnChanges, OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
|
||||
this.subscriptions = [];
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
refreshTag() {
|
||||
|
@@ -15,9 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, EventEmitter, OnInit, Output, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { TagService } from './services/tag.service';
|
||||
import { PaginationModel } from '@alfresco/adf-core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
/**
|
||||
* This component provide a list of all the tag inside the ECM
|
||||
@@ -28,7 +30,7 @@ import { PaginationModel } from '@alfresco/adf-core';
|
||||
styleUrls: ['./tag-list.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class TagListComponent implements OnInit {
|
||||
export class TagListComponent implements OnInit, OnDestroy {
|
||||
|
||||
/** Emitted when a tag is selected. */
|
||||
@Output()
|
||||
@@ -50,6 +52,8 @@ export class TagListComponent implements OnInit {
|
||||
isLoading = false;
|
||||
isSizeMinimum = true;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param tagService
|
||||
@@ -64,14 +68,21 @@ export class TagListComponent implements OnInit {
|
||||
|
||||
this.pagination = this.defaultPagination;
|
||||
|
||||
this.tagService.refresh.subscribe(() => {
|
||||
this.tagsEntries = [];
|
||||
this.refreshTag(this.defaultPagination);
|
||||
});
|
||||
this.tagService.refresh
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => {
|
||||
this.tagsEntries = [];
|
||||
this.refreshTag(this.defaultPagination);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
return this.refreshTag(this.defaultPagination);
|
||||
this.refreshTag(this.defaultPagination);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
refreshTag(opts?: any) {
|
||||
|
@@ -15,9 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation, OnDestroy, OnInit } from '@angular/core';
|
||||
import { TagService } from './services/tag.service';
|
||||
import { TagPaging } from '@alfresco/js-api';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -30,7 +32,7 @@ import { TagPaging } from '@alfresco/js-api';
|
||||
styleUrls: ['./tag-node-list.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class TagNodeListComponent implements OnChanges {
|
||||
export class TagNodeListComponent implements OnChanges, OnDestroy, OnInit {
|
||||
/** The identifier of a node. */
|
||||
@Input()
|
||||
nodeId: string;
|
||||
@@ -45,18 +47,28 @@ export class TagNodeListComponent implements OnChanges {
|
||||
@Output()
|
||||
results = new EventEmitter();
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param tagService
|
||||
*/
|
||||
constructor(private tagService: TagService) {
|
||||
this.tagService.refresh.subscribe(() => {
|
||||
this.refreshTag();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
return this.refreshTag();
|
||||
this.refreshTag();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.tagService.refresh
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => this.refreshTag());
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
refreshTag() {
|
||||
|
@@ -18,8 +18,9 @@
|
||||
import { FileModel, FileInfo } from '@alfresco/adf-core';
|
||||
import { EventEmitter, Input, Output, OnInit, OnDestroy, NgZone } from '@angular/core';
|
||||
import { UploadService, TranslationService } from '@alfresco/adf-core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Subject } from 'rxjs';
|
||||
import { UploadFilesEvent } from '../upload-files.event';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
export abstract class UploadBase implements OnInit, OnDestroy {
|
||||
|
||||
@@ -71,7 +72,7 @@ export abstract class UploadBase implements OnInit, OnDestroy {
|
||||
@Output()
|
||||
beginUpload = new EventEmitter<UploadFilesEvent>();
|
||||
|
||||
protected subscriptions: Subscription[] = [];
|
||||
protected onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(protected uploadService: UploadService,
|
||||
protected translationService: TranslationService,
|
||||
@@ -79,17 +80,14 @@ export abstract class UploadBase implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.subscriptions.push(
|
||||
this.uploadService.fileUploadError.subscribe((error) => {
|
||||
this.error.emit(error);
|
||||
})
|
||||
);
|
||||
|
||||
this.uploadService.fileUploadError
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(error => this.error.emit(error));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
|
||||
this.subscriptions = [];
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -15,10 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
FileModel, FileUploadCompleteEvent, FileUploadDeleteEvent,
|
||||
FileUploadErrorEvent, FileUploadStatus, UploadService, UserPreferencesService
|
||||
} from '@alfresco/adf-core';
|
||||
import { FileModel, FileUploadStatus, UploadService, UserPreferencesService } from '@alfresco/adf-core';
|
||||
import { ChangeDetectorRef, Component, Input, Output, EventEmitter, OnDestroy, OnInit, ViewChild, HostBinding } from '@angular/core';
|
||||
import { Subscription, merge, Subject } from 'rxjs';
|
||||
import { FileUploadingListComponent } from './file-uploading-list.component';
|
||||
@@ -33,7 +30,7 @@ import { takeUntil } from 'rxjs/operators';
|
||||
export class FileUploadingDialogComponent implements OnInit, OnDestroy {
|
||||
/** Dialog direction. Can be 'ltr' or 'rtl. */
|
||||
private direction: Direction = 'ltr';
|
||||
private onDestroy$: Subject<boolean> = new Subject<boolean>();
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
@ViewChild('uploadList')
|
||||
uploadList: FileUploadingListComponent;
|
||||
@@ -79,8 +76,9 @@ export class FileUploadingDialogComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.listSubscription = this.uploadService
|
||||
.queueChanged.subscribe((fileList: FileModel[]) => {
|
||||
this.listSubscription = this.uploadService.queueChanged
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(fileList => {
|
||||
this.filesUploadingList = fileList;
|
||||
|
||||
if (this.filesUploadingList.length) {
|
||||
@@ -92,33 +90,38 @@ export class FileUploadingDialogComponent implements OnInit, OnDestroy {
|
||||
this.uploadService.fileUploadComplete,
|
||||
this.uploadService.fileUploadDeleted
|
||||
)
|
||||
.subscribe((event: (FileUploadDeleteEvent | FileUploadCompleteEvent)) => {
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(event => {
|
||||
this.totalCompleted = event.totalComplete;
|
||||
this.changeDetector.detectChanges();
|
||||
});
|
||||
|
||||
this.errorSubscription = this.uploadService.fileUploadError
|
||||
.subscribe((event: FileUploadErrorEvent) => {
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(event => {
|
||||
this.totalErrors = event.totalError;
|
||||
this.changeDetector.detectChanges();
|
||||
});
|
||||
|
||||
this.fileUploadSubscription = this.uploadService
|
||||
.fileUpload.subscribe(() => {
|
||||
this.fileUploadSubscription = this.uploadService.fileUpload
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => {
|
||||
this.changeDetector.detectChanges();
|
||||
});
|
||||
|
||||
this.uploadService.fileDeleted.subscribe((objId) => {
|
||||
if (this.filesUploadingList) {
|
||||
const file = this.filesUploadingList.find((item) => {
|
||||
return item.data.entry.id === objId;
|
||||
});
|
||||
if (file) {
|
||||
file.status = FileUploadStatus.Cancelled;
|
||||
this.changeDetector.detectChanges();
|
||||
this.uploadService.fileDeleted
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(objId => {
|
||||
if (this.filesUploadingList) {
|
||||
const file = this.filesUploadingList.find((item) => {
|
||||
return item.data.entry.id === objId;
|
||||
});
|
||||
if (file) {
|
||||
file.status = FileUploadStatus.Cancelled;
|
||||
this.changeDetector.detectChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.userPreferencesService.select('textOrientation')
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
|
Reference in New Issue
Block a user