[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:
Denys Vuika
2019-07-16 15:56:00 +01:00
committed by Eugenio Romano
parent e2311ab045
commit 1abb9bfc89
98 changed files with 1581 additions and 1066 deletions

View File

@@ -1,4 +1,3 @@
# This is a comment.
# Each line is a file pattern followed by one or more owners.

View File

@@ -15,9 +15,11 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { Component, ViewEncapsulation, OnInit, OnDestroy } from '@angular/core';
import { UserPreferencesService, AppConfigService, AlfrescoApiService, UserPreferenceValues } from '@alfresco/adf-core';
import { HeaderDataService } from '../header-data/header-data.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: 'app-layout.component.html',
@@ -27,8 +29,8 @@ import { HeaderDataService } from '../header-data/header-data.service';
},
encapsulation: ViewEncapsulation.None
})
export class AppLayoutComponent implements OnInit {
export class AppLayoutComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
links: Array<any> = [
{ href: '/home', icon: 'home', title: 'APP_LAYOUT.HOME' },
@@ -108,14 +110,42 @@ export class AppLayoutComponent implements OnInit {
this.expandedSidenav = expand;
}
this.headerService.hideMenu.subscribe((show) => this.showMenu = show);
this.headerService.color.subscribe((color) => this.color = color);
this.headerService.title.subscribe((title) => this.title = title);
this.headerService.logo.subscribe((path) => this.logo = path);
this.headerService.redirectUrl.subscribe((redirectUrl) => this.redirectUrl = redirectUrl);
this.headerService.tooltip.subscribe((tooltip) => this.tooltip = tooltip);
this.headerService.position.subscribe((position) => this.position = position);
this.headerService.hideSidenav.subscribe((hideSidenav) => this.hideSidenav = hideSidenav);
this.headerService.hideMenu
.pipe(takeUntil(this.onDestroy$))
.subscribe(show => this.showMenu = show);
this.headerService.color
.pipe(takeUntil(this.onDestroy$))
.subscribe(color => this.color = color);
this.headerService.title
.pipe(takeUntil(this.onDestroy$))
.subscribe(title => this.title = title);
this.headerService.logo
.pipe(takeUntil(this.onDestroy$))
.subscribe(path => this.logo = path);
this.headerService.redirectUrl
.pipe(takeUntil(this.onDestroy$))
.subscribe(redirectUrl => this.redirectUrl = redirectUrl);
this.headerService.tooltip
.pipe(takeUntil(this.onDestroy$))
.subscribe(tooltip => this.tooltip = tooltip);
this.headerService.position
.pipe(takeUntil(this.onDestroy$))
.subscribe(position => this.position = position);
this.headerService.hideSidenav
.pipe(takeUntil(this.onDestroy$))
.subscribe(hideSidenav => this.hideSidenav = hideSidenav);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
constructor(

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import { Component, OnInit, ElementRef, ViewChild, OnDestroy } from '@angular/core';
import {
CardViewTextItemModel,
CardViewDateItemModel,
@@ -29,13 +29,14 @@ import {
CardViewMapItemModel,
UpdateNotification
} from '@alfresco/adf-core';
import { of } from 'rxjs';
import { of, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: './card-view.component.html',
styleUrls: ['./card-view.component.scss']
})
export class CardViewComponent implements OnInit {
export class CardViewComponent implements OnInit, OnDestroy {
@ViewChild('console') console: ElementRef;
@@ -43,6 +44,8 @@ export class CardViewComponent implements OnInit {
properties: any;
logs: string[];
private onDestroy$ = new Subject<boolean>();
constructor(private cardViewUpdateService: CardViewUpdateService) {
this.logs = [];
this.createCard();
@@ -53,7 +56,14 @@ export class CardViewComponent implements OnInit {
}
ngOnInit() {
this.cardViewUpdateService.itemUpdated$.subscribe(this.onItemChange.bind(this));
this.cardViewUpdateService.itemUpdated$
.pipe(takeUntil(this.onDestroy$))
.subscribe(this.onItemChange.bind(this));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
createCard() {

View File

@@ -24,18 +24,16 @@ import { ActivatedRoute } from '@angular/router';
styleUrls: ['cloud-breadcrumb-component.scss']
})
export class CloudBreadcrumbsComponent implements OnInit {
appName: string;
filterName: string;
constructor(private route: ActivatedRoute) { }
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.parent.params.subscribe((
params) => {
this.route.parent.params.subscribe(params => {
this.appName = params.appName;
});
this.route.queryParams.subscribe((params) => {
this.route.queryParams.subscribe(params => {
if (params.filterName) {
this.filterName = params.filterName;
}

View File

@@ -46,8 +46,9 @@ export class CloudFiltersDemoComponent implements OnInit {
) {}
ngOnInit() {
this.currentTaskFilter$ = this.cloudLayoutService.getCurrentTaskFilterParam();
this.currentProcessFilter$ = this.cloudLayoutService.getCurrentProcessFilterParam();
this.currentTaskFilter$ = this.cloudLayoutService.taskFilter$;
this.currentProcessFilter$ = this.cloudLayoutService.processFilter$;
let root = '';
if (this.route.snapshot && this.route.snapshot.firstChild) {
root = this.route.snapshot.firstChild.url[0].path;

View File

@@ -15,15 +15,18 @@
* limitations under the License.
*/
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CloudLayoutService } from './services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-cloud-settings',
templateUrl: './cloud-settings.component.html',
styleUrls: ['./cloud-settings.component.scss']
})
export class CloudSettingsComponent implements OnInit {
export class CloudSettingsComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
multiselect: boolean;
selectionMode: string;
@@ -40,8 +43,15 @@ export class CloudSettingsComponent implements OnInit {
constructor(private cloudLayoutService: CloudLayoutService) { }
ngOnInit() {
this.cloudLayoutService.getCurrentSettings()
.subscribe((settings) => this.setCurrentSettings(settings));
this.cloudLayoutService
.settings$
.pipe(takeUntil(this.onDestroy$))
.subscribe(settings => this.setCurrentSettings(settings));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
setCurrentSettings(settings) {

View File

@@ -15,32 +15,24 @@
* limitations under the License.
*/
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { Params } from '@angular/router/src/shared';
@Component({
selector: 'app-cloud-viewer',
templateUrl: './cloud-viewer.component.html'
})
export class CloudViewerComponent implements OnInit, OnDestroy {
export class CloudViewerComponent implements OnInit {
nodeId: string;
private sub: Subscription;
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.sub = this.route.params.subscribe((params: Params) => {
this.route.params.subscribe((params: Params) => {
this.nodeId = params['nodeId'];
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}

View File

@@ -45,8 +45,9 @@ export class CommunityCloudFiltersDemoComponent implements OnInit {
) {}
ngOnInit() {
this.currentTaskFilter$ = this.cloudLayoutService.getCurrentTaskFilterParam();
this.currentProcessFilter$ = this.cloudLayoutService.getCurrentProcessFilterParam();
this.currentTaskFilter$ = this.cloudLayoutService.taskFilter$;
this.currentProcessFilter$ = this.cloudLayoutService.processFilter$;
let root = '';
if (this.route.snapshot && this.route.snapshot.firstChild) {
root = this.route.snapshot.firstChild.url[0].path;

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, ViewChild, OnInit } from '@angular/core';
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import {
ProcessListCloudComponent,
ProcessFilterCloudModel,
@@ -27,12 +27,14 @@ import {
import { ActivatedRoute, Router } from '@angular/router';
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
import { CloudLayoutService } from '../services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Pagination } from '@alfresco/js-api';
@Component({
templateUrl: './community-processes-cloud.component.html'
})
export class CommunityProcessesCloudDemoComponent implements OnInit {
export class CommunityProcessesCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
static PROCESS_FILTER_PROPERTY_KEYS = 'adf-edit-process-filter';
@@ -56,6 +58,8 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
editedFilter: ProcessFilterCloudModel;
private onDestroy$ = new Subject<boolean>();
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -63,7 +67,10 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
private userPreference: UserPreferencesService,
private processFilterCloudService: ProcessFilterCloudService,
private appConfig: AppConfigService) {
const properties = this.appConfig.get<Array<any>>(CommunityProcessesCloudDemoComponent.PROCESS_FILTER_PROPERTY_KEYS);
const properties = this.appConfig.get<Array<any>>(
CommunityProcessesCloudDemoComponent.PROCESS_FILTER_PROPERTY_KEYS
);
if (properties) {
this.processFilterProperties = properties;
}
@@ -71,6 +78,7 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
ngOnInit() {
this.isFilterLoaded = false;
this.route.parent.params.subscribe((params) => {
this.appName = params.appName;
});
@@ -85,12 +93,21 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
}
});
this.cloudLayoutService.getCurrentSettings()
.subscribe((settings) => this.setCurrentSettings(settings));
this.cloudLayoutService
.settings$
.pipe(takeUntil(this.onDestroy$))
.subscribe(settings => this.setCurrentSettings(settings));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
loadDefaultFilters() {
this.processFilterCloudService.getProcessFilters('community').subscribe( (filters: ProcessFilterCloudModel[]) => {
this.processFilterCloudService
.getProcessFilters('community')
.subscribe((filters: ProcessFilterCloudModel[]) => {
this.onFilterChange(filters[0]);
});
}
@@ -103,7 +120,7 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
}
}
onChangePageSize(event) {
onChangePageSize(event: Pagination) {
this.userPreference.paginationSize = event.maxItems;
}
@@ -111,13 +128,18 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
this.selectedRows = [];
}
onRowClick(processInstanceId) {
onRowClick(processInstanceId: string) {
this.router.navigate([`/cloud/community/process-details/${processInstanceId}`]);
}
onFilterChange(query: any) {
this.editedFilter = Object.assign({}, query);
this.sortArray = [new ProcessListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })];
this.sortArray = [
new ProcessListCloudSortingModel({
orderBy: this.editedFilter.sort,
direction: this.editedFilter.order
})
];
}
onProcessFilterAction(filterAction: any) {

View File

@@ -15,11 +15,14 @@
* limitations under the License.
*/
import { Component, ViewChild, OnInit } from '@angular/core';
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { TaskListCloudComponent, TaskListCloudSortingModel, TaskFilterCloudModel, TaskFilterCloudService } from '@alfresco/adf-process-services-cloud';
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
import { ActivatedRoute, Router } from '@angular/router';
import { CloudLayoutService } from '../services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Pagination } from '@alfresco/js-api';
@Component({
templateUrl: './community-task-cloud.component.html',
@@ -28,8 +31,7 @@ import { CloudLayoutService } from '../services/cloud-layout.service';
}
`]
})
export class CommunityTasksCloudDemoComponent implements OnInit {
export class CommunityTasksCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
static TASK_FILTER_PROPERTY_KEYS = 'adf-edit-task-filter';
@@ -51,6 +53,8 @@ export class CommunityTasksCloudDemoComponent implements OnInit {
selectionMode: string;
taskDetailsRedirection: boolean;
private onDestroy$ = new Subject<boolean>();
constructor(
private cloudLayoutService: CloudLayoutService,
private route: ActivatedRoute,
@@ -79,12 +83,21 @@ export class CommunityTasksCloudDemoComponent implements OnInit {
}
});
this.cloudLayoutService.getCurrentSettings()
.subscribe((settings) => this.setCurrentSettings(settings));
this.cloudLayoutService
.settings$
.pipe(takeUntil(this.onDestroy$))
.subscribe(settings => this.setCurrentSettings(settings));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
loadDefaultFilters() {
this.taskFilterCloudService.getTaskListFilters('community').subscribe( (filters: TaskFilterCloudModel[]) => {
this.taskFilterCloudService
.getTaskListFilters('community')
.subscribe((filters: TaskFilterCloudModel[]) => {
this.onFilterChange(filters[0]);
});
}
@@ -98,7 +111,7 @@ export class CommunityTasksCloudDemoComponent implements OnInit {
}
}
onChangePageSize(event) {
onChangePageSize(event: Pagination) {
this.userPreference.paginationSize = event.maxItems;
}
@@ -106,7 +119,7 @@ export class CommunityTasksCloudDemoComponent implements OnInit {
this.selectedRows = [];
}
onRowClick(taskId) {
onRowClick(taskId: string) {
if (!this.multiselect && this.selectionMode !== 'multiple' && this.taskDetailsRedirection) {
this.router.navigate([`/cloud/community/task-details/${taskId}`]);
}

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, ViewChild, OnInit } from '@angular/core';
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import {
ProcessListCloudComponent,
ProcessFilterCloudModel,
@@ -25,13 +25,16 @@ import {
import { ActivatedRoute, Router } from '@angular/router';
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
import { CloudLayoutService } from './services/cloud-layout.service';
import { CloudLayoutService, CloudServiceSettings } from './services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Pagination } from '@alfresco/js-api';
@Component({
templateUrl: './processes-cloud-demo.component.html',
styleUrls: ['./processes-cloud-demo.component.scss']
})
export class ProcessesCloudDemoComponent implements OnInit {
export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
static PROCESS_FILTER_PROPERTY_KEYS = 'adf-edit-process-filter';
@@ -57,6 +60,8 @@ export class ProcessesCloudDemoComponent implements OnInit {
editedFilter: ProcessFilterCloudModel;
private onDestroy$ = new Subject<boolean>();
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -81,11 +86,17 @@ export class ProcessesCloudDemoComponent implements OnInit {
this.filterId = params.id;
});
this.cloudLayoutService.getCurrentSettings()
.subscribe((settings) => this.setCurrentSettings(settings));
this.cloudLayoutService.settings$
.pipe(takeUntil(this.onDestroy$))
.subscribe(settings => this.setCurrentSettings(settings));
}
setCurrentSettings(settings) {
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
setCurrentSettings(settings: CloudServiceSettings) {
if (settings) {
this.multiselect = settings.multiselect;
this.testingMode = settings.testingMode;
@@ -94,7 +105,7 @@ export class ProcessesCloudDemoComponent implements OnInit {
}
}
onChangePageSize(event) {
onChangePageSize(event: Pagination) {
this.userPreference.paginationSize = event.maxItems;
}
@@ -102,7 +113,7 @@ export class ProcessesCloudDemoComponent implements OnInit {
this.selectedRows = [];
}
onRowClick(processInstanceId) {
onRowClick(processInstanceId: string) {
if (!this.multiselect && this.selectionMode !== 'multiple' && this.processDetailsRedirection) {
this.router.navigate([`/cloud/${this.appName}/process-details/${processInstanceId}`]);
}
@@ -110,7 +121,12 @@ export class ProcessesCloudDemoComponent implements OnInit {
onFilterChange(query: any) {
this.editedFilter = Object.assign({}, query);
this.sortArray = [new ProcessListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })];
this.sortArray = [
new ProcessListCloudSortingModel({
orderBy: this.editedFilter.sort,
direction: this.editedFilter.order
})
];
}
onProcessFilterAction(filterAction: any) {

View File

@@ -16,14 +16,28 @@
*/
import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
import { BehaviorSubject } from 'rxjs';
export interface CloudServiceSettings {
multiselect: boolean;
testingMode: boolean;
taskDetailsRedirection: boolean;
processDetailsRedirection: boolean;
selectionMode: string;
}
export interface FilterSettings {
id?: string;
index?: number;
key?: string;
}
@Injectable({
providedIn: 'root'
})
export class CloudLayoutService {
private settings = {
private settings: CloudServiceSettings = {
multiselect: false,
testingMode: false,
taskDetailsRedirection: true,
@@ -31,40 +45,19 @@ export class CloudLayoutService {
selectionMode: 'single'
};
private filterTaskSubject: BehaviorSubject<any> = new BehaviorSubject({index: 0});
private filterTask$: Observable<any>;
private filterProcessSubject: BehaviorSubject<any> = new BehaviorSubject({index: 0});
private filterProcess$: Observable<any>;
private settingsSubject: BehaviorSubject<any> = new BehaviorSubject(this.settings);
private settings$: Observable<any>;
taskFilter$ = new BehaviorSubject<FilterSettings>({index: 0});
processFilter$ = new BehaviorSubject<FilterSettings>({index: 0});
settings$ = new BehaviorSubject<CloudServiceSettings>(this.settings);
constructor() {
this.filterTask$ = this.filterTaskSubject.asObservable();
this.filterProcess$ = this.filterProcessSubject.asObservable();
this.settings$ = this.settingsSubject.asObservable();
setCurrentTaskFilterParam(param: FilterSettings) {
this.taskFilter$.next(param);
}
getCurrentTaskFilterParam() {
return this.filterTask$;
setCurrentProcessFilterParam(param: FilterSettings) {
this.processFilter$.next(param);
}
setCurrentTaskFilterParam(param) {
this.filterTaskSubject.next(param);
}
getCurrentProcessFilterParam() {
return this.filterProcess$;
}
setCurrentProcessFilterParam(param) {
this.filterProcessSubject.next(param);
}
getCurrentSettings() {
return this.settings$;
}
setCurrentSettings(param) {
this.settingsSubject.next(param);
setCurrentSettings(param: CloudServiceSettings) {
this.settings$.next(param);
}
}

View File

@@ -15,17 +15,19 @@
* limitations under the License.
*/
import { Component, ViewChild, OnInit } from '@angular/core';
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { TaskListCloudComponent, TaskListCloudSortingModel, TaskFilterCloudModel } from '@alfresco/adf-process-services-cloud';
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
import { ActivatedRoute, Router } from '@angular/router';
import { CloudLayoutService } from './services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: 'tasks-cloud-demo.component.html',
styleUrls: ['tasks-cloud-demo.component.scss']
})
export class TasksCloudDemoComponent implements OnInit {
export class TasksCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
static TASK_FILTER_PROPERTY_KEYS = 'adf-edit-task-filter';
@@ -50,6 +52,8 @@ export class TasksCloudDemoComponent implements OnInit {
selectionMode: string;
taskDetailsRedirection: boolean;
private onDestroy$ = new Subject<boolean>();
constructor(
private cloudLayoutService: CloudLayoutService,
private route: ActivatedRoute,
@@ -75,8 +79,14 @@ export class TasksCloudDemoComponent implements OnInit {
this.filterId = params.id;
});
this.cloudLayoutService.getCurrentSettings()
.subscribe((settings) => this.setCurrentSettings(settings));
this.cloudLayoutService.settings$
.pipe(takeUntil(this.onDestroy$))
.subscribe(settings => this.setCurrentSettings(settings));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
setCurrentSettings(settings) {

View File

@@ -15,20 +15,24 @@
* limitations under the License.
*/
import { Component } from '@angular/core';
import { Component, OnDestroy } from '@angular/core';
import {
AppConfigService,
NotificationService,
UserPreferencesService,
UserPreferenceValues
} from '@alfresco/adf-core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-config-editor',
templateUrl: 'config-editor.component.html',
styleUrls: ['./config-editor.component.scss']
})
export class ConfigEditorComponent {
export class ConfigEditorComponent implements OnDestroy {
private onDestroy$ = new Subject<boolean>();
editor: any;
code: any;
@@ -83,11 +87,19 @@ export class ConfigEditorComponent {
this.indentCode();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
textOrientationClick() {
this.isUserPreference = true;
this.userPreferenceProperty = 'textOrientation';
this.userPreferencesService.select(this.userPreferenceProperty).subscribe((textOrientation: number) => {
this.userPreferencesService
.select(this.userPreferenceProperty)
.pipe(takeUntil(this.onDestroy$))
.subscribe((textOrientation: number) => {
this.code = JSON.stringify(textOrientation);
this.field = 'textOrientation';
this.indentCode();
@@ -99,7 +111,10 @@ export class ConfigEditorComponent {
infinitePaginationConfClick() {
this.isUserPreference = true;
this.userPreferenceProperty = UserPreferenceValues.PaginationSize;
this.userPreferencesService.select(this.userPreferenceProperty).subscribe((pageSize: number) => {
this.userPreferencesService
.select(this.userPreferenceProperty)
.pipe(takeUntil(this.onDestroy$))
.subscribe((pageSize: number) => {
this.code = JSON.stringify(pageSize);
this.field = 'adf-infinite-pagination';
this.indentCode();
@@ -109,7 +124,10 @@ export class ConfigEditorComponent {
supportedPageSizesClick() {
this.isUserPreference = true;
this.userPreferenceProperty = UserPreferenceValues.SupportedPageSizes;
this.userPreferencesService.select(this.userPreferenceProperty).subscribe((supportedPageSizes: number) => {
this.userPreferencesService
.select(this.userPreferenceProperty)
.pipe(takeUntil(this.onDestroy$))
.subscribe((supportedPageSizes: number) => {
this.code = JSON.stringify(supportedPageSizes);
this.field = 'adf-supported-page-size';
this.indentCode();

View File

@@ -25,9 +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 { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-name-column',
@@ -47,14 +48,16 @@ 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) => {
this.alfrescoApiService.nodeUpdated
.pipe(takeUntil(this.onDestroy$))
.subscribe((node: Node) => {
const row = this.context.row;
if (row) {
const { entry } = row.node;
@@ -87,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();
}
}

View File

@@ -45,7 +45,7 @@ import { SelectAppsDialogComponent } from '@alfresco/adf-process-services';
import { VersionManagerDialogAdapterComponent } from './version-manager-dialog-adapter.component';
import { MetadataDialogAdapterComponent } from './metadata-dialog-adapter.component';
import { Subscription, Subject } from 'rxjs';
import { Subject } from 'rxjs';
import { PreviewService } from '../../services/preview.service';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { SearchEntry } from '@alfresco/js-api';
@@ -201,9 +201,6 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
displayEmptyMetadata = false;
hyperlinkNavigation = false;
private onCreateFolder: Subscription;
private onEditFolder: Subscription;
constructor(private notificationService: NotificationService,
private uploadService: UploadService,
private contentService: ContentService,
@@ -264,13 +261,28 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
});
}
this.uploadService.fileUploadComplete.asObservable()
.pipe(debounceTime(300))
.subscribe((value) => this.onFileUploadEvent(value));
this.uploadService.fileUploadDeleted.subscribe((value) => this.onFileUploadEvent(value));
this.contentService.folderCreated.subscribe((value) => this.onFolderCreated(value));
this.onCreateFolder = this.contentService.folderCreate.subscribe((value) => this.onFolderAction(value));
this.onEditFolder = this.contentService.folderEdit.subscribe((value) => this.onFolderAction(value));
this.uploadService.fileUploadComplete
.pipe(
debounceTime(300),
takeUntil(this.onDestroy$)
)
.subscribe(value => this.onFileUploadEvent(value));
this.uploadService.fileUploadDeleted
.pipe(takeUntil(this.onDestroy$))
.subscribe(value => this.onFileUploadEvent(value));
this.contentService.folderCreated
.pipe(takeUntil(this.onDestroy$))
.subscribe(value => this.onFolderCreated(value));
this.contentService.folderCreate
.pipe(takeUntil(this.onDestroy$))
.subscribe(value => this.onFolderAction(value));
this.contentService.folderEdit
.pipe(takeUntil(this.onDestroy$))
.subscribe(value => this.onFolderAction(value));
this.contentMetadataService.error
.pipe(takeUntil(this.onDestroy$))
@@ -286,9 +298,6 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
}
ngOnDestroy() {
this.onCreateFolder.unsubscribe();
this.onEditFolder.unsubscribe();
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
@@ -592,7 +601,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
width: '400px'
});
dialogInstance.componentInstance.error.subscribe((message) => {
dialogInstance.componentInstance.error.subscribe((message: string) => {
this.notificationService.openSnackMessage(message);
});
}

View File

@@ -15,16 +15,18 @@
* limitations under the License.
*/
import { Component, ViewChild } from '@angular/core';
import { Component, ViewChild, OnDestroy, OnInit } from '@angular/core';
import { FormModel, FormService, LogService, FormOutcomeEvent } from '@alfresco/adf-core';
import { FormComponent } from '@alfresco/adf-process-services';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-form-list',
templateUrl: 'form-list.component.html',
styleUrls: ['form-list.component.scss']
})
export class FormListComponent {
export class FormListComponent implements OnInit, OnDestroy {
@ViewChild('adfForm')
activitiForm: FormComponent;
@@ -38,15 +40,26 @@ export class FormListComponent {
restoredData: any = {};
showValidationIcon = false;
private onDestroy$ = new Subject<boolean>();
constructor(private formService: FormService, private logService: LogService) {
}
ngOnInit() {
// Prevent default outcome actions
formService.executeOutcome.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
this.formService.executeOutcome
.pipe(takeUntil(this.onDestroy$))
.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
formOutcomeEvent.preventDefault();
this.logService.log(formOutcomeEvent.outcome);
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onRowDblClick(event: CustomEvent) {
const rowForm = event.detail.value.obj;

View File

@@ -15,46 +15,60 @@
* limitations under the License.
*/
import { Component, Inject, OnInit } from '@angular/core';
import { FormModel, FormService, FormOutcomeEvent, CoreAutomationService } from '@alfresco/adf-core';
import { Component, Inject, OnInit, OnDestroy } from '@angular/core';
import {
FormModel,
FormService,
FormOutcomeEvent,
CoreAutomationService
} from '@alfresco/adf-core';
import { InMemoryFormService } from '../../services/in-memory-form.service';
import { FakeFormService } from './fake-form.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-form-loading',
templateUrl: 'form-loading.component.html',
styleUrls: ['form-loading.component.scss'],
providers: [
{ provide: FormService, useClass: FakeFormService }
]
providers: [{ provide: FormService, useClass: FakeFormService }]
})
export class FormLoadingComponent implements OnInit {
export class FormLoadingComponent implements OnInit, OnDestroy {
form: FormModel;
typeaheadFieldValue = '';
selectFieldValue = '';
radioButtonFieldValue = '';
formattedData = {};
constructor(@Inject(FormService) private formService: InMemoryFormService,
private automationService: CoreAutomationService) {
formService.executeOutcome.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
formOutcomeEvent.preventDefault();
});
}
private onDestroy$ = new Subject<boolean>();
constructor(
@Inject(FormService) private formService: InMemoryFormService,
private automationService: CoreAutomationService
) {}
ngOnInit() {
this.formService.executeOutcome
.pipe(takeUntil(this.onDestroy$))
.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
formOutcomeEvent.preventDefault();
});
this.formattedData = {};
const formDefinitionJSON: any = this.automationService.forms.getSimpleFormDefinition();
this.form = this.formService.parseForm(formDefinitionJSON);
}
onLoadButtonClicked() {
this.formattedData = {
'typeaheadField': this.typeaheadFieldValue,
'selectBox': this.selectFieldValue,
'radioButton': this.radioButtonFieldValue
};
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onLoadButtonClicked() {
this.formattedData = {
typeaheadField: this.typeaheadFieldValue,
selectBox: this.selectFieldValue,
radioButton: this.radioButtonFieldValue
};
}
}

View File

@@ -18,7 +18,8 @@
import { Component, Inject, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormModel, FormFieldModel, FormService, FormOutcomeEvent, NotificationService, CoreAutomationService } from '@alfresco/adf-core';
import { InMemoryFormService } from '../../services/in-memory-form.service';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-form',
@@ -35,7 +36,6 @@ export class FormComponent implements OnInit, OnDestroy {
errorFields: FormFieldModel[] = [];
formConfig: string;
editor: any;
private subscriptions: Subscription[] = [];
editorOptions = {
theme: 'vs-dark',
@@ -46,15 +46,11 @@ export class FormComponent implements OnInit, OnDestroy {
automaticLayout: true
};
private onDestroy$ = new Subject<boolean>();
constructor(@Inject(FormService) private formService: InMemoryFormService,
private notificationService: NotificationService,
private automationService: CoreAutomationService) {
this.subscriptions.push(
formService.executeOutcome.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
formOutcomeEvent.preventDefault();
})
);
}
logErrors(errorFields: FormFieldModel[]) {
@@ -62,13 +58,21 @@ export class FormComponent implements OnInit, OnDestroy {
}
ngOnInit() {
this.formConfig = JSON.stringify(this.automationService.forms.getFormDefinition());
this.formService.executeOutcome
.pipe(takeUntil(this.onDestroy$))
.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
formOutcomeEvent.preventDefault();
});
this.formConfig = JSON.stringify(
this.automationService.forms.getFormDefinition()
);
this.parseForm();
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onInitFormEditor(editor) {

View File

@@ -24,14 +24,14 @@ export class HeaderDataService {
show = true;
@Output() hideMenu: EventEmitter<boolean> = new EventEmitter();
@Output() color: EventEmitter<string> = new EventEmitter();
@Output() title: EventEmitter<string> = new EventEmitter();
@Output() logo: EventEmitter<string> = new EventEmitter();
@Output() redirectUrl: EventEmitter<string | any[]> = new EventEmitter();
@Output() tooltip: EventEmitter<string> = new EventEmitter();
@Output() position: EventEmitter<string> = new EventEmitter();
@Output() hideSidenav: EventEmitter<string> = new EventEmitter();
@Output() hideMenu = new EventEmitter<boolean>();
@Output() color = new EventEmitter<string>();
@Output() title = new EventEmitter<string>();
@Output() logo = new EventEmitter<string>();
@Output() redirectUrl = new EventEmitter<string | any[]>();
@Output() tooltip = new EventEmitter<string>();
@Output() position = new EventEmitter<string>();
@Output() hideSidenav = new EventEmitter<boolean>();
hideMenuButton() {
this.show = !this.show;
@@ -59,11 +59,11 @@ export class HeaderDataService {
this.tooltip.emit(tooltip);
}
changePosition(position) {
changePosition(position: string) {
this.position.emit(position);
}
changeSidenavVisibility(hideSidenav) {
changeSidenavVisibility(hideSidenav: boolean) {
this.hideSidenav.emit(hideSidenav);
}
}

View File

@@ -15,38 +15,59 @@
* limitations under the License.
*/
import { Component, HostListener } from '@angular/core';
import { Component, HostListener, OnDestroy, OnInit } from '@angular/core';
import { LogService, ObjectDataTableAdapter } from '@alfresco/adf-core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-log',
templateUrl: './log.component.html',
styleUrls: ['./log.component.css']
})
export class LogComponent {
export class LogComponent implements OnInit, OnDestroy {
logs: any[] = [];
show = false;
ctrlLKey = 12;
logsData: ObjectDataTableAdapter;
constructor(public logService: LogService) {
private onDestroy$ = new Subject<boolean>();
logService.onMessage.subscribe((message) => {
constructor(public logService: LogService) {}
ngOnInit() {
this.logService.onMessage
.pipe(takeUntil(this.onDestroy$))
.subscribe(message => {
let contentMessage = '';
try {
contentMessage = JSON.stringify(message.text);
} catch (error) {
return;
}
this.logs.push({ type: message.type, text: contentMessage});
this.logs.push({ type: message.type, text: contentMessage });
this.logsData = new ObjectDataTableAdapter(this.logs, [
{ type: 'text', key: 'type', title: 'Log level', sortable: true },
{ type: 'text', key: 'text', title: 'Message', sortable: false }
{
type: 'text',
key: 'type',
title: 'Log level',
sortable: true
},
{
type: 'text',
key: 'text',
title: 'Message',
sortable: false
}
]);
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
@HostListener('document:keypress', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
const key = event.keyCode;
@@ -54,6 +75,5 @@ export class LogComponent {
if (key === this.ctrlLKey) {
this.show = !this.show;
}
}
}

View File

@@ -15,16 +15,18 @@
* limitations under the License.
*/
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { NotificationService } from '@alfresco/adf-core';
import { MatSnackBarConfig } from '@angular/material';
import { FormBuilder, FormGroup, FormControl } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: './notifications.component.html',
styleUrls: ['./notifications.component.scss']
})
export class NotificationsComponent implements OnInit {
export class NotificationsComponent implements OnInit, OnDestroy {
message = 'I ♥️ ADF';
withAction = false;
@@ -55,6 +57,8 @@ export class NotificationsComponent implements OnInit {
defaultDuration = 20000;
private onDestroy$ = new Subject<boolean>();
constructor(private notificationService: NotificationService,
private formBuilder: FormBuilder) {
this.snackBarConfig.duration = this.defaultDuration;
@@ -69,10 +73,15 @@ export class NotificationsComponent implements OnInit {
});
this.configForm.valueChanges
.subscribe((configFormValues) =>
.pipe(takeUntil(this.onDestroy$))
.subscribe(configFormValues =>
this.setSnackBarConfig(configFormValues)
);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
setSnackBarConfig(configFormValues: any) {

View File

@@ -48,7 +48,9 @@ export class DemoPermissionComponent implements OnInit {
}
});
}
this.nodeService.getNode(this.nodeId, {include: ['permissions'] }).subscribe( (currentNode: MinimalNodeEntryEntity) => {
this.nodeService
.getNode(this.nodeId, {include: ['permissions'] })
.subscribe( (currentNode: MinimalNodeEntryEntity) => {
this.toggleStatus = currentNode.permissions.isInheritanceEnabled;
});
}
@@ -63,9 +65,12 @@ export class DemoPermissionComponent implements OnInit {
}
openAddPermissionDialog(event: Event) {
this.nodePermissionDialogService.updateNodePermissionByDialog(this.nodeId).subscribe(
this.nodePermissionDialogService
.updateNodePermissionByDialog(this.nodeId)
.subscribe(
() => this.displayPermissionComponent.reload(),
(error) => this.showErrorMessage(error));
(error) => this.showErrorMessage(error)
);
}
showErrorMessage(error) {

View File

@@ -15,17 +15,18 @@
* limitations under the License.
*/
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl, AbstractControl } from '@angular/forms';
import { ActivatedRoute, Params } from '@angular/router';
import { debounceTime } from 'rxjs/operators';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
@Component({
templateUrl: './process-list-demo.component.html',
styleUrls: [`./process-list-demo.component.scss`]
})
export class ProcessListDemoComponent implements OnInit {
export class ProcessListDemoComponent implements OnInit, OnDestroy {
DEFAULT_SIZE = 20;
@@ -54,6 +55,8 @@ export class ProcessListDemoComponent implements OnInit {
{value: 'created-desc', title: 'Created (desc)'}
];
private onDestroy$ = new Subject<boolean>();
constructor(private route: ActivatedRoute,
private formBuilder: FormBuilder) {
}
@@ -72,6 +75,11 @@ export class ProcessListDemoComponent implements OnInit {
this.buildForm();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
buildForm() {
this.processListForm = this.formBuilder.group({
processAppId: new FormControl(this.appId, [Validators.pattern('^[0-9]*$'), Validators.min(this.minValue)]),
@@ -84,10 +92,9 @@ export class ProcessListDemoComponent implements OnInit {
});
this.processListForm.valueChanges
.pipe(
debounceTime(500)
)
.subscribe((processFilter) => {
.pipe(takeUntil(this.onDestroy$))
.pipe(debounceTime(500))
.subscribe(processFilter => {
if (this.isFormValid()) {
this.filterProcesses(processFilter);
}

View File

@@ -15,32 +15,25 @@
* limitations under the License.
*/
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-form-node-viewer',
templateUrl: './form-node-viewer.component.html',
styleUrls: ['./form-node-viewer.component.css']
})
export class FormNodeViewerComponent implements OnInit, OnDestroy {
export class FormNodeViewerComponent implements OnInit {
nodeId: string;
private sub: Subscription;
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.sub = this.route.params.subscribe((params) => {
this.route.params.subscribe((params) => {
this.nodeId = params['id'];
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}

View File

@@ -15,9 +15,8 @@
* limitations under the License.
*/
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { Params } from '@angular/router/src/shared';
@Component({
@@ -25,23 +24,16 @@ import { Params } from '@angular/router/src/shared';
templateUrl: './form-viewer.component.html',
styleUrls: ['./form-viewer.component.css']
})
export class FormViewerComponent implements OnInit, OnDestroy {
export class FormViewerComponent implements OnInit {
taskId: string;
private sub: Subscription;
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.sub = this.route.params.subscribe((params: Params) => {
this.route.params.subscribe((params: Params) => {
this.taskId = params['id'];
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}

View File

@@ -22,7 +22,8 @@ import { UploadService } from '@alfresco/adf-core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { AppConfigService } from '@alfresco/adf-core';
import { PreviewService } from '../../services/preview.service';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export function processUploadServiceFactory(api: AlfrescoApiService, config: AppConfigService) {
return new ProcessUploadService(api, config);
@@ -51,7 +52,7 @@ export class ProcessAttachmentsComponent implements OnInit, OnChanges, OnDestroy
processInstance: ProcessInstance;
private subscriptions: Subscription[] = [];
private onDestroy$ = new Subject<boolean>();
constructor(
private uploadService: UploadService,
@@ -60,11 +61,9 @@ export class ProcessAttachmentsComponent implements OnInit, OnChanges, OnDestroy
) {}
ngOnInit() {
this.subscriptions.push(
this.uploadService.fileUploadComplete.subscribe(
(value) => this.onFileUploadComplete(value.data)
)
);
this.uploadService.fileUploadComplete
.pipe(takeUntil(this.onDestroy$))
.subscribe(value => this.onFileUploadComplete(value.data));
}
ngOnChanges() {
@@ -77,8 +76,8 @@ export class ProcessAttachmentsComponent implements OnInit, OnChanges, OnDestroy
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onFileUploadComplete(content: any) {

View File

@@ -35,7 +35,7 @@ import {
UserProcessInstanceFilterRepresentation
} from '@alfresco/js-api';
import {
FORM_FIELD_VALIDATORS, FormEvent, FormFieldEvent, FormRenderingService, FormService,
FORM_FIELD_VALIDATORS, FormRenderingService, FormService,
DynamicTableRow, ValidateDynamicTableRowEvent, AppConfigService, PaginationComponent, UserPreferenceValues
} from '@alfresco/adf-core';
@@ -57,12 +57,13 @@ import {
TaskListComponent
} from '@alfresco/adf-process-services';
import { LogService } from '@alfresco/adf-core';
import { AlfrescoApiService, UserPreferencesService, ValidateFormEvent } from '@alfresco/adf-core';
import { Subscription } from 'rxjs';
import { AlfrescoApiService, UserPreferencesService } from '@alfresco/adf-core';
import { Subject } from 'rxjs';
import { /*CustomEditorComponent*/ CustomStencil01 } from './custom-editor/custom-editor.component';
import { DemoFieldValidator } from './demo-field-validator';
import { PreviewService } from '../../services/preview.service';
import { Location } from '@angular/common';
import { takeUntil } from 'rxjs/operators';
const currentProcessIdNew = '__NEW__';
const currentTaskIdNew = '__NEW__';
@@ -160,7 +161,7 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
new DemoFieldValidator()
];
private subscriptions: Subscription[] = [];
private onDestroy$ = new Subject<boolean>();
constructor(private elementRef: ElementRef,
private route: ActivatedRoute,
@@ -184,17 +185,28 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
// Uncomment this line to map 'custom_stencil_01' to local editor component
formRenderingService.setComponentTypeResolver('custom_stencil_01', () => CustomStencil01, true);
this.subscriptions.push(
formService.formLoaded.subscribe((formEvent: FormEvent) => {
formService.formLoaded
.pipe(takeUntil(this.onDestroy$))
.subscribe(formEvent => {
this.logService.log(`Form loaded: ${formEvent.form.id}`);
}),
formService.formFieldValueChanged.subscribe((formFieldEvent: FormFieldEvent) => {
});
formService.formFieldValueChanged
.pipe(takeUntil(this.onDestroy$))
.subscribe(formFieldEvent => {
this.logService.log(`Field value changed. Form: ${formFieldEvent.form.id}, Field: ${formFieldEvent.field.id}, Value: ${formFieldEvent.field.value}`);
}),
this.preferenceService.select(UserPreferenceValues.PaginationSize).subscribe((pageSize) => {
});
this.preferenceService
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntil(this.onDestroy$))
.subscribe((pageSize) => {
this.paginationPageSize = pageSize;
}),
formService.validateDynamicTableRow.subscribe(
});
formService.validateDynamicTableRow
.pipe(takeUntil(this.onDestroy$))
.subscribe(
(validateDynamicTableRowEvent: ValidateDynamicTableRowEvent) => {
const row: DynamicTableRow = validateDynamicTableRowEvent.row;
if (row && row.value && row.value.name === 'admin') {
@@ -203,20 +215,25 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
validateDynamicTableRowEvent.preventDefault();
}
}
),
formService.formContentClicked.subscribe((content) => {
this.showContentPreview(content);
}),
formService.validateForm.subscribe((validateFormEvent: ValidateFormEvent) => {
this.logService.log('Error form:' + validateFormEvent.errorsField);
})
);
formService.formContentClicked
.pipe(takeUntil(this.onDestroy$))
.subscribe((content) => {
this.showContentPreview(content);
});
formService.validateForm
.pipe(takeUntil(this.onDestroy$))
.subscribe(validateFormEvent => {
this.logService.log('Error form:' + validateFormEvent.errorsField);
});
// Uncomment this block to see form event handling in action
/*
formService.formEvents.subscribe((event: Event) => {
formService.formEvents
.pipe(takeUntil(this.onDestroy$))
.subscribe((event: Event) => {
this.logService.log('Event fired:' + event.type);
this.logService.log('Event Target:' + event.target);
});
@@ -247,8 +264,8 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onTaskFilterClick(filter: FilterRepresentationModel): void {

View File

@@ -19,12 +19,13 @@ import { Component, Input, OnChanges, OnInit, ViewChild, OnDestroy } from '@angu
import {
TaskListService,
TaskAttachmentListComponent,
TaskDetailsModel,
TaskUploadService
TaskUploadService,
TaskDetailsModel
} from '@alfresco/adf-process-services';
import { UploadService, AlfrescoApiService, AppConfigService, FileUploadCompleteEvent } from '@alfresco/adf-core';
import { UploadService, AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
import { PreviewService } from '../../services/preview.service';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export function taskUploadServiceFactory(api: AlfrescoApiService, config: AppConfigService) {
return new TaskUploadService(api, config);
@@ -51,9 +52,9 @@ export class TaskAttachmentsComponent implements OnInit, OnChanges, OnDestroy {
@Input()
taskId: string;
taskDetails: any;
taskDetails: TaskDetailsModel;
private subscriptions: Subscription[] = [];
private onDestroy$ = new Subject<boolean>();
constructor(
private uploadService: UploadService,
@@ -62,25 +63,22 @@ export class TaskAttachmentsComponent implements OnInit, OnChanges, OnDestroy {
}
ngOnInit() {
this.subscriptions.push(
this.uploadService.fileUploadComplete.subscribe(
(fileUploadCompleteEvent: FileUploadCompleteEvent) => this.onFileUploadComplete(fileUploadCompleteEvent.data)
)
);
this.uploadService.fileUploadComplete
.pipe(takeUntil(this.onDestroy$))
.subscribe(event => this.onFileUploadComplete(event.data));
}
ngOnChanges() {
if (this.taskId) {
this.activitiTaskList.getTaskDetails(this.taskId)
.subscribe((taskDetails: TaskDetailsModel) => {
this.taskDetails = taskDetails;
});
this.activitiTaskList
.getTaskDetails(this.taskId)
.subscribe(taskDetails => this.taskDetails = taskDetails);
}
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onFileUploadComplete(content: any) {

View File

@@ -20,7 +20,8 @@ import { Router, ActivatedRoute, Params } from '@angular/router';
import { NodePaging, Pagination, ResultSetPaging } from '@alfresco/js-api';
import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
import { UserPreferencesService, SearchService, AppConfigService } from '@alfresco/adf-core';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-search-result-component',
@@ -38,7 +39,7 @@ export class SearchResultComponent implements OnInit, OnDestroy {
sorting = ['name', 'asc'];
private subscriptions: Subscription[] = [];
private onDestroy$ = new Subject<boolean>();
constructor(public router: Router,
private config: AppConfigService,
@@ -55,19 +56,21 @@ export class SearchResultComponent implements OnInit, OnDestroy {
this.sorting = this.getSorting();
this.subscriptions.push(
this.queryBuilder.updated.subscribe(() => {
this.queryBuilder.updated
.pipe(takeUntil(this.onDestroy$))
.subscribe(() => {
this.sorting = this.getSorting();
this.isLoading = true;
}),
});
this.queryBuilder.executed.subscribe((resultSetPaging: ResultSetPaging) => {
this.queryBuilder.executed
.pipe(takeUntil(this.onDestroy$))
.subscribe((resultSetPaging: ResultSetPaging) => {
this.queryBuilder.paging.skipCount = 0;
this.onSearchResultLoaded(resultSetPaging);
this.isLoading = false;
})
);
});
if (this.route) {
this.route.params.forEach((params: Params) => {
@@ -102,8 +105,8 @@ export class SearchResultComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onSearchResultLoaded(resultSetPaging: ResultSetPaging) {

View File

@@ -15,11 +15,12 @@
* limitations under the License.
*/
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl, AbstractControl } from '@angular/forms';
import { ActivatedRoute, Params } from '@angular/router';
import { debounceTime } from 'rxjs/operators';
import { debounceTime, takeUntil } from 'rxjs/operators';
import moment from 'moment-es6';
import { Subject } from 'rxjs';
@Component({
selector: 'app-task-list-demo',
@@ -27,7 +28,7 @@ import moment from 'moment-es6';
styleUrls: [`./task-list-demo.component.scss`]
})
export class TaskListDemoComponent implements OnInit {
export class TaskListDemoComponent implements OnInit, OnDestroy {
DEFAULT_SIZE = 20;
taskListForm: FormGroup;
@@ -75,6 +76,8 @@ export class TaskListDemoComponent implements OnInit {
{value: 'due-desc', title: 'Due (desc)'}
];
private onDestroy$ = new Subject<boolean>();
constructor(private route: ActivatedRoute,
private formBuilder: FormBuilder) {
}
@@ -94,6 +97,11 @@ export class TaskListDemoComponent implements OnInit {
this.buildForm();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
buildForm() {
this.taskListForm = this.formBuilder.group({
taskAppId: new FormControl(this.defaultAppId, [Validators.pattern('^[0-9]*$')]),
@@ -114,9 +122,10 @@ export class TaskListDemoComponent implements OnInit {
this.taskListForm.valueChanges
.pipe(
debounceTime(500)
debounceTime(500),
takeUntil(this.onDestroy$)
)
.subscribe((taskFilter) => {
.subscribe(taskFilter => {
if (this.isFormValid()) {
this.filterTasks(taskFilter);
}

View File

@@ -15,32 +15,42 @@
* limitations under the License.
*/
import { Component, ViewChild } from '@angular/core';
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
import { UserPreferencesService, UserPreferenceValues, RestoreMessageModel, NotificationService } from '@alfresco/adf-core';
import { Router } from '@angular/router';
import { PathInfoEntity } from '@alfresco/js-api';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: './trashcan.component.html',
styleUrls: ['trashcan.component.scss']
})
export class TrashcanComponent {
export class TrashcanComponent implements OnInit, OnDestroy {
@ViewChild('documentList')
documentList: DocumentListComponent;
currentLocale;
private onDestroy$ = new Subject<boolean>();
constructor(
private preference: UserPreferencesService,
private router: Router,
private notificationService: NotificationService
) {
private notificationService: NotificationService) {
}
ngOnInit() {
this.preference
.select(UserPreferenceValues.Locale)
.subscribe((locale) => {
this.currentLocale = locale;
});
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.currentLocale = locale);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onRestore(restoreMessage: RestoreMessageModel) {

View File

@@ -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');

View File

@@ -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.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();
}
}

View File

@@ -57,7 +57,7 @@ describe('DropdownBreadcrumb', () => {
function triggerComponentChange(fakeNodeData) {
component.folderNode = fakeNodeData;
component.ngOnChanges(null);
component.ngOnChanges();
fixture.detectChanges();
}

View File

@@ -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;

View File

@@ -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,7 +95,6 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
this.form.controls['time'].disable();
}
this.subscriptions.push(
this.form.controls.time.valueChanges
.pipe(
skip(1),
@@ -104,10 +105,10 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
),
catchError((error) => {
return throwError(error);
})
}),
takeUntil(this.onDestroy$)
)
.subscribe((updates) => this.updateEntryExpiryDate(updates))
);
.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() {

View File

@@ -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(() => {
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);
}
}
}

View File

@@ -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) {

View File

@@ -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();
}
}

View File

@@ -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,14 +46,16 @@ 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) => {
this.api.nodeUpdated
.pipe(takeUntil(this.onDestroy$))
.subscribe(node => {
const row: ShareDataRow = this.context.row;
if (row) {
const { entry } = row.node;
@@ -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();
}
}

View File

@@ -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,14 +37,16 @@ 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) => {
this.api.nodeUpdated
.pipe(takeUntil(this.onDestroy$))
.subscribe(node => {
const row: ShareDataRow = this.context.row;
if (row) {
const { entry } = row.node;
@@ -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();
}
}

View File

@@ -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,14 +48,16 @@ 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) => {
this.alfrescoApiService.nodeUpdated
.pipe(takeUntil(this.onDestroy$))
.subscribe(node => {
const row: ShareDataRow = this.context.row;
if (row) {
const { entry } = row.node;
@@ -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();
}
}

View File

@@ -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)
);
}
}

View File

@@ -108,7 +108,12 @@ export class SearchControlComponent implements OnInit, OnDestroy {
private userPreferencesService: UserPreferencesService
) {
this.toggleSearch.asObservable().pipe(debounceTime(200)).subscribe(() => {
this.toggleSearch
.pipe(
debounceTime(200),
takeUntil(this.onDestroy$)
)
.subscribe(() => {
if (this.expandable) {
this.subscriptAnimationState = this.toggleAnimation();
@@ -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(() => {

View File

@@ -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();

View File

@@ -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,18 +69,16 @@ 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.queryBuilder.executed
.pipe(takeUntil(this.onDestroy$))
.subscribe(resultSetPaging => {
this.onDataLoaded(resultSetPaging);
this.searchService.dataLoaded.next(resultSetPaging);
});
@@ -87,7 +86,8 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
this.isAlive = false;
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
private updateSelectedBuckets() {

View File

@@ -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,24 +100,26 @@ 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)
);
}
@@ -130,6 +133,11 @@ export class SearchComponent implements AfterContentInit, OnChanges {
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
resetResults() {
this.cleanResults();
this.setVisibility();

View File

@@ -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,17 +79,19 @@ 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(() => {
this.siteSelect.openedChange
.pipe(takeUntil(this.onDestroy$))
.subscribe(() => {
if (this.siteSelect.panelOpen) {
this.siteSelect.panel.nativeElement.addEventListener('scroll', (event) => this.loadAllOnScroll(event));
}
@@ -98,6 +102,11 @@ export class DropdownSitesComponent implements OnInit {
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
loadAllOnScroll(event) {
if (this.isInfiniteScrollingEnabled() && this.isScrollInNextFetchArea(event)) {
this.loading = true;

View File

@@ -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() {

View File

@@ -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.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) {

View File

@@ -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() {

View File

@@ -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();
}
/**

View File

@@ -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,23 +90,28 @@ 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) => {
this.uploadService.fileDeleted
.pipe(takeUntil(this.onDestroy$))
.subscribe(objId => {
if (this.filesUploadingList) {
const file = this.filesUploadingList.find((item) => {
return item.data.entry.id === objId;

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { Component, Input, OnInit, ViewChild, OnDestroy } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
import { MatDatetimepicker, DatetimeAdapter, MAT_DATETIME_FORMATS } from '@mat-datetimepicker/core';
import { MomentDatetimeAdapter, MAT_MOMENT_DATETIME_FORMATS } from '@mat-datetimepicker/moment';
@@ -27,6 +27,8 @@ import { UserPreferencesService, UserPreferenceValues } from '../../../services/
import { MomentDateAdapter } from '../../../utils/momentDateAdapter';
import { MOMENT_DATE_FORMATS } from '../../../utils/moment-date-formats.model';
import { AppConfigService } from '../../../app-config/app-config.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
providers: [
@@ -39,7 +41,7 @@ import { AppConfigService } from '../../../app-config/app-config.service';
templateUrl: './card-view-dateitem.component.html',
styleUrls: ['./card-view-dateitem.component.scss']
})
export class CardViewDateItemComponent implements OnInit {
export class CardViewDateItemComponent implements OnInit, OnDestroy {
@Input()
property: CardViewDateItemModel;
@@ -56,6 +58,8 @@ export class CardViewDateItemComponent implements OnInit {
valueDate: Moment;
dateFormat: string;
private onDestroy$ = new Subject<boolean>();
constructor(private cardViewUpdateService: CardViewUpdateService,
private dateAdapter: DateAdapter<Moment>,
private userPreferencesService: UserPreferencesService,
@@ -64,9 +68,10 @@ export class CardViewDateItemComponent implements OnInit {
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
(<MomentDateAdapter> this.dateAdapter).overrideDisplayFormat = 'MMM DD';
@@ -75,6 +80,11 @@ export class CardViewDateItemComponent implements OnInit {
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
showProperty() {
return this.displayEmpty || !this.property.isEmpty();
}

View File

@@ -15,11 +15,13 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, Input, Output, ViewEncapsulation, OnInit, OnDestroy } from '@angular/core';
import { CommentModel } from '../models/comment.model';
import { EcmUserService } from '../userinfo/services/ecm-user.service';
import { PeopleProcessService } from '../services/people-process.service';
import { UserPreferencesService, UserPreferenceValues } from '../services/user-preferences.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-comment-list',
@@ -28,7 +30,7 @@ import { UserPreferencesService, UserPreferenceValues } from '../services/user-p
encapsulation: ViewEncapsulation.None
})
export class CommentListComponent {
export class CommentListComponent implements OnInit, OnDestroy {
/** The comments data used to populate the list. */
@Input()
@@ -39,15 +41,24 @@ export class CommentListComponent {
clickRow: EventEmitter<CommentModel> = new EventEmitter<CommentModel>();
selectedComment: CommentModel;
currentLocale;
private onDestroy$ = new Subject<boolean>();
constructor(public peopleProcessService: PeopleProcessService,
public ecmUserService: EcmUserService,
public userPreferenceService: UserPreferencesService) {
userPreferenceService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.currentLocale = locale;
});
}
ngOnInit() {
this.userPreferenceService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.currentLocale = locale);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
selectComment(comment: CommentModel): void {

View File

@@ -27,8 +27,8 @@ import { DataColumn } from '../../data/data-column.model';
import { DataRow } from '../../data/data-row.model';
import { DataTableAdapter } from '../../data/datatable-adapter';
import { AlfrescoApiService } from '../../../services/alfresco-api.service';
import { Subscription, BehaviorSubject } from 'rxjs';
import { Node } from '@alfresco/js-api';
import { BehaviorSubject, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-datatable-cell',
@@ -77,13 +77,15 @@ export class DataTableCellComponent implements OnInit, OnDestroy {
@Input()
tooltip: string;
private sub: Subscription;
protected onDestroy$ = new Subject<boolean>();
constructor(protected alfrescoApiService: AlfrescoApiService) {}
ngOnInit() {
this.updateValue();
this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => {
this.alfrescoApiService.nodeUpdated
.pipe(takeUntil(this.onDestroy$))
.subscribe(node => {
if (this.row) {
if (this.row['node'].entry.id === node.id) {
this.row['node'].entry = node;
@@ -107,9 +109,7 @@ export class DataTableCellComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
if (this.sub) {
this.sub.unsubscribe();
this.sub = null;
}
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -23,6 +23,7 @@ import {
} from '../../../services/user-preferences.service';
import { AlfrescoApiService } from '../../../services/alfresco-api.service';
import { AppConfigService } from '../../../app-config/app-config.service';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-date-cell',
@@ -75,9 +76,8 @@ export class DateCellComponent extends DataTableCellComponent {
if (userPreferenceService) {
userPreferenceService
.select(UserPreferenceValues.Locale)
.subscribe((locale) => {
this.currentLocale = locale;
});
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.currentLocale = locale);
}
}
}

View File

@@ -17,7 +17,7 @@
/* tslint:disable:component-selector */
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
import { DatetimeAdapter, MAT_DATETIME_FORMATS } from '@mat-datetimepicker/core';
import { MomentDatetimeAdapter, MAT_MOMENT_DATETIME_FORMATS } from '@mat-datetimepicker/moment';
@@ -28,6 +28,8 @@ import { MomentDateAdapter } from '../../../../utils/momentDateAdapter';
import { MOMENT_DATE_FORMATS } from '../../../../utils/moment-date-formats.model';
import { FormService } from './../../../services/form.service';
import { WidgetComponent } from './../widget.component';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
providers: [
@@ -41,12 +43,14 @@ import { WidgetComponent } from './../widget.component';
styleUrls: ['./date-time.widget.scss'],
encapsulation: ViewEncapsulation.None
})
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
minDate: Moment;
maxDate: Moment;
displayDate: Moment;
private onDestroy$ = new Subject<boolean>();
constructor(public formService: FormService,
private dateAdapter: DateAdapter<Moment>,
private userPreferencesService: UserPreferencesService) {
@@ -54,9 +58,10 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
const momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat;
@@ -73,6 +78,11 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
this.displayDate = moment(this.field.value);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onDateChanged(newDateValue) {
if (newDateValue && newDateValue.value) {
this.field.value = newDateValue.value.format(this.field.dateDisplayFormat);

View File

@@ -20,12 +20,14 @@
import { UserPreferencesService, UserPreferenceValues } from '../../../../services/user-preferences.service';
import { MomentDateAdapter } from '../../../../utils/momentDateAdapter';
import { MOMENT_DATE_FORMATS } from '../../../../utils/moment-date-formats.model';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
import moment from 'moment-es6';
import { Moment } from 'moment';
import { FormService } from './../../../services/form.service';
import { baseHost, WidgetComponent } from './../widget.component';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'date-widget',
@@ -37,7 +39,7 @@ import { baseHost, WidgetComponent } from './../widget.component';
host: baseHost,
encapsulation: ViewEncapsulation.None
})
export class DateWidgetComponent extends WidgetComponent implements OnInit {
export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
DATE_FORMAT = 'DD/MM/YYYY';
@@ -45,6 +47,8 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit {
maxDate: Moment;
displayDate: Moment;
private onDestroy$ = new Subject<boolean>();
constructor(public formService: FormService,
private dateAdapter: DateAdapter<Moment>,
private userPreferencesService: UserPreferencesService) {
@@ -52,9 +56,10 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit {
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
const momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat;
@@ -71,6 +76,11 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit {
this.displayDate = moment(this.field.value);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onDateChanged(newDateValue) {
if (newDateValue && newDateValue.value) {
this.field.value = newDateValue.value.format(this.field.dateDisplayFormat);

View File

@@ -21,13 +21,15 @@ import { UserPreferencesService, UserPreferenceValues } from '../../../../../../
import { MomentDateAdapter } from '../../../../../../utils/momentDateAdapter';
import { MOMENT_DATE_FORMATS } from '../../../../../../utils/moment-date-formats.model';
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS, MatDatepickerInputEvent } from '@angular/material';
import moment from 'moment-es6';
import { Moment } from 'moment';
import { DynamicTableColumn } from './../../dynamic-table-column.model';
import { DynamicTableRow } from './../../dynamic-table-row.model';
import { DynamicTableModel } from './../../dynamic-table.widget.model';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-date-editor',
@@ -37,7 +39,7 @@ import { DynamicTableModel } from './../../dynamic-table.widget.model';
{provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS}],
styleUrls: ['./date.editor.scss']
})
export class DateEditorComponent implements OnInit {
export class DateEditorComponent implements OnInit, OnDestroy {
DATE_FORMAT: string = 'DD-MM-YYYY';
@@ -55,14 +57,17 @@ export class DateEditorComponent implements OnInit {
minDate: Moment;
maxDate: Moment;
private onDestroy$ = new Subject<boolean>();
constructor(private dateAdapter: DateAdapter<Moment>,
private userPreferencesService: UserPreferencesService) {
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
const momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
momentDateAdapter.overrideDisplayFormat = this.DATE_FORMAT;
@@ -70,6 +75,11 @@ export class DateEditorComponent implements OnInit {
this.value = moment(this.table.getCellValue(this.row, this.column), this.DATE_FORMAT);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onDateChanged(newDateValue: MatDatepickerInputEvent<any> | HTMLInputElement) {
if (newDateValue && newDateValue.value) {
/* validates the user inputs */

View File

@@ -20,7 +20,7 @@
import { UserPreferencesService, UserPreferenceValues } from '../../../../../../services/user-preferences.service';
import { MomentDateAdapter } from '../../../../../../utils/momentDateAdapter';
import { MOMENT_DATE_FORMATS } from '../../../../../../utils/moment-date-formats.model';
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
import moment from 'moment-es6';
import { Moment } from 'moment';
@@ -29,6 +29,8 @@ import { DynamicTableRow } from './../../dynamic-table-row.model';
import { DynamicTableModel } from './../../dynamic-table.widget.model';
import { DatetimeAdapter, MAT_DATETIME_FORMATS } from '@mat-datetimepicker/core';
import { MomentDatetimeAdapter, MAT_MOMENT_DATETIME_FORMATS } from '@mat-datetimepicker/moment';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-datetime-editor',
@@ -41,7 +43,7 @@ import { MomentDatetimeAdapter, MAT_MOMENT_DATETIME_FORMATS } from '@mat-datetim
],
styleUrls: ['./datetime.editor.scss']
})
export class DateTimeEditorComponent implements OnInit {
export class DateTimeEditorComponent implements OnInit, OnDestroy {
DATE_TIME_FORMAT: string = 'DD/MM/YYYY HH:mm';
@@ -59,14 +61,17 @@ export class DateTimeEditorComponent implements OnInit {
minDate: Moment;
maxDate: Moment;
private onDestroy$ = new Subject<boolean>();
constructor(private dateAdapter: DateAdapter<Moment>,
private userPreferencesService: UserPreferencesService) {
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
const momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
momentDateAdapter.overrideDisplayFormat = this.DATE_TIME_FORMAT;
@@ -74,6 +79,11 @@ export class DateTimeEditorComponent implements OnInit {
this.value = moment(this.table.getCellValue(this.row, this.column), this.DATE_TIME_FORMAT);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onDateChanged(newDateValue) {
if (newDateValue && newDateValue.value) {
const newValue = moment(newDateValue.value, this.DATE_TIME_FORMAT);

View File

@@ -17,7 +17,7 @@
import {
Component, EventEmitter,
Input, OnInit, Output, TemplateRef, ViewEncapsulation
Input, OnInit, Output, TemplateRef, ViewEncapsulation, OnDestroy
} from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router, ActivatedRoute, Params } from '@angular/router';
@@ -36,6 +36,8 @@ import {
} from '../../app-config/app-config.service';
import { OauthConfigModel } from '../../models/oauth-config.model';
import { DomSanitizer } from '@angular/platform-browser';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
enum LoginSteps {
Landing = 0,
@@ -57,7 +59,7 @@ interface ValidationMessage {
class: 'adf-login'
}
})
export class LoginComponent implements OnInit {
export class LoginComponent implements OnInit, OnDestroy {
isPasswordShow: boolean = false;
/**
@@ -127,6 +129,7 @@ export class LoginComponent implements OnInit {
data: any;
private _message: { [id: string]: { [id: string]: ValidationMessage } };
private onDestroy$ = new Subject<boolean>();
/**
* Constructor
@@ -175,7 +178,14 @@ export class LoginComponent implements OnInit {
this.initFormFieldsDefault();
this.initFormFieldsMessagesDefault();
}
this.form.valueChanges.subscribe((data) => this.onValueChanged(data));
this.form.valueChanges
.pipe(takeUntil(this.onDestroy$))
.subscribe(data => this.onValueChanged(data));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
submit() {

View File

@@ -24,12 +24,13 @@ import {
} from '@angular/core';
import { PaginatedComponent } from './paginated-component.interface';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { PaginationComponentInterface } from './pagination-component.interface';
import { PaginationModel } from '../models/pagination.model';
import { RequestPaginationModel } from '../models/request-pagination.model';
import { UserPreferencesService, UserPreferenceValues } from '../services/user-preferences.service';
import { Pagination } from '@alfresco/js-api';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-infinite-pagination',
@@ -48,13 +49,16 @@ export class InfinitePaginationComponent implements OnInit, OnDestroy, Paginatio
});
_target: PaginatedComponent;
private onDestroy$ = new Subject<boolean>();
/** Component that provides custom pagination support. */
@Input()
set target(target: PaginatedComponent) {
if (target) {
this._target = target;
this.paginationSubscription = target.pagination.subscribe((pagination: PaginationModel) => {
target.pagination
.pipe(takeUntil(this.onDestroy$))
.subscribe(pagination => {
this.isLoading = false;
this.pagination = pagination;
@@ -90,14 +94,15 @@ export class InfinitePaginationComponent implements OnInit, OnDestroy, Paginatio
merge: true
};
private paginationSubscription: Subscription;
constructor(private cdr: ChangeDetectorRef,
private userPreferencesService: UserPreferencesService) {
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.PaginationSize).subscribe((pageSize: number) => {
this.userPreferencesService
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntil(this.onDestroy$))
.subscribe((pageSize: number) => {
this.pageSize = this.pageSize || pageSize;
this.requestPaginationModel.maxItems = this.pageSize;
});
@@ -127,8 +132,7 @@ export class InfinitePaginationComponent implements OnInit, OnDestroy, Paginatio
}
ngOnDestroy() {
if (this.paginationSubscription) {
this.paginationSubscription.unsubscribe();
}
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -23,9 +23,10 @@ import {
import { Pagination } from '@alfresco/js-api';
import { PaginatedComponent } from './paginated-component.interface';
import { PaginationComponentInterface } from './pagination-component.interface';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { PaginationModel } from '../models/pagination.model';
import { UserPreferencesService, UserPreferenceValues } from '../services/user-preferences.service';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-pagination',
@@ -82,22 +83,25 @@ export class PaginationComponent implements OnInit, OnDestroy, PaginationCompone
@Output()
prevPage: EventEmitter<PaginationModel> = new EventEmitter<PaginationModel>();
private paginationSubscription: Subscription;
private onDestroy$ = new Subject<boolean>();
constructor(private cdr: ChangeDetectorRef, private userPreferencesService: UserPreferencesService) {
this.userPreferencesService.select(UserPreferenceValues.PaginationSize).subscribe((pagSize) => {
this.pagination.maxItems = pagSize;
});
}
ngOnInit() {
this.userPreferencesService
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntil(this.onDestroy$))
.subscribe(pagSize => this.pagination.maxItems = pagSize);
if (!this.supportedPageSizes) {
this.supportedPageSizes = this.userPreferencesService.supportedPageSizes;
}
if (this.target) {
this.paginationSubscription = this.target.pagination.subscribe((pagination: PaginationModel) => {
this.target.pagination
.pipe(takeUntil(this.onDestroy$))
.subscribe(pagination => {
if (pagination.count === 0 && !this.isFirstPage) {
this.goPrevious();
}
@@ -217,6 +221,11 @@ export class PaginationComponent implements OnInit, OnDestroy, PaginationCompone
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
handlePaginationEvent(action: string, params: PaginationModel) {
const {
NEXT_PAGE,
@@ -258,10 +267,4 @@ export class PaginationComponent implements OnInit, OnDestroy, PaginationCompone
this.target.updatePagination(params);
}
}
ngOnDestroy() {
if (this.paginationSubscription) {
this.paginationSubscription.unsubscribe();
}
}
}

View File

@@ -16,15 +16,17 @@
*/
import { DatePipe } from '@angular/common';
import { Pipe, PipeTransform } from '@angular/core';
import { Pipe, PipeTransform, OnDestroy } from '@angular/core';
import { AppConfigService } from '../app-config/app-config.service';
import { UserPreferencesService, UserPreferenceValues } from '../services/user-preferences.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Pipe({
name: 'adfLocalizedDate',
pure: false
})
export class LocalizedDatePipe implements PipeTransform {
export class LocalizedDatePipe implements PipeTransform, OnDestroy {
static DEFAULT_LOCALE = 'en-US';
static DEFAULT_DATE_FORMAT = 'mediumDate';
@@ -32,11 +34,16 @@ export class LocalizedDatePipe implements PipeTransform {
defaultLocale: string = LocalizedDatePipe.DEFAULT_LOCALE;
defaultFormat: string = LocalizedDatePipe.DEFAULT_DATE_FORMAT;
private onDestroy$ = new Subject<boolean>();
constructor(public userPreferenceService?: UserPreferencesService,
public appConfig?: AppConfigService) {
if (this.userPreferenceService) {
this.userPreferenceService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.userPreferenceService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => {
if (locale) {
this.defaultLocale = locale;
}
@@ -55,4 +62,9 @@ export class LocalizedDatePipe implements PipeTransform {
return datePipe.transform(value, actualFormat);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -16,15 +16,17 @@
*/
import moment from 'moment-es6';
import { Pipe, PipeTransform } from '@angular/core';
import { Pipe, PipeTransform, OnDestroy } from '@angular/core';
import { AppConfigService } from '../app-config/app-config.service';
import { UserPreferenceValues, UserPreferencesService } from '../services/user-preferences.service';
import { DatePipe } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Pipe({
name: 'adfTimeAgo'
})
export class TimeAgoPipe implements PipeTransform {
export class TimeAgoPipe implements PipeTransform, OnDestroy {
static DEFAULT_LOCALE = 'en-US';
static DEFAULT_DATE_TIME_FORMAT = 'dd/MM/yyyy HH:mm';
@@ -32,9 +34,14 @@ export class TimeAgoPipe implements PipeTransform {
defaultLocale: string;
defaultDateTimeFormat: string;
private onDestroy$ = new Subject<boolean>();
constructor(public userPreferenceService: UserPreferencesService,
public appConfig: AppConfigService) {
this.userPreferenceService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.userPreferenceService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => {
this.defaultLocale = locale || TimeAgoPipe.DEFAULT_LOCALE;
});
this.defaultDateTimeFormat = this.appConfig.get<string>('dateValues.defaultDateTimeFormat', TimeAgoPipe.DEFAULT_DATE_TIME_FORMAT);
@@ -54,4 +61,9 @@ export class TimeAgoPipe implements PipeTransform {
}
return '';
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -15,13 +15,15 @@
* limitations under the License.
*/
import { AfterContentInit, ContentChild, Directive, Input, TemplateRef } from '@angular/core';
import { AfterContentInit, ContentChild, Directive, Input, TemplateRef, OnDestroy } from '@angular/core';
import { ViewerComponent } from '../components/viewer.component';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Directive({
selector: 'adf-viewer-extension'
})
export class ViewerExtensionDirective implements AfterContentInit {
export class ViewerExtensionDirective implements AfterContentInit, OnDestroy {
@ContentChild(TemplateRef)
template: any;
@@ -37,6 +39,8 @@ export class ViewerExtensionDirective implements AfterContentInit {
templateModel: any;
private onDestroy$ = new Subject<boolean>();
constructor(private viewerComponent: ViewerComponent) {
}
@@ -45,7 +49,9 @@ export class ViewerExtensionDirective implements AfterContentInit {
this.viewerComponent.extensionTemplates.push(this.templateModel);
this.viewerComponent.extensionChange.subscribe((fileExtension) => {
this.viewerComponent.extensionChange
.pipe(takeUntil(this.onDestroy$))
.subscribe(fileExtension => {
this.templateModel.isVisible = this.isVisible(fileExtension);
});
@@ -56,6 +62,11 @@ export class ViewerExtensionDirective implements AfterContentInit {
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
/**
* check if the current extension in the viewer is compatible with this extension checking against supportedExtensions
*/

View File

@@ -37,6 +37,8 @@ import { ReportParameterDetailsModel } from '../../diagram/models/report/reportP
import { ReportParametersModel } from '../../diagram/models/report/reportParameters.model';
import { ReportQuery } from '../../diagram/models/report/reportQuery.model';
import { AnalyticsService } from '../services/analytics.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-analytics-report-parameters',
@@ -80,7 +82,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
onDropdownChanged = new EventEmitter();
successReportParams = new EventEmitter();
successReportParams = new EventEmitter<ReportParametersModel>();
successParamOpt = new EventEmitter();
@@ -94,12 +96,10 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
reportName: string;
private dropDownSub;
private reportParamsSub;
private paramOpts;
reportParamQuery: ReportQuery;
private hideParameters: boolean = true;
formValidState: boolean = false;
private onDestroy$ = new Subject<boolean>();
constructor(private analyticsService: AnalyticsService,
private formBuilder: FormBuilder,
@@ -110,14 +110,22 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
}
ngOnInit() {
this.dropDownSub = this.onDropdownChanged.subscribe((field) => {
const paramDependOn: ReportParameterDetailsModel = this.reportParameters.definition.parameters.find((p) => p.dependsOn === field.id);
this.onDropdownChanged
.pipe(takeUntil(this.onDestroy$))
.subscribe((field: any) => {
const paramDependOn = this.reportParameters.definition.parameters.find(
(param) => param.dependsOn === field.id
);
if (paramDependOn) {
this.retrieveParameterOptions(this.reportParameters.definition.parameters, this.appId, this.reportId, field.value);
this.retrieveParameterOptions(
this.reportParameters.definition.parameters, this.appId, this.reportId, field.value
);
}
});
this.paramOpts = this.successReportParams.subscribe((report: ReportParametersModel) => {
this.successReportParams
.pipe(takeUntil(this.onDestroy$))
.subscribe(report => {
if (report.hasParameters()) {
this.retrieveParameterOptions(report.definition.parameters, this.appId);
this.generateFormGroupFromParameter(report.definition.parameters);
@@ -195,7 +203,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
}
public getReportParams(reportId: string) {
this.reportParamsSub = this.analyticsService.getReportParams(reportId).subscribe(
this.analyticsService.getReportParams(reportId).subscribe(
(res: ReportParametersModel) => {
this.reportParameters = res;
if (this.reportParameters.hasParameters()) {
@@ -293,11 +301,8 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
}
ngOnDestroy() {
this.dropDownSub.unsubscribe();
this.paramOpts.unsubscribe();
if (this.reportParamsSub) {
this.reportParamsSub.unsubscribe();
}
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
public editEnable() {
@@ -309,12 +314,14 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
}
public editTitle() {
this.reportParamsSub = this.analyticsService.updateReport(this.reportParameters.id, this.reportParameters.name).subscribe(
(res: ReportParametersModel) => {
this.analyticsService
.updateReport(this.reportParameters.id, this.reportParameters.name)
.subscribe(
() => {
this.editDisable();
this.edit.emit(this.reportParameters.name);
},
(err: any) => {
err => {
this.error.emit(err);
}
);

View File

@@ -18,11 +18,13 @@
/* tslint:disable:no-input-rename */
import { MOMENT_DATE_FORMATS, MomentDateAdapter, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, OnDestroy } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
import moment from 'moment-es6';
import { Moment } from 'moment';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-date-range-widget',
@@ -33,7 +35,7 @@ import { Moment } from 'moment';
styleUrls: ['./date-range.widget.scss'],
encapsulation: ViewEncapsulation.None
})
export class DateRangeWidgetComponent implements OnInit {
export class DateRangeWidgetComponent implements OnInit, OnDestroy {
public FORMAT_DATE_ACTIVITI: string = 'YYYY-MM-DD';
public SHOW_FORMAT: string = 'DD/MM/YYYY';
@@ -52,15 +54,18 @@ export class DateRangeWidgetComponent implements OnInit {
startDatePicker: Moment = moment();
endDatePicker: Moment = moment();
private onDestroy$ = new Subject<boolean>();
constructor(
private dateAdapter: DateAdapter<Moment>,
private userPreferencesService: UserPreferencesService) {
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
const momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
momentDateAdapter.overrideDisplayFormat = this.SHOW_FORMAT;
@@ -87,6 +92,11 @@ export class DateRangeWidgetComponent implements OnInit {
this.dateRange.valueChanges.subscribe(() => this.onGroupValueChanged());
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onGroupValueChanged() {
if (this.dateRange.valid) {
const dateStart = this.convertToMomentDateWithTime(this.dateRange.controls.startDate.value);

View File

@@ -56,7 +56,7 @@ describe('AttachFileCloudWidgetComponent', () => {
}
};
const contentSourceparam = {
const contentSourceParam = {
fileSource: {
name: 'mock-alf-content',
serviceId: 'alfresco-content'
@@ -130,7 +130,7 @@ describe('AttachFileCloudWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> contentSourceparam;
widget.field.params = <FormFieldMetadata> contentSourceParam;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('.adf-attach-widget__menu-upload')).not.toBeNull();
@@ -144,7 +144,7 @@ describe('AttachFileCloudWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> contentSourceparam;
widget.field.params = <FormFieldMetadata> contentSourceParam;
fixture.detectChanges();
fixture.whenStable().then(() => {
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-alfresco');

View File

@@ -88,8 +88,8 @@ describe('EditProcessFilterCloudComponent', () => {
});
it('should fetch process instance filter by id', async(() => {
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -103,8 +103,8 @@ describe('EditProcessFilterCloudComponent', () => {
}));
it('should display filter name as title', async(() => {
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-title-id');
const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-sub-title-id');
@@ -118,8 +118,8 @@ describe('EditProcessFilterCloudComponent', () => {
}));
it('should not display mat-spinner if isloading set to false', async(() => {
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-title-id');
const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-sub-title-id');
@@ -136,8 +136,8 @@ describe('EditProcessFilterCloudComponent', () => {
it('should display mat-spinner if isloading set to true', async(() => {
component.isLoading = true;
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
const matSpinnerElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-edit-process-filter-loading-margin');
@@ -150,8 +150,8 @@ describe('EditProcessFilterCloudComponent', () => {
describe('EditProcessFilter form', () => {
beforeEach(() => {
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
});
@@ -245,14 +245,17 @@ describe('EditProcessFilterCloudComponent', () => {
it('should display state drop down', async(() => {
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"] .mat-select-trigger');
stateElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const statusOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
expect(statusOptions.length).toEqual(3);
expect(statusOptions.length).toEqual(6);
});
}));
@@ -287,8 +290,8 @@ describe('EditProcessFilterCloudComponent', () => {
fixture.detectChanges();
component.filterProperties = ['appName', 'processName'];
fixture.detectChanges();
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -302,8 +305,8 @@ describe('EditProcessFilterCloudComponent', () => {
fixture.detectChanges();
component.filterProperties = [];
fixture.detectChanges();
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
fixture.whenStable().then(() => {
const stateController = component.editProcessFilterForm.get('status');
@@ -330,8 +333,8 @@ describe('EditProcessFilterCloudComponent', () => {
fixture.detectChanges();
component.filterProperties = ['appName', 'processName'];
fixture.detectChanges();
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
const appController = component.editProcessFilterForm.get('appName');
fixture.detectChanges();
@@ -343,8 +346,8 @@ describe('EditProcessFilterCloudComponent', () => {
}));
it('should display default sort properties', async(() => {
const processFilterIdchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
@@ -373,8 +376,8 @@ describe('EditProcessFilterCloudComponent', () => {
}));
component.sortProperties = ['id', 'processName', 'processDefinitionId'];
fixture.detectChanges();
const processFilterIdchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
@@ -396,8 +399,8 @@ describe('EditProcessFilterCloudComponent', () => {
describe('edit filter actions', () => {
beforeEach(() => {
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
getProcessFilterByIdSpy.and.returnValue(of(fakeFilter));
fixture.detectChanges();
});
@@ -425,9 +428,9 @@ describe('EditProcessFilterCloudComponent', () => {
});
}));
it('should emit delete event and delete the filter on click of delete button', async(() => {
it('should emit delete event and delete the filter on click of delete button', (done) => {
component.toggleFilterActions = true;
const deleteFilterSpy = spyOn(service, 'deleteFilter').and.returnValue(of());
const deleteFilterSpy = spyOn(service, 'deleteFilter').and.returnValue(of({}));
const deleteSpy: jasmine.Spy = spyOn(component.action, 'emit');
fixture.detectChanges();
@@ -442,9 +445,14 @@ describe('EditProcessFilterCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(deleteFilterSpy).toHaveBeenCalled();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(deleteSpy).toHaveBeenCalled();
done();
});
});
});
}));
it('should emit saveAs event and add filter on click saveAs button', async(() => {
component.toggleFilterActions = true;
@@ -497,8 +505,8 @@ describe('EditProcessFilterCloudComponent', () => {
fixture.detectChanges();
component.actions = ['save'];
fixture.detectChanges();
const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIDchange });
const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(component.processFilterActions).toBeDefined();
@@ -534,8 +542,8 @@ describe('EditProcessFilterCloudComponent', () => {
it('should set the correct lastModifiedTo date', (done) => {
component.appName = 'fake';
component.filterProperties = ['appName', 'processInstanceId', 'priority', 'lastModified'];
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange });
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange });
fixture.detectChanges();
const lastModifiedToControl: AbstractControl = component.editProcessFilterForm.get('lastModifiedTo');

View File

@@ -18,12 +18,11 @@
import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges, OnDestroy } from '@angular/core';
import { FormGroup, FormBuilder, AbstractControl } from '@angular/forms';
import { MatDialog, DateAdapter } from '@angular/material';
import { debounceTime, filter, takeUntil } from 'rxjs/operators';
import { debounceTime, filter, takeUntil, finalize } from 'rxjs/operators';
import { Subject } from 'rxjs';
import moment from 'moment-es6';
import { Moment } from 'moment';
import { ApplicationInstanceModel } from '../../../app/models/application-instance.model';
import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service';
import { ProcessFilterCloudModel, ProcessFilterProperties, ProcessFilterAction, ProcessFilterOptions } from '../models/process-filter-cloud.model';
import { TranslationService, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
@@ -120,9 +119,10 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
private appsProcessCloudService: AppsProcessCloudService) { }
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
}
ngOnChanges(changes: SimpleChanges) {
@@ -153,15 +153,14 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
*/
retrieveProcessFilterAndBuildForm() {
this.isLoading = true;
this.processFilterCloudService.getFilterById(this.appName, this.id)
.pipe(takeUntil(this.onDestroy$)).subscribe((response) => {
this.isLoading = false;
this.processFilterCloudService
.getFilterById(this.appName, this.id)
.pipe(finalize(() => this.isLoading = false))
.subscribe(response => {
this.processFilter = new ProcessFilterCloudModel(response);
this.processFilterProperties = this.createAndFilterProperties();
this.processFilterActions = this.createAndFilterActions();
this.buildForm(this.processFilterProperties);
}, (error) => {
this.isLoading = false;
});
}
@@ -170,7 +169,11 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
*/
onFilterChange() {
this.editProcessFilterForm.valueChanges
.pipe(debounceTime(500), filter(() => this.isFormValid()))
.pipe(
debounceTime(500),
filter(() => this.isFormValid()),
takeUntil(this.onDestroy$)
)
.subscribe((formValues: ProcessFilterCloudModel) => {
this.setLastModifiedToFilter(formValues);
this.changedProcessFilter = new ProcessFilterCloudModel(Object.assign({}, this.processFilter, formValues));
@@ -292,8 +295,9 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
}
getRunningApplications() {
this.appsProcessCloudService.getDeployedApplicationsByStatus(EditProcessFilterCloudComponent.APP_RUNNING_STATUS)
.pipe(takeUntil(this.onDestroy$)).subscribe((applications: ApplicationInstanceModel[]) => {
this.appsProcessCloudService
.getDeployedApplicationsByStatus(EditProcessFilterCloudComponent.APP_RUNNING_STATUS)
.subscribe(applications => {
if (applications && applications.length > 0) {
applications.map((application) => {
this.applicationNames.push({ label: application.name, value: application.name });
@@ -316,8 +320,9 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
* Save a process instance filter
*/
save(saveAction: ProcessFilterAction) {
this.processFilterCloudService.updateFilter(this.changedProcessFilter)
.pipe(takeUntil(this.onDestroy$)).subscribe((res) => {
this.processFilterCloudService
.updateFilter(this.changedProcessFilter)
.subscribe(() => {
saveAction.filter = this.changedProcessFilter;
this.action.emit(saveAction);
this.formHasBeenChanged = this.compareFilters(this.changedProcessFilter, this.processFilter);
@@ -328,8 +333,9 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
* Delete a process instance filter
*/
delete(deleteAction: ProcessFilterAction) {
this.processFilterCloudService.deleteFilter(this.processFilter)
.pipe(takeUntil(this.onDestroy$)).subscribe((res) => {
this.processFilterCloudService
.deleteFilter(this.processFilter)
.subscribe(() => {
deleteAction.filter = this.processFilter;
this.action.emit(deleteAction);
});
@@ -357,8 +363,9 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
key: 'custom-' + filterKey
};
const resultFilter: ProcessFilterCloudModel = Object.assign({}, this.changedProcessFilter, newFilter);
this.processFilterCloudService.addFilter(resultFilter)
.pipe(takeUntil(this.onDestroy$)).subscribe((res) => {
this.processFilterCloudService
.addFilter(resultFilter)
.subscribe(() => {
saveAsAction.filter = resultFilter;
this.action.emit(saveAsAction);
});

View File

@@ -50,7 +50,7 @@ export class ProcessFilterCloudService {
} else if (!this.hasProcessFilters(preferences, key)) {
return this.createProcessFilters(appName, key, this.defaultProcessFilters(appName));
} else {
return of(this.findFiltersByKeyInPrefrences(preferences, key));
return of(this.findFiltersByKeyInPreferences(preferences, key));
}
}),
catchError((err) => this.handleProcessError(err))
@@ -97,7 +97,7 @@ export class ProcessFilterCloudService {
/**
* Adds a new process instance filter
* @param filter The new filter to add
* @returns Obervable of process instance filters with newly added filter
* @returns Observable of process instance filters with newly added filter
*/
addFilter(newFilter: ProcessFilterCloudModel): Observable<ProcessFilterCloudModel[]> {
const key: string = this.prepareKey(newFilter.appName);
@@ -233,7 +233,7 @@ export class ProcessFilterCloudService {
* @param appName Name of the target app
* @returns Array of ProcessFilterCloudModel
*/
private findFiltersByKeyInPrefrences(preferences: any, key: string): ProcessFilterCloudModel[] {
private findFiltersByKeyInPreferences(preferences: any, key: string): ProcessFilterCloudModel[] {
const result = preferences.find((filter: any) => { return filter.entry.key === key; });
return result && result.entry ? JSON.parse(result.entry.value) : [];
}

View File

@@ -25,7 +25,7 @@ describe('Activiti ProcessList Cloud Service', () => {
let service: ProcessListCloudService;
let alfrescoApiMock: AlfrescoApiServiceMock;
function returFakeProcessListResults() {
function returnFakeProcessListResults() {
return {
oauth2Auth: {
callCustomApi: () => {
@@ -70,7 +70,7 @@ describe('Activiti ProcessList Cloud Service', () => {
it('should return the processes', (done) => {
const processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName' };
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returFakeProcessListResults);
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeProcessListResults);
service.getProcessByRequest(processRequest).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();

View File

@@ -82,10 +82,10 @@ export class ProcessListCloudService extends BaseCloudService {
return property === 'appName' || property === 'sorting';
}
private buildSortingParam(sortings: ProcessListCloudSortingModel[]): string {
private buildSortingParam(models: ProcessListCloudSortingModel[]): string {
let finalSorting: string = '';
if (sortings) {
for (const sort of sortings) {
if (models) {
for (const sort of models) {
if (!finalSorting) {
finalSorting = `${sort.orderBy},${sort.direction}`;
} else {

View File

@@ -16,9 +16,9 @@
*/
import { FormControl } from '@angular/forms';
import { Component, OnInit, Output, EventEmitter, ViewEncapsulation, Input, ViewChild, ElementRef, SimpleChanges, OnChanges } from '@angular/core';
import { Observable, of, BehaviorSubject } from 'rxjs';
import { switchMap, debounceTime, distinctUntilChanged, mergeMap, tap, filter, map } from 'rxjs/operators';
import { Component, OnInit, Output, EventEmitter, ViewEncapsulation, Input, ViewChild, ElementRef, SimpleChanges, OnChanges, OnDestroy } from '@angular/core';
import { Observable, of, BehaviorSubject, Subject } from 'rxjs';
import { switchMap, debounceTime, distinctUntilChanged, mergeMap, tap, filter, map, takeUntil } from 'rxjs/operators';
import { FullNamePipe, IdentityUserModel, IdentityUserService, LogService } from '@alfresco/adf-core';
import { trigger, state, style, transition, animate } from '@angular/animations';
@@ -39,7 +39,7 @@ import { trigger, state, style, transition, animate } from '@angular/animations'
encapsulation: ViewEncapsulation.None
})
export class PeopleCloudComponent implements OnInit, OnChanges {
export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
static MODE_SINGLE = 'single';
static MODE_MULTIPLE = 'multiple';
@@ -98,15 +98,13 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
private _searchUsers: IdentityUserModel[] = [];
private selectedUsersSubject: BehaviorSubject<IdentityUserModel[]>;
private searchUsersSubject: BehaviorSubject<IdentityUserModel[]>;
private onDestroy$ = new Subject<boolean>();
selectedUsers$: Observable<IdentityUserModel[]>;
searchUsers$: Observable<IdentityUserModel[]>;
_subscriptAnimationState: string = 'enter';
clientId: string;
isFocused: boolean;
invalidUsers: IdentityUserModel[] = [];
constructor(private identityUserService: IdentityUserService, private logService: LogService) {
@@ -141,6 +139,11 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
initSubjects() {
if (this.selectedUsersSubject === undefined) {
this.selectedUsersSubject = new BehaviorSubject<IdentityUserModel[]>(this.preSelectUsers);
@@ -239,11 +242,11 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
});
}
public userExists(result: any): boolean {
public userExists(result: IdentityUserModel): boolean {
return result
&& (result.id !== undefined
|| result.username !== undefined
|| result.amil !== undefined);
|| result.email !== undefined);
}
private initSearch() {
@@ -285,8 +288,9 @@ export class PeopleCloudComponent implements OnInit, OnChanges {
} else {
return of(user);
}
})
).subscribe((user) => {
}),
takeUntil(this.onDestroy$)
).subscribe((user: any) => {
this._searchUsers.push(user);
this.searchUsersSubject.next(this._searchUsers);
});

View File

@@ -19,7 +19,7 @@ import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { MOMENT_DATE_FORMATS, MomentDateAdapter } from '@alfresco/adf-core';
import moment from 'moment-es6';
import { Moment } from 'moment';
import { Observable, Subscription } from 'rxjs';
import { Observable, Subject } from 'rxjs';
import { FormBuilder, AbstractControl, Validators, FormGroup, FormControl } from '@angular/forms';
import {
LogService,
@@ -32,6 +32,7 @@ import { PeopleCloudComponent } from './people-cloud/people-cloud.component';
import { GroupCloudComponent } from '../../../../lib/group/components/group-cloud.component';
import { TaskCloudService } from '../../services/task-cloud.service';
import { StartTaskCloudRequestModel } from '../models/start-task-cloud-request.model';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-cloud-start-task',
@@ -101,9 +102,7 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy {
private assigneeForm: AbstractControl = new FormControl('');
private groupForm: AbstractControl = new FormControl('');
private localeSub: Subscription;
private createTaskSub: Subscription;
private onDestroy$ = new Subject<boolean>();
constructor(private taskService: TaskCloudService,
private dateAdapter: DateAdapter<Moment>,
@@ -114,21 +113,17 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy {
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
this.loadCurrentUser();
this.buildForm();
}
ngOnDestroy() {
if (this.localeSub) {
this.localeSub.unsubscribe();
}
if (this.createTaskSub) {
this.createTaskSub.unsubscribe();
}
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
buildForm() {
@@ -162,7 +157,7 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy {
}
private createNewTask(newTask: StartTaskCloudRequestModel) {
this.createTaskSub = this.taskService.createNewTask(newTask, this.appName)
this.taskService.createNewTask(newTask, this.appName)
.subscribe(
(res: any) => {
this.submitted = false;

View File

@@ -70,8 +70,8 @@ describe('EditTaskFilterCloudComponent', () => {
});
it('should fetch task filter by taskId', () => {
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(getTaskFilterSpy).toHaveBeenCalled();
@@ -84,8 +84,8 @@ describe('EditTaskFilterCloudComponent', () => {
});
it('should display filter name as title', async(() => {
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-title-id');
const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-sub-title-id');
@@ -96,8 +96,8 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should not display mat-spinner if isloading set to false', async(() => {
const taskFilterIDchange = new SimpleChange(null, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange });
const taskFilterIdChange = new SimpleChange(null, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange });
fixture.detectChanges();
const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-title-id');
const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-sub-title-id');
@@ -114,8 +114,8 @@ describe('EditTaskFilterCloudComponent', () => {
it('should display mat-spinner if isloading set to true', async(() => {
component.isLoading = true;
const taskFilterIDchange = new SimpleChange(null, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange });
const taskFilterIdChange = new SimpleChange(null, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange });
fixture.detectChanges();
const matSpinnerElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-edit-task-filter-loading-margin');
@@ -128,8 +128,8 @@ describe('EditTaskFilterCloudComponent', () => {
describe('EditTaskFilter form', () => {
beforeEach(() => {
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({'id': taskFilterIdChange});
fixture.detectChanges();
});
@@ -229,8 +229,8 @@ describe('EditTaskFilterCloudComponent', () => {
getTaskFilterSpy.and.returnValue(of(fakeAllTaskFilter));
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
@@ -275,8 +275,8 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should able to build a editTaskFilter form with default properties if input is empty', async(() => {
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
component.filterProperties = [];
fixture.detectChanges();
const stateController = component.editTaskFilterForm.get('status');
@@ -299,8 +299,8 @@ describe('EditTaskFilterCloudComponent', () => {
it('should able to fetch running applications when appName property defined in the input', async(() => {
component.filterProperties = ['appName', 'processInstanceId', 'priority'];
fixture.detectChanges();
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
const appController = component.editTaskFilterForm.get('appName');
fixture.detectChanges();
fixture.whenStable().then(() => {
@@ -314,8 +314,8 @@ describe('EditTaskFilterCloudComponent', () => {
describe('sort properties', () => {
it('should display default sort properties', async(() => {
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
@@ -340,8 +340,8 @@ describe('EditTaskFilterCloudComponent', () => {
priority: '12'
}));
fixture.detectChanges();
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
@@ -361,8 +361,8 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should display default sort properties if input is empty', async(() => {
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
component.sortProperties = [];
fixture.detectChanges();
@@ -386,8 +386,8 @@ describe('EditTaskFilterCloudComponent', () => {
it('should display default filter actions', async(() => {
component.toggleFilterActions = true;
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
@@ -410,8 +410,8 @@ describe('EditTaskFilterCloudComponent', () => {
it('should display filter actions when input actions are specified', async(() => {
component.actions = ['save'];
fixture.detectChanges();
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
component.toggleFilterActions = true;
fixture.detectChanges();
@@ -430,8 +430,8 @@ describe('EditTaskFilterCloudComponent', () => {
it('should display default filter actions if input is empty', async(() => {
component.toggleFilterActions = true;
component.actions = [];
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
@@ -454,8 +454,8 @@ describe('EditTaskFilterCloudComponent', () => {
it('should set the correct lastModifiedTo date', (done) => {
component.appName = 'fake';
component.filterProperties = ['appName', 'processInstanceId', 'priority', 'lastModified'];
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
const lastModifiedToControl: AbstractControl = component.editTaskFilterForm.get('lastModifiedTo');
@@ -478,8 +478,8 @@ describe('EditTaskFilterCloudComponent', () => {
describe('edit filter actions', () => {
beforeEach(() => {
const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIDchange});
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
component.ngOnChanges({ 'id': taskFilterIdChange});
fixture.detectChanges();
});

View File

@@ -124,9 +124,10 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro
}
ngOnInit() {
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
}
ngOnChanges(changes: SimpleChanges) {
@@ -159,8 +160,11 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro
*/
onFilterChange() {
this.editTaskFilterForm.valueChanges
.pipe(debounceTime(500),
filter(() => this.isFormValid()))
.pipe(
debounceTime(500),
filter(() => this.isFormValid()),
takeUntil(this.onDestroy$)
)
.subscribe((formValues: TaskFilterCloudModel) => {
this.setLastModifiedToFilter(formValues);
this.changedTaskFilter = new TaskFilterCloudModel(Object.assign({}, this.taskFilter, formValues));
@@ -334,7 +338,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro
save(saveAction: TaskFilterAction) {
this.taskFilterCloudService.updateFilter(this.changedTaskFilter)
.pipe(takeUntil(this.onDestroy$)).subscribe((res) => {
.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
saveAction.filter = this.changedTaskFilter;
this.action.emit(saveAction);
this.formHasBeenChanged = this.compareFilters(this.changedTaskFilter, this.taskFilter);
@@ -343,7 +347,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro
delete(deleteAction: TaskFilterAction) {
this.taskFilterCloudService.deleteFilter(this.taskFilter)
.pipe(takeUntil(this.onDestroy$)).subscribe((res) => {
.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
deleteAction.filter = this.taskFilter;
this.action.emit(deleteAction);
});
@@ -369,7 +373,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro
};
const resultFilter: TaskFilterCloudModel = Object.assign({}, this.changedTaskFilter, newFilter);
this.taskFilterCloudService.addFilter(resultFilter)
.pipe(takeUntil(this.onDestroy$)).subscribe((res) => {
.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
saveAsAction.filter = resultFilter;
this.action.emit(saveAsAction);
});

View File

@@ -49,7 +49,7 @@ export class TaskFilterCloudService {
} else if (!this.hasTaskFilters(preferences, key)) {
return this.createTaskFilters(appName, key, this.defaultTaskFilters(appName));
} else {
return of(this.findFiltersByKeyInPrefrences(preferences, key));
return of(this.findFiltersByKeyInPreferences(preferences, key));
}
}),
catchError((err) => this.handleTaskError(err))
@@ -138,7 +138,7 @@ export class TaskFilterCloudService {
/**
* Adds a new task filter.
* @param filter The new filter to add
* @returns Obervable of task instance filters with newly added filter
* @returns Observable of task instance filters with newly added filter
*/
addFilter(newFilter: TaskFilterCloudModel) {
const key: string = this.prepareKey(newFilter.appName);
@@ -244,7 +244,7 @@ export class TaskFilterCloudService {
* @param appName Name of the target app
* @returns Array of TaskFilterCloudModel
*/
private findFiltersByKeyInPrefrences(preferences: any, key: string): TaskFilterCloudModel[] {
private findFiltersByKeyInPreferences(preferences: any, key: string): TaskFilterCloudModel[] {
const result = preferences.find((filter: any) => { return filter.entry.key === key; });
return result && result.entry ? JSON.parse(result.entry.value) : [];
}

View File

@@ -29,8 +29,9 @@ import {
import { TaskDetailsCloudModel, TaskStatusEnum } from '../../start-task/models/task-details-cloud.model';
import { Router } from '@angular/router';
import { TaskCloudService } from '../../services/task-cloud.service';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { NumericFieldValidator } from '../../../validators/numeric-field.validator';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-cloud-task-header',
@@ -62,7 +63,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
dateFormat: string;
dateLocale: string;
private subscriptions: Subscription[] = [];
private onDestroy$ = new Subject<boolean>();
constructor(
private taskCloudService: TaskCloudService,
@@ -80,19 +81,21 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
this.loadTaskDetailsById(this.appName, this.taskId);
}
this.subscriptions.push(this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this)));
this.cardViewUpdateService.itemUpdated$
.pipe(takeUntil(this.onDestroy$))
.subscribe(this.updateTaskDetails.bind(this));
}
loadTaskDetailsById(appName: string, taskId: string): any {
this.subscriptions.push(this.taskCloudService.getTaskById(appName, taskId).subscribe(
this.taskCloudService.getTaskById(appName, taskId).subscribe(
(taskDetails) => {
this.taskDetails = taskDetails;
if (this.taskDetails.parentTaskId) {
this.loadParentName(this.taskDetails.parentTaskId);
this.loadParentName(`${this.taskDetails.parentTaskId}`);
} else {
this.refreshData();
}
}));
});
}
private initDefaultProperties() {
@@ -220,7 +223,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
);
}
private loadParentName(taskId) {
private loadParentName(taskId: string) {
this.taskCloudService.getTaskById(this.appName, taskId)
.subscribe(
(taskDetails) => {
@@ -263,7 +266,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -15,16 +15,17 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, OnChanges, Input, SimpleChanges, Output, EventEmitter, ContentChild, AfterContentInit } from '@angular/core';
import { Component, ViewEncapsulation, OnChanges, Input, SimpleChanges, Output, EventEmitter, ContentChild, AfterContentInit, OnDestroy, OnInit } from '@angular/core';
import { AppConfigService, UserPreferencesService,
DataTableSchema, UserPreferenceValues,
PaginatedComponent, PaginationModel,
DataRowEvent, CustomEmptyContentTemplateDirective } from '@alfresco/adf-core';
import { taskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model';
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
import { BehaviorSubject } from 'rxjs';
import { BehaviorSubject, Subject } from 'rxjs';
import { TaskListCloudService } from '../services/task-list-cloud.service';
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-cloud-task-list',
@@ -33,7 +34,7 @@ import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
encapsulation: ViewEncapsulation.None
})
export class TaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent {
export class TaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit {
static PRESET_KEY = 'adf-cloud-task-list.presets';
@@ -148,14 +149,13 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
isLoading = false;
selectedInstances: any[];
private onDestroy$ = new Subject<boolean>();
constructor(private taskListCloudService: TaskListCloudService,
appConfigService: AppConfigService,
private userPreferences: UserPreferencesService) {
super(appConfigService, TaskListCloudComponent.PRESET_KEY, taskPresetsCloudDefaultModel);
this.size = userPreferences.paginationSize;
this.userPreferences.select(UserPreferenceValues.PaginationSize).subscribe((pageSize) => {
this.size = pageSize;
});
this.pagination = new BehaviorSubject<PaginationModel>(<PaginationModel> {
maxItems: this.size,
@@ -165,12 +165,24 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
}
ngOnInit() {
this.userPreferences
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntil(this.onDestroy$))
.subscribe(pageSize => this.size = pageSize);
}
ngOnChanges(changes: SimpleChanges) {
if (this.isPropertyChanged(changes)) {
this.reload();
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngAfterContentInit() {
this.createDatatableSchema();
}

View File

@@ -85,10 +85,10 @@ export class TaskListCloudService extends BaseCloudService {
return requestNode[property] !== '' && requestNode[property] !== null && requestNode[property] !== undefined;
}
private buildSortingParam(sortings: TaskListCloudSortingModel[]): string {
private buildSortingParam(models: TaskListCloudSortingModel[]): string {
let finalSorting: string = '';
if (sortings) {
for (const sort of sortings) {
if (models) {
for (const sort of models) {
if (!finalSorting) {
finalSorting = `${sort.orderBy},${sort.direction}`;
} else {

View File

@@ -16,18 +16,18 @@
*/
import { AppsProcessService, TranslationService, CustomEmptyContentTemplateDirective } from '@alfresco/adf-core';
import { AfterContentInit, Component, EventEmitter, Input, OnInit, Output, ContentChild } from '@angular/core';
import { Observable, Observer, of } from 'rxjs';
import { AfterContentInit, Component, EventEmitter, Input, OnInit, Output, ContentChild, OnDestroy } from '@angular/core';
import { Observable, Observer, of, Subject } from 'rxjs';
import { AppDefinitionRepresentationModel } from '../task-list';
import { IconModel } from './icon.model';
import { share } from 'rxjs/operators';
import { share, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-apps',
templateUrl: 'apps-list.component.html',
styleUrls: ['./apps-list.component.scss']
})
export class AppsListComponent implements OnInit, AfterContentInit {
export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
public static LAYOUT_LIST: string = 'LIST';
public static LAYOUT_GRID: string = 'GRID';
@@ -60,17 +60,16 @@ export class AppsListComponent implements OnInit, AfterContentInit {
private appsObserver: Observer<AppDefinitionRepresentationModel>;
apps$: Observable<AppDefinitionRepresentationModel>;
currentApp: AppDefinitionRepresentationModel;
appList: AppDefinitionRepresentationModel [] = [];
private iconsMDL: IconModel;
loading: boolean = false;
hasEmptyCustomContentTemplate: boolean = false;
private onDestroy$ = new Subject<boolean>();
constructor(
private appsProcessService: AppsProcessService,
private translationService: TranslationService) {
@@ -83,13 +82,19 @@ export class AppsListComponent implements OnInit, AfterContentInit {
this.setDefaultLayoutType();
}
this.apps$.subscribe((app: any) => {
this.appList.push(app);
});
this.apps$
.pipe(takeUntil(this.onDestroy$))
.subscribe((app: any) => this.appList.push(app));
this.iconsMDL = new IconModel();
this.load();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngAfterContentInit() {
if (this.emptyCustomContent) {
this.hasEmptyCustomContentTemplate = true;

View File

@@ -17,7 +17,7 @@
/* tslint:disable:component-selector */
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { Component, ViewEncapsulation, OnInit, OnDestroy } from '@angular/core';
import {
UploadWidgetComponent,
FormService,
@@ -26,14 +26,13 @@ import {
ProcessContentService,
ActivitiContentService,
ContentService,
FormEvent,
AppConfigValues,
AppConfigService
} from '@alfresco/adf-core';
import { ContentNodeDialogService } from '@alfresco/adf-content-services';
import { Node, RelatedContentRepresentation } from '@alfresco/js-api';
import { from, zip, of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { from, zip, of, Subject } from 'rxjs';
import { mergeMap, takeUntil } from 'rxjs/operators';
import { AttachFileWidgetDialogService } from './attach-file-widget-dialog.service';
@Component({
@@ -53,10 +52,11 @@ import { AttachFileWidgetDialogService } from './attach-file-widget-dialog.servi
},
encapsulation: ViewEncapsulation.None
})
export class AttachFileWidgetComponent extends UploadWidgetComponent implements OnInit {
export class AttachFileWidgetComponent extends UploadWidgetComponent implements OnInit, OnDestroy {
repositoryList = [];
private tempFilesList = [];
private onDestroy$ = new Subject<boolean>();
constructor(public formService: FormService,
private logger: LogService,
@@ -82,13 +82,20 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements
this.repositoryList = repoList;
});
this.formService.taskSaved.subscribe((formSaved: FormEvent) => {
this.formService.taskSaved
.pipe(takeUntil(this.onDestroy$))
.subscribe(formSaved => {
if (formSaved.form.id === this.field.form.id) {
this.tempFilesList = [];
}
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
isFileSourceConfigured(): boolean {
return !!this.field.params && !!this.field.params.fileSource;
}

View File

@@ -15,17 +15,14 @@
* limitations under the License.
*/
import {
Component, EventEmitter, Input, Output, ViewEncapsulation, SimpleChanges, OnInit, OnDestroy, OnChanges
} from '@angular/core';
import { Component, EventEmitter, Input, Output, ViewEncapsulation, SimpleChanges, OnInit, OnDestroy, OnChanges } from '@angular/core';
import { AttachFileWidgetComponent, AttachFolderWidgetComponent } from '../content-widget';
import { EcmModelService, NodeService, WidgetVisibilityService,
FormService, FormRenderingService, FormBaseComponent, FormOutcomeModel,
ValidateFormEvent, FormEvent, FormErrorEvent, FormFieldModel,
FormEvent, FormErrorEvent, FormFieldModel,
FormModel, FormOutcomeEvent, FormValues, ContentLinkModel } from '@alfresco/adf-core';
import { Observable, of, Subscription } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { Observable, of, Subject } from 'rxjs';
import { switchMap, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-form',
@@ -84,7 +81,7 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro
debugMode: boolean = false;
protected subscriptions: Subscription[] = [];
protected onDestroy$ = new Subject<boolean>();
constructor(protected formService: FormService,
protected visibilityService: WidgetVisibilityService,
@@ -97,21 +94,22 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro
}
ngOnInit() {
this.subscriptions.push(
this.formService.formContentClicked.subscribe((content: ContentLinkModel) => {
this.formContentClicked.emit(content);
}),
this.formService.validateForm.subscribe((validateFormEvent: ValidateFormEvent) => {
this.formService.formContentClicked
.pipe(takeUntil(this.onDestroy$))
.subscribe(content => this.formContentClicked.emit(content));
this.formService.validateForm
.pipe(takeUntil(this.onDestroy$))
.subscribe(validateFormEvent => {
if (validateFormEvent.errorsField.length > 0) {
this.formError.next(validateFormEvent.errorsField);
}
})
);
});
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngOnChanges(changes: SimpleChanges) {
@@ -187,8 +185,8 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro
}
getFormByTaskId(taskId: string): Promise<FormModel> {
return new Promise<FormModel>((resolve, reject) => {
this.findProcessVariablesByTaskId(taskId).subscribe((processVariables) => {
return new Promise<FormModel>(resolve => {
this.findProcessVariablesByTaskId(taskId).subscribe(() => {
this.formService
.getTaskForm(taskId)
.subscribe(

View File

@@ -29,7 +29,7 @@ import {
OnDestroy
} from '@angular/core';
import { FormComponent } from './form.component';
import { ContentLinkModel, FormService, WidgetVisibilityService, FormRenderingService, ValidateFormEvent, FormOutcomeModel } from '@alfresco/adf-core';
import { ContentLinkModel, FormService, WidgetVisibilityService, FormRenderingService, FormOutcomeModel } from '@alfresco/adf-core';
@Component({
selector: 'adf-start-form',
@@ -77,24 +77,6 @@ export class StartFormComponent extends FormComponent implements OnChanges, OnIn
this.showTitle = false;
}
ngOnInit() {
this.subscriptions.push(
this.formService.formContentClicked.subscribe((content) => {
this.formContentClicked.emit(content);
}),
this.formService.validateForm.subscribe((validateFormEvent: ValidateFormEvent) => {
if (validateFormEvent.errorsField.length > 0) {
this.formError.next(validateFormEvent.errorsField);
}
})
);
}
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
}
ngOnChanges(changes: SimpleChanges) {
const processDefinitionId = changes['processDefinitionId'];
if (processDefinitionId && processDefinitionId.currentValue) {

View File

@@ -16,16 +16,16 @@
*/
import { CommentModel, CommentProcessService } from '@alfresco/adf-core';
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { Observable, Observer } from 'rxjs';
import { share } from 'rxjs/operators';
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy } from '@angular/core';
import { Observable, Observer, Subject } from 'rxjs';
import { share, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-process-instance-comments',
templateUrl: './process-comments.component.html',
styleUrls: ['./process-comments.component.scss']
})
export class ProcessCommentsComponent implements OnChanges {
export class ProcessCommentsComponent implements OnChanges, OnDestroy {
/** (**required**) The numeric ID of the process instance to display comments for. */
@Input()
@@ -44,16 +44,22 @@ export class ProcessCommentsComponent implements OnChanges {
private commentObserver: Observer<CommentModel>;
comment$: Observable<CommentModel>;
private onDestroy$ = new Subject<boolean>();
message: string;
beingAdded: boolean = false;
constructor(private commentProcessService: CommentProcessService) {
this.comment$ = new Observable<CommentModel>((observer) => this.commentObserver = observer)
.pipe(share());
this.comment$.subscribe((comment: CommentModel) => {
this.comments.push(comment);
});
this.comment$ = new Observable<CommentModel>(observer => this.commentObserver = observer).pipe(share());
this.comment$
.pipe(takeUntil(this.onDestroy$))
.subscribe(comment => this.comments.push(comment));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngOnChanges(changes: SimpleChanges) {

View File

@@ -17,20 +17,20 @@
import { LogService } from '@alfresco/adf-core';
import { DatePipe } from '@angular/common';
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild, OnDestroy } from '@angular/core';
import { MatDialog } from '@angular/material';
import { Observable, Observer } from 'rxjs';
import { Observable, Observer, Subject } from 'rxjs';
import { TaskDetailsEvent, TaskDetailsModel } from '../../task-list';
import { ProcessInstance } from '../models/process-instance.model';
import { ProcessService } from './../services/process.service';
import { share } from 'rxjs/operators';
import { share, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-process-instance-tasks',
templateUrl: './process-instance-tasks.component.html',
styleUrls: ['./process-instance-tasks.component.css']
})
export class ProcessInstanceTasksComponent implements OnInit, OnChanges {
export class ProcessInstanceTasksComponent implements OnInit, OnChanges, OnDestroy {
/** (**required**) The ID of the process instance to display tasks for. */
@Input()
@@ -51,10 +51,10 @@ export class ProcessInstanceTasksComponent implements OnInit, OnChanges {
private taskObserver: Observer<TaskDetailsModel>;
private completedTaskObserver: Observer<TaskDetailsModel>;
private onDestroy$ = new Subject<boolean>();
task$: Observable<TaskDetailsModel>;
completedTask$: Observable<TaskDetailsModel>;
message: string;
processId: string;
@@ -78,12 +78,18 @@ export class ProcessInstanceTasksComponent implements OnInit, OnChanges {
}
ngOnInit() {
this.task$.subscribe((task: TaskDetailsModel) => {
this.activeTasks.push(task);
});
this.completedTask$.subscribe((task: TaskDetailsModel) => {
this.completedTasks.push(task);
});
this.task$
.pipe(takeUntil(this.onDestroy$))
.subscribe(task => this.activeTasks.push(task));
this.completedTask$
.pipe(takeUntil(this.onDestroy$))
.subscribe(task => this.completedTasks.push(task));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngOnChanges(changes: SimpleChanges) {

View File

@@ -17,7 +17,7 @@
import {
Component, EventEmitter, Input, OnChanges, OnInit,
Output, SimpleChanges, ViewChild, ViewEncapsulation
Output, SimpleChanges, ViewChild, ViewEncapsulation, OnDestroy
} from '@angular/core';
import {
ActivitiContentService, AppConfigService, AppConfigValues,
@@ -28,8 +28,8 @@ import { ProcessDefinitionRepresentation } from './../models/process-definition.
import { ProcessInstance } from './../models/process-instance.model';
import { ProcessService } from './../services/process.service';
import { FormControl, Validators, AbstractControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Observable, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { MatAutocompleteTrigger } from '@angular/material';
import { StartFormComponent } from '../../form';
@@ -39,7 +39,7 @@ import { StartFormComponent } from '../../form';
styleUrls: ['./start-process.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class StartProcessInstanceComponent implements OnChanges, OnInit {
export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestroy {
MAX_LENGTH: number = 255;
@@ -101,6 +101,8 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit {
filteredProcesses: Observable<ProcessDefinitionRepresentation[]>;
maxProcessNameLength: number = this.MAX_LENGTH;
private onDestroy$ = new Subject<boolean>();
constructor(private activitiProcess: ProcessService,
private activitiContentService: ActivitiContentService,
private appConfig: AppConfigService) {
@@ -112,13 +114,22 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit {
this.loadStartProcess();
this.processNameInput.valueChanges.subscribe((name) => this.name = name);
this.processNameInput.valueChanges
.pipe(takeUntil(this.onDestroy$))
.subscribe(name => this.name = name);
this.filteredProcesses = this.processDefinitionInput.valueChanges
.pipe(
map((value) => this._filter(value))
map((value) => this._filter(value)),
takeUntil(this.onDestroy$)
);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngOnChanges(changes: SimpleChanges) {
if (changes['values'] && changes['values'].currentValue) {
this.moveNodeFromCStoPS();

View File

@@ -16,16 +16,16 @@
*/
import { LogService, UserPreferencesService, UserPreferenceValues, UserProcessModel, FormFieldModel, FormModel } from '@alfresco/adf-core';
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, OnDestroy } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { MOMENT_DATE_FORMATS, MomentDateAdapter } from '@alfresco/adf-core';
import moment from 'moment-es6';
import { Moment } from 'moment';
import { Observable, of } from 'rxjs';
import { Observable, of, Subject } from 'rxjs';
import { Form } from '../models/form.model';
import { TaskDetailsModel } from '../models/task-details.model';
import { TaskListService } from './../services/tasklist.service';
import { switchMap, defaultIfEmpty } from 'rxjs/operators';
import { switchMap, defaultIfEmpty, takeUntil } from 'rxjs/operators';
import { FormBuilder, AbstractControl, Validators, FormGroup, FormControl } from '@angular/forms';
@Component({
@@ -37,7 +37,7 @@ import { FormBuilder, AbstractControl, Validators, FormGroup, FormControl } from
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }],
encapsulation: ViewEncapsulation.None
})
export class StartTaskComponent implements OnInit {
export class StartTaskComponent implements OnInit, OnDestroy {
public FORMAT_DATE: string = 'DD/MM/YYYY';
MAX_LENGTH: number = 255;
@@ -71,6 +71,8 @@ export class StartTaskComponent implements OnInit {
maxTaskNameLength: number = this.MAX_LENGTH;
loading = false;
private onDestroy$ = new Subject<boolean>();
/**
* Constructor
* @param auth
@@ -92,14 +94,21 @@ export class StartTaskComponent implements OnInit {
this.validateMaxTaskNameLength();
this.field = new FormFieldModel(new FormModel(), { id: this.assigneeId, value: this.assigneeId, placeholder: 'Assignee' });
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.dateAdapter.setLocale(locale);
});
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
this.loadFormsTask();
this.buildForm();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
buildForm() {
this.taskForm = this.formBuilder.group({
name: new FormControl(this.taskDetailsModel.name, [Validators.required, Validators.maxLength(this.maxTaskNameLength), this.whitespaceValidator]),
@@ -107,7 +116,9 @@ export class StartTaskComponent implements OnInit {
formKey: new FormControl('')
});
this.taskForm.valueChanges.subscribe((taskFormValues) => this.setTaskDetails(taskFormValues));
this.taskForm.valueChanges
.pipe(takeUntil(this.onDestroy$))
.subscribe(taskFormValues => this.setTaskDetails(taskFormValues));
}
public whitespaceValidator(control: FormControl) {

View File

@@ -33,23 +33,24 @@ import {
Output,
SimpleChanges,
TemplateRef,
ViewChild
ViewChild,
OnDestroy
} from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material';
import { Observable, Observer } from 'rxjs';
import { Observable, Observer, Subject } from 'rxjs';
import { ContentLinkModel, FormFieldValidator, FormModel, FormOutcomeEvent } from '@alfresco/adf-core';
import { TaskQueryRequestRepresentationModel } from '../models/filter.model';
import { TaskDetailsModel } from '../models/task-details.model';
import { TaskListService } from './../services/tasklist.service';
import { UserRepresentation } from '@alfresco/js-api';
import { share } from 'rxjs/operators';
import { share, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-task-details',
templateUrl: './task-details.component.html',
styleUrls: ['./task-details.component.scss']
})
export class TaskDetailsComponent implements OnInit, OnChanges {
export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
@ViewChild('activitiComments')
activitiComments: CommentsComponent;
@@ -166,17 +167,15 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
taskDetails: TaskDetailsModel;
taskFormName: string = null;
taskPeople: UserProcessModel[] = [];
noTaskDetailsTemplateComponent: TemplateRef<any>;
showAssignee: boolean = false;
showAttachForm: boolean = false;
internalReadOnlyForm: boolean = false;
private peopleSearchObserver: Observer<UserProcessModel[]>;
public errorDialogRef: MatDialogRef<TemplateRef<any>>;
private onDestroy$ = new Subject<boolean>();
peopleSearch: Observable<UserProcessModel[]>;
@@ -189,21 +188,30 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
private logService: LogService,
private cardViewUpdateService: CardViewUpdateService,
private dialog: MatDialog) {
this.peopleSearch = new Observable<UserProcessModel[]>((observer) => this.peopleSearchObserver = observer)
.pipe(share());
this.authService.getBpmLoggedUser().subscribe((user: UserRepresentation) => {
this.currentLoggedUser = user;
});
}
ngOnInit() {
this.peopleSearch = new Observable<UserProcessModel[]>((observer) => this.peopleSearchObserver = observer).pipe(share());
this.authService.getBpmLoggedUser().subscribe(user => {
this.currentLoggedUser = user;
});
if (this.taskId) {
this.loadDetails(this.taskId);
}
this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this));
this.cardViewUpdateService.itemClicked$.subscribe(this.clickTaskDetails.bind(this));
this.cardViewUpdateService.itemUpdated$
.pipe(takeUntil(this.onDestroy$))
.subscribe(this.updateTaskDetails.bind(this));
this.cardViewUpdateService.itemClicked$
.pipe(takeUntil(this.onDestroy$))
.subscribe(this.clickTaskDetails.bind(this));
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngOnChanges(changes: SimpleChanges): void {
@@ -265,12 +273,9 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
* @param updateNotification
*/
private updateTaskDetails(updateNotification: UpdateNotification) {
this.taskListService.updateTask(this.taskId, updateNotification.changed)
.subscribe(
() => {
this.loadDetails(this.taskId);
}
);
this.taskListService
.updateTask(this.taskId, updateNotification.changed)
.subscribe(() => this.loadDetails(this.taskId));
}
private clickTaskDetails(clickNotification: ClickNotification) {
@@ -386,9 +391,9 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
* Complete button clicked
*/
onComplete(): void {
this.taskListService.completeTask(this.taskId).subscribe(
(res) => this.onFormCompleted(null)
);
this.taskListService
.completeTask(this.taskId)
.subscribe(() => this.onFormCompleted(null));
}
onShowAttachForm() {
@@ -461,10 +466,13 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
searchUser(searchedWord: string) {
this.peopleProcessService.getWorkflowUsers(null, searchedWord)
.subscribe((users) => {
.subscribe(
users => {
users = users.filter((user) => user.id !== this.taskDetails.assignee.id);
this.peopleSearchObserver.next(users);
}, (error) => this.logService.error('Could not load users'));
},
() => this.logService.error('Could not load users')
);
}
onCloseSearch() {
@@ -472,8 +480,9 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
}
assignTaskToUser(selectedUser: UserProcessModel) {
this.taskListService.assignTask(this.taskDetails.id, selectedUser).subscribe(
(res: any) => {
this.taskListService
.assignTask(this.taskDetails.id, selectedUser)
.subscribe(() => {
this.logService.info('Task Assigned to ' + selectedUser.email);
this.assignTask.emit();
});

View File

@@ -285,8 +285,7 @@ export class TaskHeaderComponent implements OnChanges, OnInit {
* @param taskId
*/
claimTask(taskId: string) {
this.activitiTaskService.claimTask(taskId).subscribe(
(res: any) => {
this.activitiTaskService.claimTask(taskId).subscribe(() => {
this.logService.info('Task claimed');
this.claim.emit(taskId);
});
@@ -298,8 +297,7 @@ export class TaskHeaderComponent implements OnChanges, OnInit {
* @param taskId
*/
unclaimTask(taskId: string) {
this.activitiTaskService.unclaimTask(taskId).subscribe(
(res: any) => {
this.activitiTaskService.unclaimTask(taskId).subscribe(() => {
this.logService.info('Task unclaimed');
this.unclaim.emit(taskId);
});

View File

@@ -21,21 +21,22 @@ import {
UserPreferencesService, UserPreferenceValues, PaginationModel } from '@alfresco/adf-core';
import {
AfterContentInit, Component, ContentChild, EventEmitter,
Input, OnChanges, Output, SimpleChanges } from '@angular/core';
Input, OnChanges, Output, SimpleChanges, OnDestroy, OnInit } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
import { Observable, BehaviorSubject, Subject } from 'rxjs';
import { TaskQueryRequestRepresentationModel } from '../models/filter.model';
import { TaskListModel } from '../models/task-list.model';
import { taskPresetsDefaultModel } from '../models/task-preset.model';
import { TaskListService } from './../services/tasklist.service';
import moment from 'moment-es6';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-tasklist',
templateUrl: './task-list.component.html',
styleUrls: ['./task-list.component.css']
})
export class TaskListComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent {
export class TaskListComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit {
static PRESET_KEY = 'adf-task-list.presets';
@@ -170,13 +171,12 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
*/
hasCustomDataSource: boolean = false;
private onDestroy$ = new Subject<boolean>();
constructor(private taskListService: TaskListService,
appConfigService: AppConfigService,
private userPreferences: UserPreferencesService) {
super(appConfigService, TaskListComponent.PRESET_KEY, taskPresetsDefaultModel);
this.userPreferences.select(UserPreferenceValues.PaginationSize).subscribe((pageSize) => {
this.size = pageSize;
});
this.pagination = new BehaviorSubject<PaginationModel>(<PaginationModel> {
maxItems: this.size,
@@ -196,6 +196,18 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
}
}
ngOnInit() {
this.userPreferences
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntil(this.onDestroy$))
.subscribe(pageSize => this.size = pageSize);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
setCustomDataSource(rows: any[]): void {
if (rows) {
this.rows = rows;

View File

@@ -29,7 +29,7 @@
"lint-lib": "./node_modules/.bin/tslint -p ./lib/tsconfig.json -c ./lib/tslint.json",
"lint-e2e": "tsc -p ./e2e/tsconfig.e2e.json && ./node_modules/.bin/tslint -p ./e2e/tsconfig.e2e.json -c ./tslint.json",
"validate-config": "ajv validate -s ./lib/core/app-config/schema.json -d ./demo-shell/src/app.config.json --errors=text --verbose",
"spellcheck": "cspell 'demo-shell/{src,e2e}/**/*.ts' 'e2e/**/*.ts' 'lib/{content-services,core,extensions,insights,process-services}/**/*.ts'",
"spellcheck": "cspell 'demo-shell/{src,e2e}/**/*.ts' 'e2e/**/*.ts' 'lib/{content-services,core,extensions,insights,process-services,process-services-cloud}/**/*.ts'",
"stylelint": "stylelint ./**/*.scss --config stylelint-config.json",
"04": "echo -------------------------------------------- Demo Shell -----------------------------------------------",
"04s": "",

View File

@@ -175,7 +175,6 @@
"format": "PascalCase"
}
],
"arrow-parens": true,
"no-input-prefix": true,
"ordered-imports": false,
"template-conditional-complexity": [