mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
AAE-21566 Handling new form event - show spinner (#9656)
* [AAE-21566] Add spinner event in process form * CR * CR * added test for spinner service * fix unit test * fix lint
This commit is contained in:
parent
5802ac56af
commit
d59fbdd825
@ -17,10 +17,7 @@
|
|||||||
|
|
||||||
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, CanActivateChild, UrlTree } from '@angular/router';
|
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, CanActivateChild, UrlTree } from '@angular/router';
|
||||||
import { AuthenticationService } from '../services/authentication.service';
|
import { AuthenticationService } from '../services/authentication.service';
|
||||||
import {
|
import { AppConfigService, AppConfigValues } from '../../app-config/app-config.service';
|
||||||
AppConfigService,
|
|
||||||
AppConfigValues
|
|
||||||
} from '../../app-config/app-config.service';
|
|
||||||
import { OauthConfigModel } from '../models/oauth-config.model';
|
import { OauthConfigModel } from '../models/oauth-config.model';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { StorageService } from '../../common/services/storage.service';
|
import { StorageService } from '../../common/services/storage.service';
|
||||||
@ -28,9 +25,7 @@ import { Observable } from 'rxjs';
|
|||||||
import { BasicAlfrescoAuthService } from '../basic-auth/basic-alfresco-auth.service';
|
import { BasicAlfrescoAuthService } from '../basic-auth/basic-alfresco-auth.service';
|
||||||
import { OidcAuthenticationService } from '../services/oidc-authentication.service';
|
import { OidcAuthenticationService } from '../services/oidc-authentication.service';
|
||||||
|
|
||||||
|
|
||||||
export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
||||||
|
|
||||||
protected get withCredentials(): boolean {
|
protected get withCredentials(): boolean {
|
||||||
return this.appConfigService.get<boolean>('auth.withCredentials', false);
|
return this.appConfigService.get<boolean>('auth.withCredentials', false);
|
||||||
}
|
}
|
||||||
@ -43,8 +38,7 @@ export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
|||||||
protected appConfigService: AppConfigService,
|
protected appConfigService: AppConfigService,
|
||||||
protected dialog: MatDialog,
|
protected dialog: MatDialog,
|
||||||
private storageService: StorageService
|
private storageService: StorageService
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
abstract checkLogin(
|
abstract checkLogin(
|
||||||
activeRoute: ActivatedRouteSnapshot,
|
activeRoute: ActivatedRouteSnapshot,
|
||||||
@ -96,7 +90,7 @@ export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
|||||||
|
|
||||||
urlToRedirect = `${urlToRedirect}?redirectUrl=${url}`;
|
urlToRedirect = `${urlToRedirect}?redirectUrl=${url}`;
|
||||||
return this.navigate(urlToRedirect);
|
return this.navigate(urlToRedirect);
|
||||||
} else if (this.getOauthConfig().silentLogin && !this.oidcAuthenticationService.isPublicUrl()) {
|
} else if (this.getOauthConfig().silentLogin && !this.oidcAuthenticationService.isPublicUrl()) {
|
||||||
if (!this.oidcAuthenticationService.hasValidIdToken() || !this.oidcAuthenticationService.hasValidAccessToken()) {
|
if (!this.oidcAuthenticationService.hasValidIdToken() || !this.oidcAuthenticationService.hasValidAccessToken()) {
|
||||||
this.oidcAuthenticationService.ssoLogin(url);
|
this.oidcAuthenticationService.ssoLogin(url);
|
||||||
}
|
}
|
||||||
@ -114,13 +108,7 @@ export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getOauthConfig(): OauthConfigModel {
|
protected getOauthConfig(): OauthConfigModel {
|
||||||
return (
|
return this.appConfigService && this.appConfigService.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null);
|
||||||
this.appConfigService &&
|
|
||||||
this.appConfigService.get<OauthConfigModel>(
|
|
||||||
AppConfigValues.OAUTHCONFIG,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getLoginRoute(): string {
|
protected getLoginRoute(): string {
|
||||||
@ -132,20 +120,12 @@ export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected isOAuthWithoutSilentLogin(): boolean {
|
protected isOAuthWithoutSilentLogin(): boolean {
|
||||||
const oauth = this.appConfigService.get<OauthConfigModel>(
|
const oauth = this.appConfigService.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null);
|
||||||
AppConfigValues.OAUTHCONFIG,
|
return this.authenticationService.isOauth() && !!oauth && !oauth.silentLogin;
|
||||||
null
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
this.authenticationService.isOauth() && !!oauth && !oauth.silentLogin
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected isSilentLogin(): boolean {
|
protected isSilentLogin(): boolean {
|
||||||
const oauth = this.appConfigService.get<OauthConfigModel>(
|
const oauth = this.appConfigService.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null);
|
||||||
AppConfigValues.OAUTHCONFIG,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
return this.authenticationService.isOauth() && oauth && oauth.silentLogin;
|
return this.authenticationService.isOauth() && oauth && oauth.silentLogin;
|
||||||
}
|
}
|
||||||
|
@ -701,12 +701,12 @@ describe('Form Renderer Component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Form rules', () => {
|
describe('Form rules', () => {
|
||||||
it('should call the Form Rules Manager init on component changes', () => {
|
it('should call the Form Rules Manager init', () => {
|
||||||
spyOn(rulesManager, 'initialize');
|
spyOn(rulesManager, 'initialize');
|
||||||
const formModel = formService.parseForm(customWidgetFormWithVisibility.formRepresentation.formDefinition);
|
const formModel = formService.parseForm(customWidgetFormWithVisibility.formRepresentation.formDefinition);
|
||||||
|
|
||||||
formRendererComponent.formDefinition = formModel;
|
formRendererComponent.formDefinition = formModel;
|
||||||
formRendererComponent.ngOnChanges();
|
formRendererComponent.ngOnInit();
|
||||||
|
|
||||||
expect(rulesManager.initialize).toHaveBeenCalledWith(formModel);
|
expect(rulesManager.initialize).toHaveBeenCalledWith(formModel);
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, Input, OnDestroy, Injector, OnChanges, OnInit, Inject } from '@angular/core';
|
import { Component, ViewEncapsulation, Input, OnDestroy, Injector, OnInit, Inject } from '@angular/core';
|
||||||
import { FormRulesManager, formRulesManagerFactory } from '../models/form-rules.model';
|
import { FormRulesManager, formRulesManagerFactory } from '../models/form-rules.model';
|
||||||
import { FormModel } from './widgets/core/form.model';
|
import { FormModel } from './widgets/core/form.model';
|
||||||
import { ContainerModel, FormFieldModel, TabModel } from './widgets';
|
import { ContainerModel, FormFieldModel, TabModel } from './widgets';
|
||||||
@ -36,7 +36,7 @@ import { FORM_FIELD_MODEL_RENDER_MIDDLEWARE, FormFieldModelRenderMiddleware } fr
|
|||||||
],
|
],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class FormRendererComponent<T> implements OnInit, OnChanges, OnDestroy {
|
export class FormRendererComponent<T> implements OnInit, OnDestroy {
|
||||||
/** Toggle debug options. */
|
/** Toggle debug options. */
|
||||||
@Input()
|
@Input()
|
||||||
showDebugButton: boolean = false;
|
showDebugButton: boolean = false;
|
||||||
@ -57,9 +57,6 @@ export class FormRendererComponent<T> implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.runMiddlewareServices();
|
this.runMiddlewareServices();
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges(): void {
|
|
||||||
this.formRulesManager.initialize(this.formDefinition);
|
this.formRulesManager.initialize(this.formDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
lib/core/src/lib/form/events/form-spinner.event.ts
Normal file
25
lib/core/src/lib/form/events/form-spinner.event.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface FormSpinnerEventPayload {
|
||||||
|
showSpinner: boolean;
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FormSpinnerEvent {
|
||||||
|
constructor(public type: string, public payload: FormSpinnerEventPayload) {}
|
||||||
|
}
|
@ -21,3 +21,4 @@ export * from './form-field.event';
|
|||||||
export * from './validate-form-field.event';
|
export * from './validate-form-field.event';
|
||||||
export * from './validate-form.event';
|
export * from './validate-form.event';
|
||||||
export * from './form-rules.event';
|
export * from './form-rules.event';
|
||||||
|
export * from './form-spinner.event';
|
||||||
|
@ -39,7 +39,7 @@ export function formRulesManagerFactory<T>(injector: Injector): FormRulesManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
export abstract class FormRulesManager<T> {
|
export abstract class FormRulesManager<T> {
|
||||||
constructor(private formService: FormService) {}
|
constructor(protected formService: FormService) {}
|
||||||
|
|
||||||
protected formModel: FormModel;
|
protected formModel: FormModel;
|
||||||
private onDestroy$ = new Subject<boolean>();
|
private onDestroy$ = new Subject<boolean>();
|
||||||
@ -66,7 +66,9 @@ export abstract class FormRulesManager<T> {
|
|||||||
this.handleRuleEvent(event, rules);
|
this.handleRuleEvent(event, rules);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.formService.formRulesEvent.next(new FormRulesEvent('formLoaded', new FormEvent(formModel)));
|
const onFormLoadedEvent = new FormEvent(formModel);
|
||||||
|
const formRules = new FormRulesEvent('formLoaded', onFormLoadedEvent);
|
||||||
|
this.formService.formRulesEvent.next(formRules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,12 +29,12 @@ import { ValidateFormEvent } from '../events/validate-form.event';
|
|||||||
import { ValidateFormFieldEvent } from '../events/validate-form-field.event';
|
import { ValidateFormFieldEvent } from '../events/validate-form-field.event';
|
||||||
import { FormValidationService } from './form-validation-service.interface';
|
import { FormValidationService } from './form-validation-service.interface';
|
||||||
import { FormRulesEvent } from '../events/form-rules.event';
|
import { FormRulesEvent } from '../events/form-rules.event';
|
||||||
|
import { FormSpinnerEvent } from '../events';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class FormService implements FormValidationService {
|
export class FormService implements FormValidationService {
|
||||||
|
|
||||||
formLoaded = new Subject<FormEvent>();
|
formLoaded = new Subject<FormEvent>();
|
||||||
formDataRefreshed = new Subject<FormEvent>();
|
formDataRefreshed = new Subject<FormEvent>();
|
||||||
formFieldValueChanged = new Subject<FormFieldEvent>();
|
formFieldValueChanged = new Subject<FormFieldEvent>();
|
||||||
@ -44,6 +44,7 @@ export class FormService implements FormValidationService {
|
|||||||
taskSaved = new Subject<FormEvent>();
|
taskSaved = new Subject<FormEvent>();
|
||||||
taskSavedError = new Subject<FormErrorEvent>();
|
taskSavedError = new Subject<FormErrorEvent>();
|
||||||
formContentClicked = new Subject<ContentLinkModel>();
|
formContentClicked = new Subject<ContentLinkModel>();
|
||||||
|
toggleFormSpinner = new Subject<FormSpinnerEvent>();
|
||||||
|
|
||||||
validateForm = new Subject<ValidateFormEvent>();
|
validateForm = new Subject<ValidateFormEvent>();
|
||||||
validateFormField = new Subject<ValidateFormFieldEvent>();
|
validateFormField = new Subject<ValidateFormFieldEvent>();
|
||||||
@ -55,8 +56,7 @@ export class FormService implements FormValidationService {
|
|||||||
|
|
||||||
formRulesEvent = new Subject<FormRulesEvent>();
|
formRulesEvent = new Subject<FormRulesEvent>();
|
||||||
|
|
||||||
constructor() {
|
constructor() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses JSON data to create a corresponding Form model.
|
* Parses JSON data to create a corresponding Form model.
|
||||||
|
@ -38,8 +38,10 @@ export class TimeAgoPipe implements PipeTransform, OnDestroy {
|
|||||||
|
|
||||||
private onDestroy$ = new Subject<boolean>();
|
private onDestroy$ = new Subject<boolean>();
|
||||||
|
|
||||||
constructor(public userPreferenceService: UserPreferencesService,
|
constructor(
|
||||||
public appConfig: AppConfigService) {
|
public userPreferenceService: UserPreferencesService,
|
||||||
|
public appConfig: AppConfigService
|
||||||
|
) {
|
||||||
this.userPreferenceService
|
this.userPreferenceService
|
||||||
.select(UserPreferenceValues.Locale)
|
.select(UserPreferenceValues.Locale)
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
@ -41,6 +41,7 @@ import { ConfirmDialogComponent } from '@alfresco/adf-content-services';
|
|||||||
import { v4 as uuidGeneration } from 'uuid';
|
import { v4 as uuidGeneration } from 'uuid';
|
||||||
import { FormCloudDisplayMode, FormCloudDisplayModeConfiguration } from '../../services/form-fields.interfaces';
|
import { FormCloudDisplayMode, FormCloudDisplayModeConfiguration } from '../../services/form-fields.interfaces';
|
||||||
import { DisplayModeService } from '../public-api';
|
import { DisplayModeService } from '../public-api';
|
||||||
|
import { FormCloudSpinnerService } from '../services/spinner/form-cloud-spinner.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-cloud-form',
|
selector: 'adf-cloud-form',
|
||||||
@ -128,9 +129,13 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
protected formService: FormService,
|
protected formService: FormService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
protected visibilityService: WidgetVisibilityService,
|
protected visibilityService: WidgetVisibilityService,
|
||||||
private readonly displayModeService: DisplayModeService
|
private readonly displayModeService: DisplayModeService,
|
||||||
|
private spinnerService: FormCloudSpinnerService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.spinnerService.initSpinnerHandling(this.onDestroy$);
|
||||||
|
|
||||||
this.id = uuidGeneration();
|
this.id = uuidGeneration();
|
||||||
|
|
||||||
this.formService.formContentClicked.pipe(takeUntil(this.onDestroy$)).subscribe((content) => {
|
this.formService.formContentClicked.pipe(takeUntil(this.onDestroy$)).subscribe((content) => {
|
||||||
@ -375,6 +380,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
}
|
}
|
||||||
return form;
|
return form;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,8 +402,10 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
|
|
||||||
private refreshFormData() {
|
private refreshFormData() {
|
||||||
this.form = this.parseForm(this.formCloudRepresentationJSON);
|
this.form = this.parseForm(this.formCloudRepresentationJSON);
|
||||||
this.onFormLoaded(this.form);
|
if (this.form) {
|
||||||
this.onFormDataRefreshed(this.form);
|
this.onFormLoaded(this.form);
|
||||||
|
this.onFormDataRefreshed(this.form);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onFormLoaded(form: FormModel) {
|
protected onFormLoaded(form: FormModel) {
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
<div class="adf-cloud-form-spinner">
|
||||||
|
<div class="adf-cloud-form-spinner-content">
|
||||||
|
<mat-progress-spinner
|
||||||
|
color="primary"
|
||||||
|
mode="indeterminate"
|
||||||
|
></mat-progress-spinner>
|
||||||
|
<span class="adf-cloud-form-spinner-content-message">
|
||||||
|
{{message | translate}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,20 @@
|
|||||||
|
.adf-cloud-form {
|
||||||
|
&-spinner {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
place-content: center center;
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column wrap;
|
||||||
|
place-content: center center;
|
||||||
|
row-gap: 25px;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&-message {
|
||||||
|
font-size: var(--theme-body-4-font-size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: './form-spinner.component.html',
|
||||||
|
styleUrls: ['./form-spinner.component.scss']
|
||||||
|
})
|
||||||
|
export class FormSpinnerComponent {
|
||||||
|
@Input() message = '';
|
||||||
|
}
|
@ -42,10 +42,14 @@ import { FileViewerWidgetComponent } from './components/widgets/file-viewer/file
|
|||||||
import { DisplayRichTextWidgetComponent } from './components/widgets/display-rich-text/display-rich-text.widget';
|
import { DisplayRichTextWidgetComponent } from './components/widgets/display-rich-text/display-rich-text.widget';
|
||||||
import { RichTextEditorModule } from '../rich-text-editor';
|
import { RichTextEditorModule } from '../rich-text-editor';
|
||||||
import { A11yModule } from '@angular/cdk/a11y';
|
import { A11yModule } from '@angular/cdk/a11y';
|
||||||
|
import { OverlayModule } from '@angular/cdk/overlay';
|
||||||
|
import { FormSpinnerComponent } from './components/spinner/form-spinner.component';
|
||||||
|
import { FormCloudSpinnerService } from './services/spinner/form-cloud-spinner.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
OverlayModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
@ -76,7 +80,8 @@ import { A11yModule } from '@angular/cdk/a11y';
|
|||||||
PropertiesViewerWidgetComponent,
|
PropertiesViewerWidgetComponent,
|
||||||
FilePropertiesTableCloudComponent,
|
FilePropertiesTableCloudComponent,
|
||||||
FileViewerWidgetComponent,
|
FileViewerWidgetComponent,
|
||||||
DisplayRichTextWidgetComponent
|
DisplayRichTextWidgetComponent,
|
||||||
|
FormSpinnerComponent
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
FormCloudComponent,
|
FormCloudComponent,
|
||||||
@ -92,6 +97,7 @@ import { A11yModule } from '@angular/cdk/a11y';
|
|||||||
PropertiesViewerWidgetComponent,
|
PropertiesViewerWidgetComponent,
|
||||||
FileViewerWidgetComponent,
|
FileViewerWidgetComponent,
|
||||||
DisplayRichTextWidgetComponent
|
DisplayRichTextWidgetComponent
|
||||||
]
|
],
|
||||||
|
providers: [FormCloudSpinnerService]
|
||||||
})
|
})
|
||||||
export class FormCloudModule {}
|
export class FormCloudModule {}
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { FormCloudSpinnerService } from './form-cloud-spinner.service';
|
||||||
|
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 { FormSpinnerComponent } from '../../components/spinner/form-spinner.component';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
|
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
||||||
|
import { PortalModule } from '@angular/cdk/portal';
|
||||||
|
import { HarnessLoader } from '@angular/cdk/testing';
|
||||||
|
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-overlay-test',
|
||||||
|
template: `<div>adf-cloud-overlay-test</div>`
|
||||||
|
})
|
||||||
|
class SpinnerTestComponent {}
|
||||||
|
|
||||||
|
describe('FormCloudSpinnerService', () => {
|
||||||
|
let fixture: ComponentFixture<SpinnerTestComponent>;
|
||||||
|
let rootLoader: HarnessLoader;
|
||||||
|
let spinnerService: FormCloudSpinnerService;
|
||||||
|
let formService: FormService;
|
||||||
|
|
||||||
|
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({
|
||||||
|
declarations: [FormSpinnerComponent, SpinnerTestComponent],
|
||||||
|
providers: [
|
||||||
|
FormCloudSpinnerService,
|
||||||
|
{
|
||||||
|
provide: FormService,
|
||||||
|
useValue: {
|
||||||
|
toggleFormSpinner: new Subject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
imports: [OverlayModule, PortalModule, MatProgressSpinnerModule, TranslateModule.forRoot()]
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(SpinnerTestComponent);
|
||||||
|
rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);
|
||||||
|
spinnerService = TestBed.inject(FormCloudSpinnerService);
|
||||||
|
formService = TestBed.inject(FormService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should toggle spinner', async () => {
|
||||||
|
spinnerService.initSpinnerHandling(onDestroy$);
|
||||||
|
formService.toggleFormSpinner.next(showSpinnerEvent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
let hasSpinner = await rootLoader.hasHarness(MatProgressSpinnerHarness);
|
||||||
|
expect(hasSpinner).toBeTrue();
|
||||||
|
|
||||||
|
formService.toggleFormSpinner.next(hideSpinnerEvent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
hasSpinner = await rootLoader.hasHarness(MatProgressSpinnerHarness);
|
||||||
|
expect(hasSpinner).toBeFalse();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,48 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable, inject } 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';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FormCloudSpinnerService {
|
||||||
|
private formService = inject(FormService);
|
||||||
|
private overlay = inject(Overlay);
|
||||||
|
|
||||||
|
private overlayRef?: OverlayRef;
|
||||||
|
|
||||||
|
initSpinnerHandling(onDestroy$: Observable<boolean>): void {
|
||||||
|
this.formService.toggleFormSpinner.pipe(takeUntil(onDestroy$)).subscribe((event: FormSpinnerEvent) => {
|
||||||
|
if (event?.payload.showSpinner) {
|
||||||
|
this.overlayRef = this.overlay.create({
|
||||||
|
hasBackdrop: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const userProfilePortal = new ComponentPortal(FormSpinnerComponent);
|
||||||
|
const componentRef = this.overlayRef.attach(userProfilePortal);
|
||||||
|
componentRef.instance.message = event.payload.message;
|
||||||
|
} else if (event?.payload.showSpinner === false) {
|
||||||
|
this.overlayRef?.detach();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
<mat-card class="adf-start-process" *ngIf="(loading$ | async) === false; else spinner">
|
<mat-card
|
||||||
|
*ngIf="(loading$ | async) === false; else spinner"
|
||||||
|
class="adf-start-process"
|
||||||
|
>
|
||||||
|
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
|
|
||||||
@ -100,10 +103,12 @@
|
|||||||
<ng-template #taskFormCloudButtons>
|
<ng-template #taskFormCloudButtons>
|
||||||
<div class="adf-start-process-cloud-actions">
|
<div class="adf-start-process-cloud-actions">
|
||||||
<button
|
<button
|
||||||
|
*ngIf="showCancelButton"
|
||||||
mat-button
|
mat-button
|
||||||
(click)="cancelStartProcess()"
|
(click)="cancelStartProcess()"
|
||||||
id="cancel_process">
|
id="cancel_process"
|
||||||
{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.CANCEL' | translate | uppercase}}
|
>
|
||||||
|
{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.CANCEL' | translate | uppercase}}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
color="primary"
|
color="primary"
|
||||||
@ -112,7 +117,8 @@
|
|||||||
(click)="startProcess()"
|
(click)="startProcess()"
|
||||||
data-automation-id="btn-start"
|
data-automation-id="btn-start"
|
||||||
id="button-start"
|
id="button-start"
|
||||||
class="adf-btn-start">
|
class="adf-btn-start"
|
||||||
|
>
|
||||||
{{'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.START' | translate | uppercase}}
|
{{'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.START' | translate | uppercase}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -86,6 +86,10 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy
|
|||||||
@Input()
|
@Input()
|
||||||
showTitle: boolean = true;
|
showTitle: boolean = true;
|
||||||
|
|
||||||
|
/** Show/hide cancel button. */
|
||||||
|
@Input()
|
||||||
|
showCancelButton: boolean = true;
|
||||||
|
|
||||||
/** Emitted when the process is successfully started. */
|
/** Emitted when the process is successfully started. */
|
||||||
@Output()
|
@Output()
|
||||||
success = new EventEmitter<ProcessInstanceCloud>();
|
success = new EventEmitter<ProcessInstanceCloud>();
|
||||||
@ -187,20 +191,24 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy
|
|||||||
}
|
}
|
||||||
|
|
||||||
setProcessDefinitionOnForm(selectedProcessDefinitionName: string) {
|
setProcessDefinitionOnForm(selectedProcessDefinitionName: string) {
|
||||||
this.processDefinitionCurrent = this.filteredProcesses.find(
|
const processDefinitionCurrent = this.filteredProcesses.find(
|
||||||
(process: ProcessDefinitionCloud) => process.name === selectedProcessDefinitionName || process.key === selectedProcessDefinitionName
|
(process: ProcessDefinitionCloud) => process.name === selectedProcessDefinitionName || process.key === selectedProcessDefinitionName
|
||||||
);
|
);
|
||||||
|
|
||||||
this.startProcessCloudService.getStartEventFormStaticValuesMapping(this.appName, this.processDefinitionCurrent.id).subscribe(
|
this.startProcessCloudService.getStartEventFormStaticValuesMapping(this.appName, processDefinitionCurrent.id).subscribe(
|
||||||
(staticMappings) => {
|
(staticMappings) => {
|
||||||
this.staticMappings = staticMappings;
|
this.staticMappings = staticMappings;
|
||||||
this.resolvedValues = this.staticMappings.concat(this.values || []);
|
this.resolvedValues = this.staticMappings.concat(this.values || []);
|
||||||
|
this.processDefinitionCurrent = processDefinitionCurrent;
|
||||||
},
|
},
|
||||||
() => (this.resolvedValues = this.values)
|
() => {
|
||||||
|
this.resolvedValues = this.values;
|
||||||
|
this.processDefinitionCurrent = processDefinitionCurrent;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.isFormCloudLoaded = false;
|
this.isFormCloudLoaded = false;
|
||||||
this.processPayloadCloud.processDefinitionKey = this.processDefinitionCurrent.key;
|
this.processPayloadCloud.processDefinitionKey = processDefinitionCurrent.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getProcessDefinitionListByNameOrKey(processDefinitionName: string): ProcessDefinitionCloud[] {
|
private getProcessDefinitionListByNameOrKey(processDefinitionName: string): ProcessDefinitionCloud[] {
|
||||||
|
@ -32,11 +32,7 @@ import { AdfHttpClient } from '@alfresco/adf-core/api';
|
|||||||
export class NotificationCloudService extends BaseCloudService {
|
export class NotificationCloudService extends BaseCloudService {
|
||||||
appsListening = [];
|
appsListening = [];
|
||||||
|
|
||||||
constructor(
|
constructor(public apollo: Apollo, private http: HttpLink, private authService: AuthenticationService, protected adfHttpClient: AdfHttpClient) {
|
||||||
public apollo: Apollo,
|
|
||||||
private http: HttpLink,
|
|
||||||
private authService: AuthenticationService,
|
|
||||||
protected adfHttpClient: AdfHttpClient) {
|
|
||||||
super(adfHttpClient);
|
super(adfHttpClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user