[ACS-8959] Introduce new takeUntilDestroyed operator where possible (#10388)

This commit is contained in:
dominikiwanekhyland
2024-11-19 11:54:00 +01:00
committed by GitHub
parent 3f6b60760f
commit 3078387325
128 changed files with 1452 additions and 1546 deletions

View File

@@ -16,35 +16,35 @@
*/
import {
ChangeDetectorRef,
Component,
DestroyRef,
EventEmitter,
HostListener,
inject,
Input,
OnChanges,
Output,
SimpleChanges,
OnDestroy,
HostListener,
OnInit,
ChangeDetectorRef,
inject
Output,
SimpleChanges
} from '@angular/core';
import { Observable, of, forkJoin, Subject, Subscription } from 'rxjs';
import { switchMap, takeUntil, map, filter } from 'rxjs/operators';
import { forkJoin, Observable, of, Subscription } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';
import {
ConfirmDialogComponent,
ContentLinkModel,
FORM_FIELD_VALIDATORS,
FormBaseComponent,
FormEvent,
FormFieldModel,
FormFieldValidator,
FormModel,
FormOutcomeEvent,
FormOutcomeModel,
WidgetVisibilityService,
FormService,
FORM_FIELD_VALIDATORS,
FormFieldValidator,
FormValues,
FormModel,
ContentLinkModel,
UploadWidgetContentLinkModel,
FormEvent,
ConfirmDialogComponent
WidgetVisibilityService
} from '@alfresco/adf-core';
import { FormCloudService } from '../services/form-cloud.service';
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
@@ -54,13 +54,14 @@ import { v4 as uuidGeneration } from 'uuid';
import { FormCloudDisplayMode, FormCloudDisplayModeConfiguration } from '../../services/form-fields.interfaces';
import { FormCloudSpinnerService } from '../services/spinner/form-cloud-spinner.service';
import { DisplayModeService } from '../services/display-mode.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-form',
templateUrl: './form-cloud.component.html',
styleUrls: ['./form-cloud.component.scss']
})
export class FormCloudComponent extends FormBaseComponent implements OnChanges, OnInit, OnDestroy {
export class FormCloudComponent extends FormBaseComponent implements OnChanges, OnInit {
/** App name to fetch corresponding form and values. */
@Input()
appName: string = '';
@@ -131,8 +132,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
nodeId: string;
formCloudRepresentationJSON: any;
protected onDestroy$ = new Subject<boolean>();
readonly id: string;
displayMode: string;
displayConfiguration: FormCloudDisplayModeConfiguration = DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0];
@@ -146,14 +145,16 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
protected displayModeService = inject(DisplayModeService);
protected changeDetector = inject(ChangeDetectorRef);
private readonly destroyRef = inject(DestroyRef);
constructor() {
super();
this.spinnerService.initSpinnerHandling(this.onDestroy$);
this.spinnerService.initSpinnerHandling(this.destroyRef);
this.id = uuidGeneration();
this.formService.formContentClicked.pipe(takeUntil(this.onDestroy$)).subscribe((content) => {
this.formService.formContentClicked.pipe(takeUntilDestroyed()).subscribe((content) => {
if (content instanceof UploadWidgetContentLinkModel) {
this.form.setNodeIdValueForViewersLinkedToUploadWidget(content);
this.onFormDataRefreshed(this.form);
@@ -163,12 +164,12 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
}
});
this.formService.updateFormValuesRequested.pipe(takeUntil(this.onDestroy$)).subscribe((valuesToSetIfNotPresent) => {
this.formService.updateFormValuesRequested.pipe(takeUntilDestroyed()).subscribe((valuesToSetIfNotPresent) => {
this.form.addValuesNotPresent(valuesToSetIfNotPresent);
this.onFormDataRefreshed(this.form);
});
this.formService.formFieldValueChanged.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
this.formService.formFieldValueChanged.pipe(takeUntilDestroyed()).subscribe(() => {
if (this.disableSaveButton) {
this.disableSaveButton = false;
}
@@ -222,7 +223,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
DisplayModeService.displayMode$
.pipe(
filter((change) => change.id === this.id),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((displayModeChange) => {
const oldDisplayMode = this.displayMode;
@@ -281,7 +282,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
getFormByTaskId(appName: string, taskId: string, version?: number): Promise<FormModel> {
return new Promise<FormModel>((resolve) => {
forkJoin(this.formCloudService.getTaskForm(appName, taskId, version), this.formCloudService.getTaskVariables(appName, taskId))
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(
(data) => {
this.formCloudRepresentationJSON = data[0];
@@ -314,7 +315,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
delete flattenForm.formDefinition;
return flattenForm;
}),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe(
(form) => {
@@ -337,7 +338,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
if (this.form && this.appName && this.taskId) {
this.formCloudService
.saveTaskForm(this.appName, this.taskId, this.processInstanceId, `${this.form.id}`, this.form.values)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(
() => {
this.onTaskSaved(this.form);
@@ -372,7 +373,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
if (this.form && this.appName && this.taskId) {
this.formCloudService
.completeTaskForm(this.appName, this.taskId, this.processInstanceId, `${this.form.id}`, this.form.values, outcome, this.appVersion)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(
() => {
this.onTaskCompleted(this.form);
@@ -478,11 +479,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
protected storeFormAsMetadata() {}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
switchToDisplayMode(newDisplayMode?: string) {
this.displayModeService.switchToDisplayMode(this.id, FormCloudDisplayMode[newDisplayMode], this.displayMode, this.displayModeConfigurations);
}

View File

@@ -21,47 +21,47 @@ import { ContentCloudNodeSelectorService } from '../../../services/content-cloud
import { ProcessCloudContentService } from '../../../services/process-cloud-content.service';
import { AttachFileCloudWidgetComponent } from './attach-file-cloud-widget.component';
import {
FormFieldModel,
FormModel,
FormFieldTypes,
FormService,
DownloadService,
AppConfigService,
UploadWidgetContentLinkModel,
ContentLinkModel,
DownloadService,
FormFieldModel,
FormFieldTypes,
FormModel,
FormService,
LocalizedDatePipe,
NotificationService,
ContentLinkModel
UploadWidgetContentLinkModel
} from '@alfresco/adf-core';
import {
allSourceParams,
contentSourceParam,
fakeNode,
mockNodeId,
fakeLocalPngResponse,
onlyLocalParams,
allSourceWithWrongAliasParams,
allSourceWithNoAliasParams,
fakeNodeWithProperties,
menuTestSourceParam,
expectedValues,
fakeLocalPngAnswer,
allSourceWithStringTypeEmptyValue,
mockNodeIdBasedOnStringVariableValue,
mockAllFileSourceWithStringVariablePathType,
mockAllFileSourceWithFolderVariablePathType,
mockContentFileSource,
mockAllFileSourceWithStaticPathType,
formVariables,
processVariables,
mockAllFileSourceWithRenamedFolderVariablePathType,
allSourceParamsWithRelativePath,
fakeLocalPhysicalRecordResponse,
allSourceWithNoAliasParams,
allSourceWithStringTypeEmptyValue,
allSourceWithWrongAliasParams,
contentSourceParam,
displayableCMParams,
expectedValues,
fakeLocalPhysicalRecordResponse,
fakeLocalPngAnswer,
fakeLocalPngHavingCMProperties,
mockMyNodeId
fakeLocalPngResponse,
fakeNode,
fakeNodeWithProperties,
formVariables,
menuTestSourceParam,
mockAllFileSourceWithFolderVariablePathType,
mockAllFileSourceWithRenamedFolderVariablePathType,
mockAllFileSourceWithStaticPathType,
mockAllFileSourceWithStringVariablePathType,
mockContentFileSource,
mockMyNodeId,
mockNodeId,
mockNodeIdBasedOnStringVariableValue,
onlyLocalParams,
processVariables
} from '../../../mocks/attach-file-cloud-widget.mock';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { CUSTOM_ELEMENTS_SCHEMA, Injector, runInInjectionContext } from '@angular/core';
import {
ContentModule,
ContentNodeSelectorPanelService,
@@ -162,9 +162,12 @@ describe('AttachFileCloudWidgetComponent', () => {
contentCloudNodeSelectorService = TestBed.inject(ContentCloudNodeSelectorService);
appConfigService = TestBed.inject(AppConfigService);
formService = TestBed.inject(FormService);
const injector = TestBed.inject(Injector);
contentNodeSelectorPanelService = TestBed.inject(ContentNodeSelectorPanelService);
openUploadFileDialogSpy = spyOn(contentCloudNodeSelectorService, 'openUploadFileDialog').and.returnValue(of([fakeNode]));
localizedDataPipe = new LocalizedDatePipe();
runInInjectionContext(injector, () => {
localizedDataPipe = new LocalizedDatePipe();
});
});
afterEach(() => {

View File

@@ -17,19 +17,17 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, OnInit, ViewEncapsulation, OnDestroy, inject } from '@angular/core';
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import {
WidgetComponent,
FormService,
ADF_DATE_FORMATS,
AdfDateFnsAdapter,
DateFnsUtils,
ADF_DATE_FORMATS,
ErrorWidgetComponent,
DEFAULT_DATE_FORMAT,
ErrorMessageModel,
DEFAULT_DATE_FORMAT
ErrorWidgetComponent,
FormService,
WidgetComponent
} from '@alfresco/adf-core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { addDays, parseISO } from 'date-fns';
@@ -38,6 +36,7 @@ import { NgIf } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'date-widget',
@@ -62,7 +61,7 @@ import { MatInputModule } from '@angular/material/input';
},
encapsulation: ViewEncapsulation.None
})
export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
export class DateCloudWidgetComponent extends WidgetComponent implements OnInit {
typeId = 'DateCloudWidgetComponent';
minDate: Date = null;
@@ -71,9 +70,9 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit,
dateInputControl: FormControl<Date> = new FormControl<Date>(null);
private onDestroy$ = new Subject<void>();
public readonly formService = inject(FormService);
private readonly destroyRef = inject(DestroyRef);
private readonly dateAdapter = inject(DateAdapter);
ngOnInit(): void {
@@ -101,7 +100,7 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit,
}
private subscribeToDateChanges(): void {
this.dateInputControl.valueChanges.pipe(takeUntil(this.onDestroy$)).subscribe((newDate: Date) => {
this.dateInputControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((newDate: Date) => {
this.field.value = newDate;
this.updateField();
});
@@ -198,9 +197,4 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit,
this.maxDate = parseISO(this.field.maxValue);
}
}
ngOnDestroy(): void {
this.onDestroy$.next();
this.onDestroy$.complete();
}
}

View File

@@ -29,15 +29,16 @@ import {
WidgetComponent
} from '@alfresco/adf-core';
import { AsyncPipe, NgFor, NgIf } from '@angular/common';
import { Component, inject, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { TranslateModule } from '@ngx-translate/core';
import { BehaviorSubject, Subject } from 'rxjs';
import { filter, map, takeUntil } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { TaskVariableCloud } from '../../../models/task-variable-cloud.model';
import { FormCloudService } from '../../../services/form-cloud.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
export const DEFAULT_OPTION = {
id: 'empty',
@@ -65,7 +66,7 @@ export const HIDE_FILTER_LIMIT = 5;
SelectFilterInputComponent
]
})
export class DropdownCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
export class DropdownCloudWidgetComponent extends WidgetComponent implements OnInit {
public formService = inject(FormService);
private formCloudService = inject(FormCloudService);
private appConfig = inject(AppConfigService);
@@ -84,8 +85,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
private readonly defaultVariableOptionId = 'id';
private readonly defaultVariableOptionLabel = 'name';
private readonly defaultVariableOptionPath = 'data';
protected onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
get showRequiredMessage(): boolean {
return this.dropdownControl.touched && this.dropdownControl.errors?.required && !this.isRestApiFailed && !this.variableOptionsFailed;
@@ -133,11 +133,6 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
compareDropdownValues(opt1: FormFieldOption | string, opt2: FormFieldOption | string): boolean {
if (!opt1 || !opt2) {
return false;
@@ -186,7 +181,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
this.dropdownControl.valueChanges
.pipe(
filter(() => !!this.field),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((value) => {
this.setOptionValue(value, this.field);
@@ -216,7 +211,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
map((search) =>
search ? this.field.options.filter(({ name }) => name.toLowerCase().includes(search.toLowerCase())) : this.field.options
),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((result) => this.list$.next(result));
}
@@ -333,7 +328,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
const bodyParam = this.buildBodyParam();
this.formCloudService
.getRestWidgetData(this.field.form.id, this.field.id, bodyParam)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
next: (result: FormFieldOption[]) => {
this.resetRestApiErrorMessage();
@@ -366,7 +361,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
this.formService.formFieldValueChanged
.pipe(
filter((event: FormFieldEvent) => this.isFormFieldEventOfTypeDropdown(event) && this.isParentFormFieldEvent(event)),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((event: FormFieldEvent) => {
const valueOfParentWidget = event.field.value;

View File

@@ -15,13 +15,13 @@
* limitations under the License.
*/
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { WidgetComponent, FormService } from '@alfresco/adf-core';
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { FormService, WidgetComponent } from '@alfresco/adf-core';
import { UntypedFormControl } from '@angular/forms';
import { filter, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { ComponentSelectionMode } from '../../../../types';
import { IdentityGroupModel } from '../../../../group/models/identity-group.model';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
/* eslint-disable @angular-eslint/component-selector */
@@ -41,9 +41,7 @@ import { IdentityGroupModel } from '../../../../group/models/identity-group.mode
},
encapsulation: ViewEncapsulation.None
})
export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit {
typeId = 'GroupCloudWidgetComponent';
roles: string[];
@@ -53,6 +51,8 @@ export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit
search: UntypedFormControl;
validate = false;
private readonly destroyRef = inject(DestroyRef);
constructor(formService: FormService) {
super(formService);
}
@@ -71,7 +71,7 @@ export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit
this.search.statusChanges
.pipe(
filter((value: string) => value === 'INVALID'),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {
this.field.markAsInvalid();
@@ -81,19 +81,13 @@ export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit
this.search.statusChanges
.pipe(
filter((value: string) => value === 'VALID'),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {
this.field.validate();
this.field.form.validateForm();
});
}
ngOnDestroy(): void {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onChangedGroup(groups: IdentityGroupModel[]): void {
this.field.value = groups?.length ? [...groups] : null;
this.onFieldChanged(this.field);

View File

@@ -15,14 +15,14 @@
* limitations under the License.
*/
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { WidgetComponent, FormService } from '@alfresco/adf-core';
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { FormService, WidgetComponent } from '@alfresco/adf-core';
import { UntypedFormControl } from '@angular/forms';
import { filter, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { ComponentSelectionMode } from '../../../../types';
import { IdentityUserModel } from '../../../../people/models/identity-user.model';
import { IdentityUserService } from '../../../../people/services/identity-user.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
/* eslint-disable @angular-eslint/component-selector */
@@ -42,9 +42,7 @@ import { IdentityUserService } from '../../../../people/services/identity-user.s
},
encapsulation: ViewEncapsulation.None
})
export class PeopleCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
export class PeopleCloudWidgetComponent extends WidgetComponent implements OnInit {
typeId = 'PeopleCloudWidgetComponent';
appName: string;
@@ -56,6 +54,8 @@ export class PeopleCloudWidgetComponent extends WidgetComponent implements OnIni
groupsRestriction: string[];
validate = false;
private readonly destroyRef = inject(DestroyRef);
constructor(formService: FormService, private identityUserService: IdentityUserService) {
super(formService);
}
@@ -75,7 +75,7 @@ export class PeopleCloudWidgetComponent extends WidgetComponent implements OnIni
this.search.statusChanges
.pipe(
filter((value: string) => value === 'INVALID'),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {
this.field.markAsInvalid();
@@ -85,7 +85,7 @@ export class PeopleCloudWidgetComponent extends WidgetComponent implements OnIni
this.search.statusChanges
.pipe(
filter((value: string) => value === 'VALID'),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {
this.field.validate();
@@ -99,11 +99,6 @@ export class PeopleCloudWidgetComponent extends WidgetComponent implements OnIni
}
}
ngOnDestroy(): void {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
onChangedUser(users: IdentityUserModel[]): void {
this.field.value = users?.length ? [...users] : null;
this.onFieldChanged(this.field);

View File

@@ -17,12 +17,11 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { WidgetComponent, FormService, FormFieldOption, ErrorMessageModel } from '@alfresco/adf-core';
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { ErrorMessageModel, FormFieldOption, FormService, WidgetComponent } from '@alfresco/adf-core';
import { FormCloudService } from '../../../services/form-cloud.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'radio-buttons-cloud-widget',
@@ -45,7 +44,7 @@ export class RadioButtonsCloudWidgetComponent extends WidgetComponent implements
typeId = 'RadioButtonsCloudWidgetComponent';
restApiError: ErrorMessageModel;
protected onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
constructor(public formService: FormService, private formCloudService: FormCloudService, private translateService: TranslateService) {
super(formService);
@@ -60,7 +59,7 @@ export class RadioButtonsCloudWidgetComponent extends WidgetComponent implements
getValuesFromRestApi() {
this.formCloudService
.getRestWidgetData(this.field.form.id, this.field.id)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(
(result: FormFieldOption[]) => {
this.field.options = result;

View File

@@ -21,7 +21,7 @@ import { OverlayModule } from '@angular/cdk/overlay';
import { FormService, FormSpinnerEvent } from '@alfresco/adf-core';
import { Subject } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core';
import { Component } from '@angular/core';
import { Component, DestroyRef, inject } from '@angular/core';
import { FormSpinnerComponent } from '../../components/spinner/form-spinner.component';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
@@ -33,18 +33,20 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
selector: 'adf-cloud-overlay-test',
template: `<div>adf-cloud-overlay-test</div>`
})
class SpinnerTestComponent {}
class SpinnerTestComponent {
destroyRef = inject(DestroyRef)
}
describe('FormCloudSpinnerService', () => {
let fixture: ComponentFixture<SpinnerTestComponent>;
let rootLoader: HarnessLoader;
let spinnerService: FormCloudSpinnerService;
let formService: FormService;
let destroyRef: DestroyRef;
const showSpinnerEvent = new FormSpinnerEvent('toggle-spinner', { showSpinner: true, message: 'LOAD_SPINNER_MESSAGE' });
const hideSpinnerEvent = new FormSpinnerEvent('toggle-spinner', { showSpinner: false });
const onDestroy$ = new Subject<boolean>();
beforeEach(() => {
TestBed.configureTestingModule({
@@ -65,10 +67,11 @@ describe('FormCloudSpinnerService', () => {
rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);
spinnerService = TestBed.inject(FormCloudSpinnerService);
formService = TestBed.inject(FormService);
destroyRef = fixture.componentInstance.destroyRef
});
it('should toggle spinner', async () => {
spinnerService.initSpinnerHandling(onDestroy$);
spinnerService.initSpinnerHandling(destroyRef);
formService.toggleFormSpinner.next(showSpinnerEvent);
fixture.detectChanges();

View File

@@ -15,13 +15,12 @@
* limitations under the License.
*/
import { Injectable, inject } from '@angular/core';
import { DestroyRef, inject, Injectable } from '@angular/core';
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { FormService, FormSpinnerEvent } from '@alfresco/adf-core';
import { Observable } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FormSpinnerComponent } from '../../components/spinner/form-spinner.component';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Injectable()
export class FormCloudSpinnerService {
@@ -30,8 +29,8 @@ export class FormCloudSpinnerService {
private overlayRef?: OverlayRef;
initSpinnerHandling(onDestroy$: Observable<boolean>): void {
this.formService.toggleFormSpinner.pipe(takeUntil(onDestroy$)).subscribe((event: FormSpinnerEvent) => {
initSpinnerHandling(destroyRef: DestroyRef): void {
this.formService.toggleFormSpinner.pipe(takeUntilDestroyed(destroyRef)).subscribe((event: FormSpinnerEvent) => {
if (event?.payload.showSpinner) {
this.overlayRef = this.overlay.create({
hasBackdrop: true

View File

@@ -17,26 +17,28 @@
import {
Component,
DestroyRef,
ElementRef,
EventEmitter,
Inject,
inject,
Input,
OnChanges,
OnInit,
Output,
EventEmitter,
ViewChild,
ViewEncapsulation,
Input,
SimpleChanges,
OnChanges,
OnDestroy,
Inject
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { distinctUntilChanged, switchMap, mergeMap, filter, tap, takeUntil, debounceTime } from 'rxjs/operators';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { BehaviorSubject, Observable } from 'rxjs';
import { debounceTime, distinctUntilChanged, filter, mergeMap, switchMap, tap } from 'rxjs/operators';
import { ComponentSelectionMode } from '../../types';
import { IdentityGroupModel } from '../models/identity-group.model';
import { IdentityGroupServiceInterface } from '../services/identity-group.service.interface';
import { IDENTITY_GROUP_SERVICE_TOKEN } from '../services/identity-group-service.token';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-group',
@@ -50,7 +52,7 @@ import { IDENTITY_GROUP_SERVICE_TOKEN } from '../services/identity-group-service
],
encapsulation: ViewEncapsulation.None
})
export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
export class GroupCloudComponent implements OnInit, OnChanges {
/** Name of the application. If specified this shows the groups who have access to the app. */
@Input()
appName: string;
@@ -119,7 +121,6 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
private groupInput: ElementRef<HTMLInputElement>;
private searchGroups: IdentityGroupModel[] = [];
private onDestroy$ = new Subject<boolean>();
selectedGroups: IdentityGroupModel[] = [];
invalidGroups: IdentityGroupModel[] = [];
@@ -137,6 +138,8 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
typingUniqueValueNotEmpty$: Observable<any>;
private readonly destroyRef = inject(DestroyRef);
constructor(
@Inject(IDENTITY_GROUP_SERVICE_TOKEN)
private identityGroupService: IdentityGroupServiceInterface
@@ -172,7 +175,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
return groups;
}),
filter((group) => !this.isGroupAlreadySelected(group)),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((searchedGroup: IdentityGroupModel) => {
this.searchGroups.push(searchedGroup);
@@ -467,9 +470,4 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
getValidationMinLength(): string {
return this.searchGroupsControl.errors.minlength.requiredLength;
}
ngOnDestroy(): void {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -17,29 +17,31 @@
import { UntypedFormControl } from '@angular/forms';
import {
AfterViewInit,
Component,
DestroyRef,
ElementRef,
EventEmitter,
Inject,
inject,
Input,
OnChanges,
OnInit,
Output,
EventEmitter,
ViewEncapsulation,
Input,
SimpleChanges,
OnChanges,
OnDestroy,
ViewChild,
ElementRef,
Inject,
AfterViewInit
ViewEncapsulation
} from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { switchMap, debounceTime, distinctUntilChanged, mergeMap, tap, filter, takeUntil } from 'rxjs/operators';
import { BehaviorSubject, Observable } from 'rxjs';
import { debounceTime, distinctUntilChanged, filter, mergeMap, switchMap, tap } from 'rxjs/operators';
import { FullNamePipe } from '@alfresco/adf-core';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { ComponentSelectionMode } from '../../types';
import { IdentityUserModel } from '../models/identity-user.model';
import { IdentityUserServiceInterface } from '../services/identity-user.service.interface';
import { IDENTITY_USER_SERVICE_TOKEN } from '../services/identity-user-service.token';
import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-people',
@@ -54,7 +56,7 @@ import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-
providers: [FullNamePipe],
encapsulation: ViewEncapsulation.None
})
export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit {
export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
/** Name of the application. If specified, this shows the users who have access to the app. */
@Input()
appName: string;
@@ -175,7 +177,6 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy, After
private userInput: ElementRef<HTMLInputElement>;
private searchUsers: IdentityUserModel[] = [];
private onDestroy$ = new Subject<boolean>();
selectedUsers: IdentityUserModel[] = [];
invalidUsers: IdentityUserModel[] = [];
@@ -193,6 +194,8 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy, After
typingUniqueValueNotEmpty$: Observable<string>;
private readonly destroyRef = inject(DestroyRef);
constructor(
@Inject(IDENTITY_USER_SERVICE_TOKEN)
private identityUserService: IdentityUserServiceInterface
@@ -245,7 +248,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy, After
return users;
}),
filter((user) => !this.isUserAlreadySelected(user) && !this.isExcludedUser(user)),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((user: IdentityUserModel) => {
this.searchUsers.push(user);
@@ -563,9 +566,4 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy, After
getValidationMinLength(): string {
return this.searchUserCtrl.errors.minlength.requiredLength;
}
ngOnDestroy(): void {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -15,18 +15,17 @@
* limitations under the License.
*/
import { Directive, HostListener, Output, EventEmitter, OnInit, OnDestroy, ElementRef } from '@angular/core';
import { DestroyRef, Directive, ElementRef, EventEmitter, HostListener, inject, OnInit, Output } from '@angular/core';
import { ProcessCloudService } from '../services/process-cloud.service';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { ProcessInstanceCloud } from '../start-process/models/process-instance-cloud.model';
import { IdentityUserService } from '../../people/services/identity-user.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
selector: '[adf-cloud-cancel-process]'
})
export class CancelProcessDirective implements OnInit, OnDestroy {
export class CancelProcessDirective implements OnInit {
/** Emitted when the process is cancelled. */
@Output()
@@ -40,7 +39,7 @@ export class CancelProcessDirective implements OnInit, OnDestroy {
canCancelProcess = false;
private onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
constructor(
private elementRef: ElementRef,
@@ -49,7 +48,7 @@ export class CancelProcessDirective implements OnInit, OnDestroy {
ngOnInit() {
this.processCloudService.dataChangesDetected
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((processDetails) => {
this.processInstanceDetails = processDetails;
this.canCancelProcess = this.checkCanCancelProcess();
@@ -82,9 +81,4 @@ export class CancelProcessDirective implements OnInit, OnDestroy {
this.error.emit('Permission denied, only process initiator can cancel the process');
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -15,18 +15,18 @@
* limitations under the License.
*/
import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges, OnDestroy, ViewEncapsulation } from '@angular/core';
import { FormBuilder, AbstractControl, FormGroup, FormControl } from '@angular/forms';
import { Component, DestroyRef, EventEmitter, inject, Input, OnChanges, OnInit, Output, SimpleChanges, ViewEncapsulation } from '@angular/core';
import { AbstractControl, FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { DateAdapter } from '@angular/material/core';
import { MatDialog } from '@angular/material/dialog';
import { debounceTime, filter, takeUntil, finalize, switchMap, tap } from 'rxjs/operators';
import { Subject, Observable, Subscription } from 'rxjs';
import { debounceTime, filter, finalize, switchMap, tap } from 'rxjs/operators';
import { Observable, Subscription } from 'rxjs';
import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service';
import {
ProcessFilterCloudModel,
ProcessFilterProperties,
ProcessFilterAction,
ProcessFilterCloudModel,
ProcessFilterOptions,
ProcessFilterProperties,
ProcessSortFilterProperty
} from '../models/process-filter-cloud.model';
import { DateFnsUtils, TranslationService, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
@@ -37,6 +37,7 @@ import { DateCloudFilterType, DateRangeFilter } from '../../../models/date-cloud
import { IdentityUserModel } from '../../../people/models/identity-user.model';
import { Environment } from '../../../common/interface/environment.interface';
import { endOfDay, isValid, startOfDay } from 'date-fns';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
export const PROCESS_FILTER_ACTION_SAVE = 'save';
export const PROCESS_FILTER_ACTION_SAVE_AS = 'saveAs';
@@ -71,7 +72,7 @@ interface ProcessFilterFormProps {
styleUrls: ['./edit-process-filter-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDestroy {
export class EditProcessFilterCloudComponent implements OnInit, OnChanges {
/** The name of the application. */
@Input()
appName: string = '';
@@ -184,10 +185,11 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
appVersionOptions: ProcessFilterOptions[] = [];
initiatorOptions: IdentityUserModel[] = [];
private onDestroy$ = new Subject<boolean>();
isLoading: boolean = false;
private filterChangeSub: Subscription;
private readonly destroyRef = inject(DestroyRef);
constructor(
private formBuilder: FormBuilder,
public dialog: MatDialog,
@@ -202,7 +204,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
ngOnInit() {
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((locale) => this.dateAdapter.setLocale(locale));
}
@@ -212,12 +214,6 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
this.retrieveProcessFilterAndBuildForm();
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
filterTracker(_index: number, item: ProcessFilterProperties) {
return item.key;
}
@@ -284,7 +280,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
.pipe(
debounceTime(500),
filter(() => this.isFormValid()),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((formValues: Partial<ProcessFilterCloudModel>) => {
this.setLastModifiedFromFilter(formValues);

View File

@@ -15,16 +15,28 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import {
Component,
DestroyRef,
EventEmitter,
inject,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewEncapsulation
} from '@angular/core';
import { Observable } from 'rxjs';
import { ProcessFilterCloudService } from '../services/process-filter-cloud.service';
import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model';
import { AppConfigService, TranslationService } from '@alfresco/adf-core';
import { FilterParamsModel } from '../../../task/task-filters/models/filter-cloud.model';
import { debounceTime, takeUntil, tap } from 'rxjs/operators';
import { debounceTime, tap } from 'rxjs/operators';
import { ProcessListCloudService } from '../../../process/process-list/services/process-list-cloud.service';
import { PROCESS_SEARCH_API_METHOD_TOKEN } from '../../../services/cloud-token.service';
import { ProcessFilterCloudAdapter } from '../../process-list/models/process-cloud-query-request.model';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-process-filters',
@@ -32,7 +44,7 @@ import { ProcessFilterCloudAdapter } from '../../process-list/models/process-clo
styleUrls: ['./process-filters-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestroy {
export class ProcessFiltersCloudComponent implements OnInit, OnChanges {
/** (required) The application name */
@Input()
appName: string = '';
@@ -73,8 +85,7 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestro
currentFiltersValues: { [key: string]: number } = {};
updatedFiltersSet = new Set<string>();
private onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
private readonly processFilterCloudService = inject(ProcessFilterCloudService);
private readonly translationService = inject(TranslationService);
private readonly appConfigService = inject(AppConfigService);
@@ -108,7 +119,7 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestro
getFilters(appName: string): void {
this.filters$ = this.processFilterCloudService.getProcessFilters(appName);
this.filters$.pipe(takeUntil(this.onDestroy$)).subscribe({
this.filters$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
next: (res) => {
this.resetFilter();
this.filters = res || [];
@@ -240,11 +251,6 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestro
this.currentFilter = undefined;
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
isActiveFilter(filter: ProcessFilterCloudModel): boolean {
return this.currentFilter.name === filter.name;
}
@@ -253,7 +259,7 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestro
if (this.appName && this.enableNotifications) {
this.processFilterCloudService
.getProcessNotificationSubscription(this.appName)
.pipe(debounceTime(1000), takeUntil(this.onDestroy$))
.pipe(debounceTime(1000), takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.updateFilterCounters();
});
@@ -310,7 +316,7 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestro
*
*/
getFilterKeysAfterExternalRefreshing(): void {
this.processFilterCloudService.filterKeyToBeRefreshed$.pipe(takeUntil(this.onDestroy$)).subscribe((filterKey: string) => {
this.processFilterCloudService.filterKeyToBeRefreshed$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((filterKey: string) => {
this.updatedFiltersSet.delete(filterKey);
});
}

View File

@@ -15,19 +15,28 @@
* limitations under the License.
*/
import { Component, Input, OnChanges, OnInit, OnDestroy, EventEmitter, ViewEncapsulation, Output } from '@angular/core';
import {
Component,
DestroyRef,
EventEmitter,
inject,
Input,
OnChanges,
OnInit,
Output,
ViewEncapsulation
} from '@angular/core';
import {
AppConfigService,
CardViewBaseItemModel,
CardViewDateItemModel,
CardViewItem,
CardViewTextItemModel,
TranslationService,
AppConfigService,
CardViewDateItemModel,
CardViewBaseItemModel
TranslationService
} from '@alfresco/adf-core';
import { ProcessInstanceCloud } from '../../start-process/models/process-instance-cloud.model';
import { ProcessCloudService } from '../../services/process-cloud.service';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-process-header',
@@ -36,7 +45,7 @@ import { Subject } from 'rxjs';
styleUrls: ['./process-header-cloud.component.scss'],
host: { class: 'adf-cloud-process-header' }
})
export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy {
export class ProcessHeaderCloudComponent implements OnChanges, OnInit {
/** (Required) The name of the application. */
@Input()
appName: string = '';
@@ -54,7 +63,7 @@ export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy
dateFormat: string;
dateLocale: string;
private onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
constructor(
private processCloudService: ProcessCloudService,
@@ -66,7 +75,7 @@ export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy
this.dateFormat = this.appConfig.get('adf-cloud-process-header.defaultDateFormat');
this.dateLocale = this.appConfig.get('dateValues.defaultDateLocale');
this.processCloudService.dataChangesDetected.pipe(takeUntil(this.onDestroy$)).subscribe((processDetails) => this.onLoaded(processDetails));
this.processCloudService.dataChangesDetected.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((processDetails) => this.onLoaded(processDetails));
}
ngOnChanges() {
@@ -152,9 +161,4 @@ export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy
private isValidSelection(filteredProperties: string[], cardItem: CardViewBaseItemModel): boolean {
return filteredProperties ? filteredProperties.indexOf(cardItem.key) >= 0 : true;
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -16,47 +16,53 @@
*/
import {
Component,
ViewEncapsulation,
OnChanges,
AfterContentInit,
Component,
ContentChild,
Output,
EventEmitter,
SimpleChanges,
Input,
ViewChild,
Inject,
OnDestroy,
Optional
Input,
OnChanges,
Optional,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import {
DataTableSchema,
PaginatedComponent,
CustomEmptyContentTemplateDirective,
AppConfigService,
UserPreferencesService,
PaginationModel,
UserPreferenceValues,
DataRowEvent,
CustomEmptyContentTemplateDirective,
CustomLoadingContentTemplateDirective,
DataCellEvent,
DataColumn,
DataRowActionEvent,
DataRowEvent,
DataTableComponent,
DataColumn
DataTableSchema,
PaginatedComponent,
PaginationModel,
UserPreferencesService,
UserPreferenceValues
} from '@alfresco/adf-core';
import { ProcessListCloudService } from '../services/process-list-cloud.service';
import { BehaviorSubject, combineLatest, Subject } from 'rxjs';
import { processCloudPresetsDefaultModel } from '../models/process-cloud-preset.model';
import { ProcessListRequestModel, ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
import { filter, map, switchMap, take, takeUntil } from 'rxjs/operators';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, PROCESS_SEARCH_API_METHOD_TOKEN } from '../../../services/cloud-token.service';
import {
PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN,
PROCESS_SEARCH_API_METHOD_TOKEN
} from '../../../services/cloud-token.service';
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
import { ProcessListDatatableAdapter } from '../datatable/process-list-datatable-adapter';
import { ProcessListDataColumnCustomData, PROCESS_LIST_CUSTOM_VARIABLE_COLUMN } from '../../../models/data-column-custom-data';
import {
PROCESS_LIST_CUSTOM_VARIABLE_COLUMN,
ProcessListDataColumnCustomData
} from '../../../models/data-column-custom-data';
import { VariableMapperService } from '../../../services/variable-mapper.sevice';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
const PRESET_KEY = 'adf-cloud-process-list.presets';
@@ -66,7 +72,9 @@ const PRESET_KEY = 'adf-cloud-process-list.presets';
styleUrls: ['./process-list-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataColumnCustomData> implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy {
export class ProcessListCloudComponent
extends DataTableSchema<ProcessListDataColumnCustomData>
implements OnChanges, AfterContentInit, PaginatedComponent {
@ViewChild(DataTableComponent) dataTable: DataTableComponent;
@@ -255,8 +263,6 @@ export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataCo
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
private onDestroy$ = new Subject<boolean>();
pagination: BehaviorSubject<PaginationModel>;
size: number;
skipCount: number = 0;
@@ -299,9 +305,7 @@ export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataCo
this.isColumnSchemaCreated$,
this.fetchProcessesTrigger$
]).pipe(
filter(([isColumnSchemaCreated]) => {
return isColumnSchemaCreated;
}),
filter(([isColumnSchemaCreated]) => isColumnSchemaCreated),
switchMap(() => {
if (this.searchMethod === 'POST') {
const requestNode = this.createProcessListRequestNode();
@@ -313,7 +317,7 @@ export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataCo
return this.processListCloudService.getProcessByRequest(requestNode).pipe(take(1));
}
}),
takeUntil(this.onDestroy$)
takeUntilDestroyed()
).subscribe({
next: (processes) => {
this.rows = this.variableMapperService.mapVariablesByColumnTitle(processes.list.entries, this.columns);
@@ -367,12 +371,6 @@ export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataCo
this.createDatatableSchema();
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngOnChanges(changes: SimpleChanges) {
if (this.isPropertyChanged(changes, 'sorting')) {
this.formatSorting(changes['sorting'].currentValue);

View File

@@ -17,12 +17,12 @@
import {
Component,
DestroyRef,
EventEmitter,
HostListener,
inject,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
@@ -30,19 +30,26 @@ import {
ViewEncapsulation
} from '@angular/core';
import { ContentLinkModel, FORM_FIELD_VALIDATORS, FormFieldValidator, FormModel, TranslationService } from '@alfresco/adf-core';
import {
ContentLinkModel,
FORM_FIELD_VALIDATORS,
FormFieldValidator,
FormModel,
TranslationService
} from '@alfresco/adf-core';
import { AbstractControl, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
import { catchError, debounceTime, takeUntil } from 'rxjs/operators';
import { catchError, debounceTime } from 'rxjs/operators';
import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
import { ProcessPayloadCloud } from '../models/process-payload-cloud.model';
import { ProcessWithFormPayloadCloud } from '../models/process-with-form-payload-cloud.model';
import { StartProcessCloudService } from '../services/start-process-cloud.service';
import { forkJoin, of, Subject } from 'rxjs';
import { forkJoin, of } from 'rxjs';
import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model';
import { TaskVariableCloud } from '../../../form/models/task-variable-cloud.model';
import { ProcessNameCloudPipe } from '../../../pipes/process-name-cloud.pipe';
import { FormCloudDisplayModeConfiguration } from '../../../services/form-fields.interfaces';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
const MAX_NAME_LENGTH: number = 255;
const PROCESS_DEFINITION_DEBOUNCE: number = 300;
@@ -53,7 +60,7 @@ const PROCESS_DEFINITION_DEBOUNCE: number = 300;
styleUrls: ['./start-process-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy {
export class StartProcessCloudComponent implements OnChanges, OnInit {
@ViewChild(MatAutocompleteTrigger)
inputAutocomplete: MatAutocompleteTrigger;
@@ -133,7 +140,6 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy
resolvedValues?: TaskVariableCloud[];
customOutcome: string;
protected onDestroy$ = new Subject<boolean>();
isProcessStarting = false;
isFormCloudLoaded = false;
@@ -154,6 +160,7 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy
processDefinition: new FormControl('', [Validators.required, this.processDefinitionNameValidator()])
});
private readonly destroyRef = inject(DestroyRef);
private readonly startProcessCloudService = inject(StartProcessCloudService);
private readonly processNameCloudPipe = inject(ProcessNameCloudPipe);
@@ -204,7 +211,7 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy
this.processDefinition.setValue(this.processDefinitionName);
this.processDefinition.valueChanges
.pipe(debounceTime(PROCESS_DEFINITION_DEBOUNCE))
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((processDefinitionName) => {
this.selectProcessDefinitionByProcessDefinitionName(processDefinitionName);
});
@@ -327,7 +334,7 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy
this.startProcessCloudService
.getProcessDefinitions(this.appName)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(
(processDefinitionRepresentations: ProcessDefinitionCloud[]) => {
this.processDefinitionList = processDefinitionRepresentations;
@@ -498,9 +505,4 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy
this.processInstanceName.markAsDirty();
this.processInstanceName.markAsTouched();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -15,21 +15,21 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, OnDestroy, ViewChild } from '@angular/core';
import { Component, DestroyRef, EventEmitter, inject, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { Observable, Subject } from 'rxjs';
import { UntypedFormBuilder, Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { DateFnsUtils, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
import { PeopleCloudComponent } from '../../../people/components/people-cloud.component';
import { GroupCloudComponent } from '../../../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';
import { TaskPriorityOption } from '../../models/task.model';
import { IdentityUserService } from '../../../people/services/identity-user.service';
import { IdentityUserModel } from '../../../people/models/identity-user.model';
import { DateFnsAdapter, MAT_DATE_FNS_FORMATS } from '@angular/material-date-fns-adapter';
import { isValid, parse } from 'date-fns';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
const MAX_NAME_LENGTH = 255;
const DATE_FORMAT: string = 'dd/MM/yyyy';
@@ -44,7 +44,7 @@ const DATE_FORMAT: string = 'dd/MM/yyyy';
],
encapsulation: ViewEncapsulation.None
})
export class StartTaskCloudComponent implements OnInit, OnDestroy {
export class StartTaskCloudComponent implements OnInit {
/** (required) Name of the app. */
@Input()
appName: string = '';
@@ -99,7 +99,8 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy {
private assigneeForm = new UntypedFormControl('');
private groupForm = new UntypedFormControl('');
private onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
constructor(
private taskService: TaskCloudService,
@@ -112,18 +113,13 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy {
ngOnInit() {
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((locale) => this.dateAdapter.setLocale(DateFnsUtils.getLocaleFromString(locale)));
this.loadCurrentUser();
this.buildForm();
this.loadDefaultPriorities();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
buildForm() {
this.taskForm = this.formBuilder.group({
name: new UntypedFormControl(this.name, [Validators.required, Validators.maxLength(this.getMaxNameLength()), this.whitespaceValidator]),

View File

@@ -15,13 +15,12 @@
* limitations under the License.
*/
import { Directive, EventEmitter, Input, OnDestroy, Output } from '@angular/core';
import { Subject } from 'rxjs';
import { DestroyRef, Directive, EventEmitter, inject, Input, Output } from '@angular/core';
import { FilterParamsModel } from '../models/filter-cloud.model';
@Directive()
// eslint-disable-next-line @angular-eslint/directive-class-suffix
export abstract class BaseTaskFiltersCloudComponent implements OnDestroy {
export abstract class BaseTaskFiltersCloudComponent {
/** Display filters available to the current user for the application with the specified name. */
@Input()
appName: string = '';
@@ -48,12 +47,7 @@ export abstract class BaseTaskFiltersCloudComponent implements OnDestroy {
counters: { [key: string]: number } = {};
updatedCountersSet = new Set<string>();
protected onDestroy$ = new Subject<boolean>();
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
protected destroyRef = inject(DestroyRef);
wasFilterUpdated(filterKey: string): boolean {
return this.updatedCountersSet.has(filterKey);

View File

@@ -15,14 +15,14 @@
* limitations under the License.
*/
import { OnChanges, SimpleChanges, OnInit, OnDestroy, Directive, Input, Output, EventEmitter, inject } from '@angular/core';
import { DestroyRef, Directive, EventEmitter, inject, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { AssignmentType, FilterOptions, TaskFilterAction, TaskFilterProperties, TaskStatusFilter } from '../../models/filter-cloud.model';
import { TaskCloudService } from './../../../services/task-cloud.service';
import { AppsProcessCloudService } from './../../../../app/services/apps-process-cloud.service';
import { DateCloudFilterType, DateRangeFilter } from '../../../../models/date-cloud-filter.model';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { debounceTime, filter, finalize, switchMap, takeUntil } from 'rxjs/operators';
import { Observable, Subject } from 'rxjs';
import { debounceTime, filter, finalize, switchMap } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { DateAdapter } from '@angular/material/core';
import { DateFnsUtils, TranslationService, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
import { TaskFilterDialogCloudComponent } from '../task-filter-dialog/task-filter-dialog-cloud.component';
@@ -32,6 +32,7 @@ import { IdentityGroupModel } from '../../../../group/models/identity-group.mode
import { MatSelectChange } from '@angular/material/select';
import { Environment } from '../../../../common/interface/environment.interface';
import { isValid } from 'date-fns';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
/* eslint-disable @typescript-eslint/naming-convention */
@@ -54,7 +55,7 @@ const ORDER_PROPERTY = 'order';
@Directive()
// eslint-disable-next-line @angular-eslint/directive-class-suffix
export abstract class BaseEditTaskFilterCloudComponent<T> implements OnInit, OnChanges, OnDestroy {
export abstract class BaseEditTaskFilterCloudComponent<T> implements OnInit, OnChanges {
public static ACTIONS_DISABLED_BY_DEFAULT = [ACTION_SAVE, ACTION_DELETE];
/** (required) Name of the app. */
@@ -133,9 +134,9 @@ export abstract class BaseEditTaskFilterCloudComponent<T> implements OnInit, OnC
@Output()
filterChange = new EventEmitter<T>();
protected onDestroy$ = new Subject<boolean>();
isLoading: boolean = false;
protected destroyRef = inject(DestroyRef);
protected translateService = inject(TranslationService);
protected taskCloudService = inject(TaskCloudService);
protected userPreferencesService = inject(UserPreferencesService);
@@ -147,7 +148,7 @@ export abstract class BaseEditTaskFilterCloudComponent<T> implements OnInit, OnC
ngOnInit() {
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((locale) => this.dateAdapter.setLocale(locale));
}
@@ -158,11 +159,6 @@ export abstract class BaseEditTaskFilterCloudComponent<T> implements OnInit, OnC
}
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
createFilterActions(): TaskFilterAction[] {
return [
{
@@ -430,7 +426,7 @@ export abstract class BaseEditTaskFilterCloudComponent<T> implements OnInit, OnC
.pipe(
debounceTime(500),
filter(() => this.isFormValid()),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((formValues) => {
this.assignNewFilter(formValues);
@@ -471,7 +467,7 @@ export abstract class BaseEditTaskFilterCloudComponent<T> implements OnInit, OnC
this.getTaskFilterById(this.appName, this.id)
.pipe(
finalize(() => (this.isLoading = false)),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe((response) => {
this.taskFilter = response;
@@ -490,14 +486,14 @@ export abstract class BaseEditTaskFilterCloudComponent<T> implements OnInit, OnC
return filters.length === 0;
}),
switchMap(() => this.restoreDefaultTaskFilters()),
takeUntil(this.onDestroy$)
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {});
}
save(saveAction: TaskFilterAction): void {
this.updateFilter(this.changedTaskFilter)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
saveAction.filter = this.changedTaskFilter;
this.action.emit(saveAction);

View File

@@ -15,12 +15,12 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, inject } from '@angular/core';
import { takeUntil } from 'rxjs/operators';
import { Component, inject, ViewEncapsulation } from '@angular/core';
import { Observable } from 'rxjs';
import { TaskFilterProperties, TaskFilterAction, ServiceTaskFilterCloudModel } from '../../models/filter-cloud.model';
import { ServiceTaskFilterCloudModel, TaskFilterAction, TaskFilterProperties } from '../../models/filter-cloud.model';
import { ServiceTaskFilterCloudService } from '../../services/service-task-filter-cloud.service';
import { BaseEditTaskFilterCloudComponent, DropdownOption } from './base-edit-task-filter-cloud.component';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-edit-service-task-filter',
@@ -64,7 +64,7 @@ export class EditServiceTaskFilterCloudComponent extends BaseEditTaskFilterCloud
protected addFilter(filterToAdd: ServiceTaskFilterCloudModel): Observable<any> {
return this.serviceTaskFilterCloudService
.addFilter(filterToAdd)
.pipe(takeUntil(this.onDestroy$));
.pipe(takeUntilDestroyed(this.destroyRef));
}
isDisabledForDefaultFilters(action: TaskFilterAction): boolean {

View File

@@ -15,14 +15,20 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, inject } from '@angular/core';
import { takeUntil, map } from 'rxjs/operators';
import { Component, inject, ViewEncapsulation } from '@angular/core';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { TaskFilterCloudModel, TaskFilterProperties, TaskFilterAction, TaskStatusFilter } from '../../models/filter-cloud.model';
import {
TaskFilterAction,
TaskFilterCloudModel,
TaskFilterProperties,
TaskStatusFilter
} from '../../models/filter-cloud.model';
import { TaskFilterCloudService } from '../../services/task-filter-cloud.service';
import { DateCloudFilterType } from '../../../../models/date-cloud-filter.model';
import { BaseEditTaskFilterCloudComponent, DropdownOption } from './base-edit-task-filter-cloud.component';
import { set } from 'date-fns';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-edit-task-filter',
@@ -98,7 +104,7 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
protected addFilter(filterToAdd: TaskFilterCloudModel): Observable<any> {
return this.taskFilterCloudService
.addFilter(filterToAdd)
.pipe(takeUntil(this.onDestroy$));
.pipe(takeUntilDestroyed(this.destroyRef));
}
isDisabledForDefaultFilters(action: TaskFilterAction): boolean {

View File

@@ -15,13 +15,22 @@
* limitations under the License.
*/
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation, inject } from '@angular/core';
import {
Component,
EventEmitter,
inject,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewEncapsulation
} from '@angular/core';
import { Observable } from 'rxjs';
import { FilterParamsModel, ServiceTaskFilterCloudModel } from '../models/filter-cloud.model';
import { takeUntil } from 'rxjs/operators';
import { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component';
import { ServiceTaskFilterCloudService } from '../services/service-task-filter-cloud.service';
import { TranslationService } from '@alfresco/adf-core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-service-task-filters',
@@ -67,7 +76,7 @@ export class ServiceTaskFiltersCloudComponent extends BaseTaskFiltersCloudCompon
getFilters(appName: string): void {
this.filters$ = this.serviceTaskFilterCloudService.getTaskListFilters(appName);
this.filters$.pipe(takeUntil(this.onDestroy$)).subscribe(
this.filters$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(
(res: ServiceTaskFilterCloudModel[]) => {
this.resetFilter();
this.filters = res || [];

View File

@@ -15,18 +15,28 @@
* limitations under the License.
*/
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation, inject } from '@angular/core';
import {
Component,
EventEmitter,
inject,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewEncapsulation
} from '@angular/core';
import { Observable } from 'rxjs';
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
import { TaskFilterCloudModel, FilterParamsModel } from '../models/filter-cloud.model';
import { FilterParamsModel, TaskFilterCloudModel } from '../models/filter-cloud.model';
import { AppConfigService, TranslationService } from '@alfresco/adf-core';
import { debounceTime, takeUntil, tap } from 'rxjs/operators';
import { debounceTime, tap } from 'rxjs/operators';
import { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component';
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
import { TaskCloudEngineEvent } from '../../../models/engine-event-cloud.model';
import { TaskListCloudService } from '../../task-list/services/task-list-cloud.service';
import { TaskFilterCloudAdapter } from '../../../models/filter-cloud-model';
import { TASK_SEARCH_API_METHOD_TOKEN } from '../../../services/cloud-token.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-task-filters',
@@ -88,7 +98,7 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
getFilters(appName: string): void {
this.filters$ = this.taskFilterCloudService.getTaskListFilters(appName);
this.filters$.pipe(takeUntil(this.onDestroy$)).subscribe(
this.filters$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(
(res) => {
this.resetFilter();
this.filters = res || [];
@@ -267,7 +277,7 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
*
*/
getFilterKeysAfterExternalRefreshing(): void {
this.taskFilterCloudService.filterKeyToBeRefreshed$.pipe(takeUntil(this.onDestroy$)).subscribe((filterKey: string) => {
this.taskFilterCloudService.filterKeyToBeRefreshed$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((filterKey: string) => {
this.updatedCountersSet.delete(filterKey);
});
}

View File

@@ -15,17 +15,28 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation, OnDestroy, ViewChild } from '@angular/core';
import {
Component,
DestroyRef,
EventEmitter,
inject,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
import { TaskCloudService } from '../../services/task-cloud.service';
import { FormRenderingService, FormModel, ContentLinkModel, FormOutcomeEvent, FormFieldValidator, FORM_FIELD_VALIDATORS } from '@alfresco/adf-core';
import { ContentLinkModel, FORM_FIELD_VALIDATORS, FormFieldValidator, FormModel, FormOutcomeEvent, FormRenderingService } from '@alfresco/adf-core';
import { AttachFileCloudWidgetComponent } from '../../../form/components/widgets/attach-file/attach-file-cloud-widget.component';
import { DropdownCloudWidgetComponent } from '../../../form/components/widgets/dropdown/dropdown-cloud.widget';
import { DateCloudWidgetComponent } from '../../../form/components/widgets/date/date-cloud.widget';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { FormCloudDisplayModeConfiguration } from '../../../services/form-fields.interfaces';
import { FormCloudComponent } from '../../../form/components/form-cloud.component';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-task-form',
@@ -33,7 +44,7 @@ import { FormCloudComponent } from '../../../form/components/form-cloud.componen
styleUrls: ['./task-form-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TaskFormCloudComponent implements OnInit, OnChanges, OnDestroy {
export class TaskFormCloudComponent implements OnInit, OnChanges {
/** App id to fetch corresponding form and values. */
@Input()
appName: string = '';
@@ -138,7 +149,8 @@ export class TaskFormCloudComponent implements OnInit, OnChanges, OnDestroy {
candidateGroups: string[] = [];
loading: boolean = false;
onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
constructor(private taskCloudService: TaskCloudService, private formRenderingService: FormRenderingService) {
this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileCloudWidgetComponent, true);
@@ -176,7 +188,7 @@ export class TaskFormCloudComponent implements OnInit, OnChanges, OnDestroy {
this.loading = true;
this.taskCloudService
.getTaskById(this.appName, this.taskId)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((details) => {
this.taskDetails = details;
this.loading = false;
@@ -271,9 +283,4 @@ export class TaskFormCloudComponent implements OnInit, OnChanges, OnDestroy {
onDisplayModeOff(displayModeConfiguration: FormCloudDisplayModeConfiguration) {
this.displayModeOff.emit(displayModeConfiguration);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -15,25 +15,36 @@
* limitations under the License.
*/
import { Component, Input, EventEmitter, Output, OnDestroy, OnChanges, OnInit, ViewEncapsulation } from '@angular/core';
import { takeUntil, concatMap, catchError, finalize } from 'rxjs/operators';
import { Subject, of, forkJoin } from 'rxjs';
import {
CardViewDateItemModel,
CardViewItem,
CardViewTextItemModel,
CardViewBaseItemModel,
CardViewArrayItemModel,
TranslationService,
Component,
DestroyRef,
EventEmitter,
inject,
Input,
OnChanges,
OnInit,
Output,
ViewEncapsulation
} from '@angular/core';
import { catchError, concatMap, finalize } from 'rxjs/operators';
import { forkJoin, of } from 'rxjs';
import {
AppConfigService,
UpdateNotification,
CardViewUpdateService,
CardViewDatetimeItemModel,
CardViewArrayItem,
CardViewSelectItemModel
CardViewArrayItemModel,
CardViewBaseItemModel,
CardViewDateItemModel,
CardViewDatetimeItemModel,
CardViewItem,
CardViewSelectItemModel,
CardViewTextItemModel,
CardViewUpdateService,
TranslationService,
UpdateNotification
} from '@alfresco/adf-core';
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
import { TaskCloudService } from '../../services/task-cloud.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'adf-cloud-task-header',
@@ -41,7 +52,7 @@ import { TaskCloudService } from '../../services/task-cloud.service';
styleUrls: ['./task-header-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
export class TaskHeaderCloudComponent implements OnInit, OnChanges {
/** (Required) The name of the application. */
@Input()
@@ -79,7 +90,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
isLoading = true;
processInstanceId: string;
private onDestroy$ = new Subject<boolean>();
private readonly destroyRef = inject(DestroyRef);
constructor(
private taskCloudService: TaskCloudService,
@@ -93,13 +104,13 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
ngOnInit() {
this.taskCloudService.dataChangesDetected$
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.loadTaskDetailsById(this.appName, this.taskId);
});
this.cardViewUpdateService.itemUpdated$
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(this.updateTaskDetails.bind(this)
);
}
@@ -346,9 +357,4 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
private isValidSelection(filteredProperties: string[], cardItem: CardViewBaseItemModel): boolean {
return filteredProperties ? filteredProperties.indexOf(cardItem.key) >= 0 : true;
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}

View File

@@ -15,38 +15,51 @@
* limitations under the License.
*/
import { OnChanges, Input, SimpleChanges, Output, EventEmitter, ContentChild, AfterContentInit, OnDestroy, OnInit, Directive } from '@angular/core';
import {
AfterContentInit,
ContentChild,
DestroyRef,
Directive,
EventEmitter,
inject,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges
} from '@angular/core';
import {
AppConfigService,
UserPreferencesService,
DataTableSchema,
UserPreferenceValues,
PaginatedComponent,
PaginationModel,
DataRowEvent,
CustomEmptyContentTemplateDirective,
DataCellEvent,
DataRowActionEvent,
DataRow,
DataColumn,
ObjectDataTableAdapter
DataRow,
DataRowActionEvent,
DataRowEvent,
DataTableSchema,
ObjectDataTableAdapter,
PaginatedComponent,
PaginationModel,
UserPreferencesService,
UserPreferenceValues
} from '@alfresco/adf-core';
import { taskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model';
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { BehaviorSubject, Observable } from 'rxjs';
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
import { map, take, takeUntil } from 'rxjs/operators';
import { map, take } from 'rxjs/operators';
import { TaskCloudService } from '../../services/task-cloud.service';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { TasksListCloudPreferences } from '../models/tasks-cloud-preferences';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Directive()
// eslint-disable-next-line @angular-eslint/directive-class-suffix
export abstract class BaseTaskListCloudComponent<T = unknown>
extends DataTableSchema<T>
implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit
// eslint-disable-next-line @typescript-eslint/brace-style
{
implements OnChanges, AfterContentInit, PaginatedComponent, OnInit {
@ContentChild(CustomEmptyContentTemplateDirective)
emptyCustomContent: CustomEmptyContentTemplateDirective;
@@ -138,11 +151,11 @@ export abstract class BaseTaskListCloudComponent<T = unknown>
private defaultSorting = { key: 'startDate', direction: 'desc' };
boundReplacePriorityValues: (row: DataRow, col: DataColumn) => any;
private onDestroy$ = new Subject<boolean>();
protected abstract isLoading$: Observable<boolean>;
protected isLoadingPreferences$ = new BehaviorSubject<boolean>(true);
protected readonly destroyRef = inject(DestroyRef);
constructor(
appConfigService: AppConfigService,
private taskCloudService: TaskCloudService,
@@ -165,7 +178,7 @@ export abstract class BaseTaskListCloudComponent<T = unknown>
ngOnInit() {
this.userPreferences
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntil(this.onDestroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((pageSize) => (this.size = pageSize));
}
@@ -179,11 +192,6 @@ export abstract class BaseTaskListCloudComponent<T = unknown>
this.reload();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
private retrieveTasksPreferences(): void {
this.isLoadingPreferences$.next(true);
this.cloudPreferenceService

View File

@@ -15,15 +15,16 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, Input, Inject, OnDestroy } from '@angular/core';
import { Component, Inject, Input, ViewEncapsulation } from '@angular/core';
import { AppConfigService, UserPreferencesService } from '@alfresco/adf-core';
import { ServiceTaskQueryCloudRequestModel } from '../models/service-task-cloud.model';
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
import { TaskCloudService } from '../../services/task-cloud.service';
import { Subject, combineLatest, BehaviorSubject } from 'rxjs';
import { BehaviorSubject, combineLatest } from 'rxjs';
import { PreferenceCloudServiceInterface, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/public-api';
import { map, takeUntil } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
const PRESET_KEY = 'adf-cloud-service-task-list.presets';
@@ -33,12 +34,10 @@ const PRESET_KEY = 'adf-cloud-service-task-list.presets';
styleUrls: ['./base-task-list-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent implements OnDestroy {
export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent {
@Input()
queryParams: { [key: string]: any } = {};
private onDestroyServiceTaskList$ = new Subject<boolean>();
private isReloadingSubject$ = new BehaviorSubject<boolean>(false);
isLoading$ = combineLatest([this.isLoadingPreferences$, this.isReloadingSubject$]).pipe(
map(([isLoadingPreferences, isReloading]) => isLoadingPreferences || isReloading)
@@ -54,11 +53,6 @@ export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent im
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY, cloudPreferenceService);
}
ngOnDestroy() {
this.onDestroyServiceTaskList$.next(true);
this.onDestroyServiceTaskList$.complete();
}
reload() {
this.isReloadingSubject$.next(true);
@@ -66,7 +60,7 @@ export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent im
if (this.requestNode.appName || this.requestNode.appName === '') {
combineLatest([this.serviceTaskListCloudService.getServiceTaskByRequest(this.requestNode), this.isColumnSchemaCreated$])
.pipe(takeUntil(this.onDestroyServiceTaskList$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(
([tasks]) => {
this.rows = tasks.list.entries;

View File

@@ -15,22 +15,27 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, Input, Inject, OnDestroy, Optional } from '@angular/core';
import { Component, Inject, Input, Optional, ViewEncapsulation } from '@angular/core';
import { AppConfigService, UserPreferencesService } from '@alfresco/adf-core';
import { TaskListRequestModel, TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
import { TaskCloudService } from '../../services/task-cloud.service';
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN, TASK_SEARCH_API_METHOD_TOKEN } from '../../../services/cloud-token.service';
import {
TASK_LIST_CLOUD_TOKEN,
TASK_LIST_PREFERENCES_SERVICE_TOKEN,
TASK_SEARCH_API_METHOD_TOKEN
} from '../../../services/cloud-token.service';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
import { Subject, BehaviorSubject, combineLatest } from 'rxjs';
import { filter, map, switchMap, take, takeUntil } from 'rxjs/operators';
import { BehaviorSubject, combineLatest, Subject } from 'rxjs';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { VariableMapperService } from '../../../services/variable-mapper.sevice';
import { ProcessListDataColumnCustomData } from '../../../models/data-column-custom-data';
import { TaskCloudModel } from '../../../models/task-cloud.model';
import { PaginatedEntries } from '@alfresco/js-api';
import { TaskInstanceCloudListViewModel } from '../models/task-cloud-view.model';
import { TasksListDatatableAdapter } from '../datatable/task-list-datatable-adapter';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
const PRESET_KEY = 'adf-cloud-task-list.presets';
@@ -40,7 +45,7 @@ const PRESET_KEY = 'adf-cloud-task-list.presets';
styleUrls: ['./base-task-list-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessListDataColumnCustomData> implements OnDestroy {
export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessListDataColumnCustomData> {
/**
* The assignee of the process. Possible values are: "assignee" (the current user is the assignee),
* "candidate" (the current user is a task candidate", "group_x" (the task is assigned to a group
@@ -187,8 +192,6 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
@Input()
completedByUsers: string[] = [];
private onDestroyTaskList$ = new Subject<boolean>();
rows: TaskInstanceCloudListViewModel[] = [];
dataAdapter: TasksListDatatableAdapter | undefined;
@@ -223,7 +226,7 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
return this.taskListCloudService.getTaskByRequest(requestNode);
}
}),
takeUntil(this.onDestroyTaskList$)
takeUntilDestroyed()
)
.subscribe({
next: (tasks: { list: PaginatedEntries<TaskCloudModel> }) => {
@@ -247,11 +250,6 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
});
}
ngOnDestroy() {
this.onDestroyTaskList$.next(true);
this.onDestroyTaskList$.complete();
}
reload() {
this.isReloadingSubject$.next(true);
this.fetchProcessesTrigger$.next();