mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
Migrate to new animations api (#12078)
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/animations": ">=20.3.25",
|
||||
"@angular/cdk": ">=20.2.14",
|
||||
"@angular/common": ">=20.3.25",
|
||||
"@angular/compiler": ">=20.3.25",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { FORM_CLOUD_SERVICE_FIELD_VALIDATORS_TOKEN, FormCloudService } from './form-cloud.service';
|
||||
import { BehaviorSubject, firstValueFrom, of } from 'rxjs';
|
||||
import { BehaviorSubject, firstValueFrom, lastValueFrom, of } from 'rxjs';
|
||||
import { AdfHttpClient } from '@alfresco/adf-core/api';
|
||||
import { FORM_FIELD_VALIDATORS, FormFieldValidator, NoopAuthModule } from '@alfresco/adf-core';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
@@ -59,18 +59,16 @@ describe('Form Cloud service', () => {
|
||||
});
|
||||
|
||||
describe('Form tests', () => {
|
||||
it('should fetch and parse form', (done) => {
|
||||
it('should fetch and parse form', async () => {
|
||||
const formId = 'form-id';
|
||||
requestSpy.and.returnValue(Promise.resolve(mockFormResponseBody));
|
||||
|
||||
service.getForm(appName, formId).subscribe((result) => {
|
||||
expect(result).toBeDefined();
|
||||
expect(result.formRepresentation.id).toBe(formId);
|
||||
expect(result.formRepresentation.name).toBe('task-form');
|
||||
expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/form/v1/forms/${formId}`);
|
||||
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('GET');
|
||||
done();
|
||||
});
|
||||
const result = await lastValueFrom(service.getForm(appName, formId));
|
||||
expect(result).toBeDefined();
|
||||
expect(result.formRepresentation.id).toBe(formId);
|
||||
expect(result.formRepresentation.name).toBe('task-form');
|
||||
expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/form/v1/forms/${formId}`);
|
||||
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('GET');
|
||||
});
|
||||
|
||||
it('should parse valid form json ', () => {
|
||||
@@ -134,7 +132,7 @@ describe('Form Cloud service', () => {
|
||||
expect(requestSpy.calls.all().some((call) => call.args[0].includes('/rb/'))).toBe(false);
|
||||
});
|
||||
|
||||
it('should fetch task variables', (done) => {
|
||||
it('should fetch task variables', async () => {
|
||||
requestSpy.and.returnValue(
|
||||
Promise.resolve({
|
||||
list: {
|
||||
@@ -172,18 +170,16 @@ describe('Form Cloud service', () => {
|
||||
})
|
||||
);
|
||||
|
||||
service.getTaskVariables(appName, taskId).subscribe((result) => {
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].name).toBe('fakeProperty');
|
||||
expect(result[0].value).toBe('fakeValue');
|
||||
expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/query/v1/tasks/${taskId}/variables`);
|
||||
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('GET');
|
||||
done();
|
||||
});
|
||||
const result = await lastValueFrom(service.getTaskVariables(appName, taskId), { defaultValue: [] });
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].name).toBe('fakeProperty');
|
||||
expect(result[0].value).toBe('fakeValue');
|
||||
expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/query/v1/tasks/${taskId}/variables`);
|
||||
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('GET');
|
||||
});
|
||||
|
||||
it('should fetch result if the variable value is 0', (done) => {
|
||||
it('should fetch result if the variable value is 0', async () => {
|
||||
requestSpy.and.returnValue(
|
||||
Promise.resolve({
|
||||
list: {
|
||||
@@ -221,16 +217,14 @@ describe('Form Cloud service', () => {
|
||||
})
|
||||
);
|
||||
|
||||
service.getTaskVariables(appName, taskId).subscribe((result) => {
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].name).toBe('fakeProperty');
|
||||
expect(result[0].value).toBe(0);
|
||||
done();
|
||||
});
|
||||
const result = await lastValueFrom(service.getTaskVariables(appName, taskId));
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].name).toBe('fakeProperty');
|
||||
expect(result[0].value).toBe(0);
|
||||
});
|
||||
|
||||
it('should fetch task form flattened', (done) => {
|
||||
it('should fetch task form flattened', async () => {
|
||||
spyOn(service, 'getTask').and.returnValue(of(mockTaskResponseBody.entry));
|
||||
spyOn(service, 'getForm').and.returnValue(
|
||||
of({
|
||||
@@ -241,41 +235,35 @@ describe('Form Cloud service', () => {
|
||||
} as any)
|
||||
);
|
||||
|
||||
service.getTaskForm(appName, taskId).subscribe((result) => {
|
||||
expect(result).toBeDefined();
|
||||
expect(result.name).toBe('task-form');
|
||||
expect(result.taskId).toBe('id');
|
||||
expect(result.taskName).toBe('name');
|
||||
done();
|
||||
});
|
||||
const result = await lastValueFrom(service.getTaskForm(appName, taskId));
|
||||
expect(result).toBeDefined();
|
||||
expect(result.name).toBe('task-form');
|
||||
expect(result.taskId).toBe('id');
|
||||
expect(result.taskName).toBe('name');
|
||||
});
|
||||
|
||||
it('should save task form', (done) => {
|
||||
it('should save task form', async () => {
|
||||
requestSpy.and.returnValue(Promise.resolve(mockTaskResponseBody));
|
||||
const formId = 'form-id';
|
||||
|
||||
service.saveTaskForm(appName, taskId, processInstanceId, formId, {}).subscribe((result: any) => {
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBe('id');
|
||||
expect(result.name).toBe('name');
|
||||
expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/form/v1/forms/${formId}/save`);
|
||||
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('POST');
|
||||
done();
|
||||
});
|
||||
const result = await lastValueFrom(service.saveTaskForm(appName, taskId, processInstanceId, formId, {}));
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBe('id');
|
||||
expect(result.name).toBe('name');
|
||||
expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/form/v1/forms/${formId}/save`);
|
||||
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('POST');
|
||||
});
|
||||
|
||||
it('should complete task form', (done) => {
|
||||
it('should complete task form', async () => {
|
||||
requestSpy.and.returnValue(Promise.resolve(mockTaskResponseBody));
|
||||
const formId = 'form-id';
|
||||
|
||||
service.completeTaskForm(appName, taskId, processInstanceId, formId, {}, '', 1).subscribe((result: any) => {
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBe('id');
|
||||
expect(result.name).toBe('name');
|
||||
expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/form/v1/forms/${formId}/submit/versions/1`);
|
||||
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('POST');
|
||||
done();
|
||||
});
|
||||
const result = await lastValueFrom(service.completeTaskForm(appName, taskId, processInstanceId, formId, {}, '', 1));
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBe('id');
|
||||
expect(result.name).toBe('name');
|
||||
expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/form/v1/forms/${formId}/submit/versions/1`);
|
||||
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('POST');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,29 +56,29 @@
|
||||
<mat-progress-bar *ngIf="validationLoading" mode="indeterminate" />
|
||||
|
||||
<div class="adf-error-container adf-error-messages-container">
|
||||
<mat-error *ngIf="hasPreselectError() && !isValidationLoading()" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-error *ngIf="hasPreselectError() && !isValidationLoading()" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_GROUPS.ERROR.NOT_FOUND' | translate }}</div>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="searchGroupsControl.hasError('pattern')" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-error *ngIf="searchGroupsControl.hasError('pattern')" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_PEOPLE_GROUPS.ERROR.INVALID_PATTERN' | translate: { pattern: getValidationPattern() } }}</div>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="searchGroupsControl.hasError('maxlength')" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-error *ngIf="searchGroupsControl.hasError('maxlength')" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_PEOPLE_GROUPS.ERROR.INVALID_MAX_LENGTH' | translate: { requiredLength: getValidationMaxLength() } }}</div>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="searchGroupsControl.hasError('minlength')" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-error *ngIf="searchGroupsControl.hasError('minlength')" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_PEOPLE_GROUPS.ERROR.INVALID_MIN_LENGTH' | translate: { requiredLength: getValidationMinLength() } }}</div>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="(searchGroupsControl.hasError('required') || groupChipsCtrl.hasError('required')) && isDirty()"
|
||||
[@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_PEOPLE_GROUPS.ERROR.REQUIRED' | translate }} </div>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="searchGroupsControl.hasError('searchTypingError') && !this.isFocused"
|
||||
data-automation-id="invalid-groups-typing-error" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
data-automation-id="invalid-groups-typing-error" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_GROUPS.ERROR.NOT_FOUND' | translate }}</div>
|
||||
</mat-error>
|
||||
|
||||
@@ -45,6 +45,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-down-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0%);
|
||||
}
|
||||
}
|
||||
|
||||
.adf-error-messages-container .adf-error-icon {
|
||||
@include mixins.adf-error-icon;
|
||||
}
|
||||
|
||||
.adf-error-messages-container .adf-error {
|
||||
animation: slide-down-fade-in 300ms cubic-bezier(0.55, 0, 0.55, 0.2);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged, filter, mergeMap, switchMap, tap } from 'rxjs/operators';
|
||||
import { ComponentSelectionMode } from '../../types';
|
||||
@@ -65,12 +64,6 @@ import { IconModule } from '@alfresco/adf-core';
|
||||
],
|
||||
templateUrl: './group-cloud.component.html',
|
||||
styleUrls: ['./group-cloud.component.scss'],
|
||||
animations: [
|
||||
trigger('transitionMessages', [
|
||||
state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
|
||||
transition('void => enter', [style({ opacity: 0, transform: 'translateY(-100%)' }), animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)')])
|
||||
])
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
@@ -153,7 +146,6 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
||||
invalidGroups: IdentityGroupModel[] = [];
|
||||
|
||||
searchGroups$ = new BehaviorSubject<IdentityGroupModel[]>(this.searchGroups);
|
||||
subscriptAnimationState: string = 'enter';
|
||||
isFocused: boolean;
|
||||
touched: boolean = false;
|
||||
|
||||
|
||||
@@ -68,21 +68,21 @@
|
||||
<mat-progress-bar *ngIf="validationLoading" mode="indeterminate" />
|
||||
|
||||
<div class="adf-error-container adf-error-messages-container" *ngIf="showErrors">
|
||||
<mat-error *ngIf="hasPreselectError() && !isValidationLoading()" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-error *ngIf="hasPreselectError() && !isValidationLoading()" class="adf-error adf-error-animate">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_USERS.ERROR.NOT_FOUND' | translate : { userName: validateUsersMessage } }}</div>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="searchUserCtrl.hasError('pattern')" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-error *ngIf="searchUserCtrl.hasError('pattern')" class="adf-error adf-error-animate">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_PEOPLE_GROUPS.ERROR.INVALID_PATTERN' | translate : { pattern: getValidationPattern() } }}</div>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="searchUserCtrl.hasError('maxlength')" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-error *ngIf="searchUserCtrl.hasError('maxlength')" class="adf-error adf-error-animate">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">
|
||||
{{ 'ADF_CLOUD_PEOPLE_GROUPS.ERROR.INVALID_MAX_LENGTH' | translate : { requiredLength: getValidationMaxLength() } }}
|
||||
</div>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="searchUserCtrl.hasError('minlength')" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-error *ngIf="searchUserCtrl.hasError('minlength')" class="adf-error adf-error-animate">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">
|
||||
{{ 'ADF_CLOUD_PEOPLE_GROUPS.ERROR.INVALID_MIN_LENGTH' | translate : { requiredLength: getValidationMinLength() } }}
|
||||
@@ -90,17 +90,15 @@
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="(searchUserCtrl.hasError('required') || userChipsCtrl.hasError('required')) && isDirty()"
|
||||
[@transitionMessages]="subscriptAnimationState"
|
||||
class="adf-error"
|
||||
class="adf-error adf-error-animate"
|
||||
>
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_PEOPLE_GROUPS.ERROR.REQUIRED' | translate }}</div>
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="searchUserCtrl.hasError('searchTypingError') && !this.isFocused"
|
||||
[@transitionMessages]="subscriptAnimationState"
|
||||
data-automation-id="invalid-users-typing-error"
|
||||
class="adf-error"
|
||||
class="adf-error adf-error-animate"
|
||||
>
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ 'ADF_CLOUD_USERS.ERROR.NOT_FOUND' | translate : { userName: searchedValue } }}</div>
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
@use '../../mixins' as mixins;
|
||||
|
||||
@keyframes adf-people-cloud-slide-in-down {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.adf {
|
||||
&-people-cloud {
|
||||
width: 100%;
|
||||
@@ -49,6 +61,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.adf-error-messages-container .adf-error-icon {
|
||||
@include mixins.adf-error-icon;
|
||||
.adf-error-messages-container {
|
||||
.adf-error-icon {
|
||||
@include mixins.adf-error-icon;
|
||||
}
|
||||
|
||||
.adf-error-animate {
|
||||
animation: adf-people-cloud-slide-in-down 300ms cubic-bezier(0.55, 0, 0.55, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import {
|
||||
import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged, filter, mergeMap, switchMap, tap } from 'rxjs/operators';
|
||||
import { FullNamePipe, IconModule, InitialUsernamePipe } from '@alfresco/adf-core';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { ComponentSelectionMode } from '../../types';
|
||||
import { IdentityUserModel } from '../models/identity-user.model';
|
||||
import { MatFormFieldAppearance, MatFormFieldModule, SubscriptSizing } from '@angular/material/form-field';
|
||||
@@ -69,12 +68,6 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
providers: [FullNamePipe],
|
||||
templateUrl: './people-cloud.component.html',
|
||||
styleUrls: ['./people-cloud.component.scss'],
|
||||
animations: [
|
||||
trigger('transitionMessages', [
|
||||
state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
|
||||
transition('void => enter', [style({ opacity: 0, transform: 'translateY(-100%)' }), animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)')])
|
||||
])
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
|
||||
@@ -215,7 +208,6 @@ export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
|
||||
invalidUsers: IdentityUserModel[] = [];
|
||||
|
||||
searchUsers$ = new BehaviorSubject<IdentityUserModel[]>(this.searchUsers);
|
||||
subscriptAnimationState: string = 'enter';
|
||||
isFocused: boolean;
|
||||
touched: boolean = false;
|
||||
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
|
||||
import { BrowserTestingModule } from '@angular/platform-browser/testing';
|
||||
import { NoopTranslateModule } from '@alfresco/adf-core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { provideNoopAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
@NgModule({
|
||||
imports: [BrowserDynamicTestingModule, NoopTranslateModule, NoopAnimationsModule]
|
||||
imports: [BrowserTestingModule, NoopTranslateModule],
|
||||
providers: [provideNoopAnimations()]
|
||||
})
|
||||
export class GlobalTestingModule {}
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
import 'zone.js';
|
||||
import 'zone.js/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
|
||||
import { platformBrowserTesting } from '@angular/platform-browser/testing';
|
||||
import { GlobalTestingModule } from './lib/testing/global-testing.module';
|
||||
|
||||
TestBed.initTestEnvironment(GlobalTestingModule, platformBrowserDynamicTesting(), {
|
||||
TestBed.initTestEnvironment(GlobalTestingModule, platformBrowserTesting(), {
|
||||
teardown: { destroyAfterEach: true }
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user