Compare commits

...
Author SHA1 Message Date
Denys Vuika 0b6a73bb5d fix after rebase [ci:force] 2024-10-02 09:57:27 -04:00
Denys Vuika 244a1dff2e fix after rebase [ci:force] 2024-10-02 09:57:27 -04:00
Denys Vuika cc74849f78 migrate cloud components [ci:force] 2024-10-02 09:57:27 -04:00
Denys Vuika 96e14c88da migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 0012b5fb5a migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 95593e488b migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 9d4d3c556d migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 44b5ec00cb migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 91accbf0a4 migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika e0c354e10a migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika bbebaccef4 migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika e2e6417139 migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika ace50ca8cd migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 9843a2415f migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 7fa18879f5 migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 5a503603e7 migrate cloud components 2024-10-02 09:57:27 -04:00
Denys Vuika 3a6754c0f0 migrate cloud components 2024-10-02 09:57:26 -04:00
Denys Vuika 2c1dc48b50 migrate cloud components 2024-10-02 09:57:26 -04:00
Denys Vuika a7c74d34b3 migrate cloud components 2024-10-02 09:57:26 -04:00
Denys Vuika 97b5ec833a migrate cloud components 2024-10-02 09:57:26 -04:00
Denys Vuika 9d10f702b8 migrate cloud components 2024-10-02 09:57:26 -04:00
Denys Vuika 7e72569d48 migrate cloud components 2024-10-02 09:57:26 -04:00
Denys Vuika f8c1b0f6cc migrate cloud components 2024-10-02 09:57:26 -04:00
Denys Vuika 2eec264bff migrate attach cloud widget 2024-10-02 09:57:26 -04:00
Denys Vuika feca05e835 fixes and conversion 2024-10-02 09:57:26 -04:00
Denys Vuika 6d9838eaf4 pipe fixes and conversion 2024-10-02 09:57:26 -04:00
Denys Vuika 7b88c10137 process common module 2024-10-02 09:57:26 -04:00
Denys Vuika b57f953dd0 process common module, date range filter is not a service 2024-10-02 09:57:26 -04:00
Denys Vuika c0d60495d0 process common module, date range filter is not a service 2024-10-02 09:57:26 -04:00
Denys Vuika fa61d28dc9 app list component stories 2024-10-02 09:57:26 -04:00
Denys Vuika fbdac3fff6 app list component 2024-10-02 09:57:26 -04:00
130 changed files with 1368 additions and 1344 deletions
@@ -16,7 +16,17 @@
*/
import { Inject, Injectable, inject } from '@angular/core';
import { AuthConfig, AUTH_CONFIG, OAuthErrorEvent, OAuthEvent, OAuthService, OAuthStorage, TokenResponse, LoginOptions, OAuthSuccessEvent } from 'angular-oauth2-oidc';
import {
AuthConfig,
AUTH_CONFIG,
OAuthErrorEvent,
OAuthEvent,
OAuthService,
OAuthStorage,
TokenResponse,
LoginOptions,
OAuthSuccessEvent
} from 'angular-oauth2-oidc';
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
import { from, Observable } from 'rxjs';
import { distinctUntilChanged, filter, map, shareReplay, take } from 'rxjs/operators';
@@ -25,229 +35,230 @@ import { AUTH_MODULE_CONFIG, AuthModuleConfig } from './auth-config';
const isPromise = <T>(value: T | Promise<T>): value is Promise<T> => value && typeof (value as Promise<T>).then === 'function';
@Injectable()
@Injectable({ providedIn: 'root' })
export class RedirectAuthService extends AuthService {
readonly authModuleConfig: AuthModuleConfig = inject(AUTH_MODULE_CONFIG);
readonly authModuleConfig: AuthModuleConfig = inject(AUTH_MODULE_CONFIG);
onLogin: Observable<any>;
onLogin: Observable<any>;
onTokenReceived: Observable<any>;
onTokenReceived: Observable<any>;
private _loadDiscoveryDocumentPromise = Promise.resolve(false);
private _loadDiscoveryDocumentPromise = Promise.resolve(false);
/** Subscribe to whether the user has valid Id/Access tokens. */
authenticated$!: Observable<boolean>;
/** Subscribe to whether the user has valid Id/Access tokens. */
authenticated$!: Observable<boolean>;
/** Subscribe to errors reaching the IdP. */
idpUnreachable$!: Observable<Error>;
/** Subscribe to errors reaching the IdP. */
idpUnreachable$!: Observable<Error>;
/**
* Get whether the user has valid Id/Access tokens.
*
* @returns `true` if the user is authenticated, otherwise `false`
*/
get authenticated(): boolean {
return this.oauthService.hasValidIdToken() && this.oauthService.hasValidAccessToken();
}
/**
* Get whether the user has valid Id/Access tokens.
*
* @returns `true` if the user is authenticated, otherwise `false`
*/
get authenticated(): boolean {
return this.oauthService.hasValidIdToken() && this.oauthService.hasValidAccessToken();
}
private authConfig!: AuthConfig | Promise<AuthConfig>;
private authConfig!: AuthConfig | Promise<AuthConfig>;
private readonly AUTH_STORAGE_ITEMS: string[] = [
'access_token',
'access_token_stored_at',
'expires_at',
'granted_scopes',
'id_token',
'id_token_claims_obj',
'id_token_expires_at',
'id_token_stored_at',
'nonce',
'PKCE_verifier',
'refresh_token',
'session_state'
];
private readonly AUTH_STORAGE_ITEMS: string[] = [
'access_token',
'access_token_stored_at',
'expires_at',
'granted_scopes',
'id_token',
'id_token_claims_obj',
'id_token_expires_at',
'id_token_stored_at',
'nonce',
'PKCE_verifier',
'refresh_token',
'session_state'
];
constructor(private oauthService: OAuthService, private _oauthStorage: OAuthStorage, @Inject(AUTH_CONFIG) authConfig: AuthConfig) {
super();
this.authConfig = authConfig;
constructor(
private oauthService: OAuthService,
private _oauthStorage: OAuthStorage,
@Inject(AUTH_CONFIG) authConfig: AuthConfig
) {
super();
this.authConfig = authConfig;
this.oauthService.clearHashAfterLogin = true;
this.oauthService.clearHashAfterLogin = true;
this.authenticated$ = this.oauthService.events.pipe(
map(() => this.authenticated),
distinctUntilChanged(),
shareReplay(1)
);
this.authenticated$ = this.oauthService.events.pipe(
map(() => this.authenticated),
distinctUntilChanged(),
shareReplay(1)
);
this.oauthService.events.pipe(take(1)).subscribe(() => {
if (this.oauthService.getAccessToken() && !this.authenticated) {
this.AUTH_STORAGE_ITEMS.map((item: string) => this._oauthStorage.removeItem(item));
this.reloadPage();
}
});
this.oauthService.events.pipe(take(1)).subscribe(() => {
if(this.oauthService.getAccessToken() && !this.authenticated){
this.AUTH_STORAGE_ITEMS.map((item: string) => this._oauthStorage.removeItem(item));
this.reloadPage();
this.onLogin = this.authenticated$.pipe(
filter((authenticated) => authenticated),
map(() => undefined)
);
this.onTokenReceived = this.oauthService.events.pipe(
filter((event: OAuthEvent) => event.type === 'token_received'),
map(() => undefined)
);
this.idpUnreachable$ = this.oauthService.events.pipe(
filter((event): event is OAuthErrorEvent => event.type === 'discovery_document_load_error'),
map((event) => event.reason as Error)
);
}
init(): Promise<boolean> {
if (isPromise(this.authConfig)) {
return this.authConfig.then((config) => this.configureAuth(config));
}
});
this.onLogin = this.authenticated$.pipe(
filter((authenticated) => authenticated),
map(() => undefined)
);
this.onTokenReceived = this.oauthService.events.pipe(
filter((event: OAuthEvent) => event.type === 'token_received'),
map(() => undefined)
);
this.idpUnreachable$ = this.oauthService.events.pipe(
filter((event): event is OAuthErrorEvent => event.type === 'discovery_document_load_error'),
map((event) => event.reason as Error)
);
}
init(): Promise<boolean> {
if (isPromise(this.authConfig)) {
return this.authConfig.then((config) => this.configureAuth(config));
return this.configureAuth(this.authConfig);
}
return this.configureAuth(this.authConfig);
}
logout() {
this.oauthService.logOut();
}
ensureDiscoveryDocument(): Promise<boolean> {
this._loadDiscoveryDocumentPromise = this._loadDiscoveryDocumentPromise
.catch(() => false)
.then((loaded) => {
if (!loaded) {
return this.oauthService.loadDiscoveryDocument().then(() => true);
}
return true;
});
return this._loadDiscoveryDocumentPromise;
}
login(currentUrl?: string): void {
let stateKey: string | undefined;
if (currentUrl) {
const randomValue = window.crypto.getRandomValues(new Uint32Array(1))[0];
stateKey = `auth_state_${randomValue}${Date.now()}`;
this._oauthStorage.setItem(stateKey, JSON.stringify(currentUrl || {}));
}
// initLoginFlow will initialize the login flow in either code or implicit depending on the configuration
this.ensureDiscoveryDocument().then(() => void this.oauthService.initLoginFlow(stateKey));
}
baseAuthLogin(username: string, password: string): Observable<TokenResponse> {
this.oauthService.useHttpBasicAuth = true;
return from(this.oauthService.fetchTokenUsingPasswordFlow(username, password)).pipe(
map((response) => {
const props = new Map<string, string>();
props.set('id_token', response.id_token);
// for backward compatibility we need to set the response in our storage
this.oauthService['storeAccessTokenResponse'](response.access_token, response.refresh_token, response.expires_in, response.scope, props);
return response;
})
);
}
async loginCallback(loginOptions?: LoginOptions): Promise<string | undefined> {
return this.ensureDiscoveryDocument()
.then(() => this.oauthService.tryLogin({ ...loginOptions, preventClearHashAfterLogin: this.authModuleConfig.preventClearHashAfterLogin }))
.then(() => this._getRedirectUrl());
}
private _getRedirectUrl() {
const DEFAULT_REDIRECT = '/';
const stateKey = this.oauthService.state;
if (stateKey) {
const stateStringified = this._oauthStorage.getItem(stateKey);
if (stateStringified) {
// cleanup state from storage
this._oauthStorage.removeItem(stateKey);
return JSON.parse(stateStringified);
}
}
return DEFAULT_REDIRECT;
}
private configureAuth(config: AuthConfig): Promise<boolean> {
this.oauthService.configure(config);
this.oauthService.tokenValidationHandler = new JwksValidationHandler();
if (config.sessionChecksEnabled) {
this.oauthService.events.pipe(filter((event) => event.type === 'session_terminated')).subscribe(() => {
logout() {
this.oauthService.logOut();
});
}
return this.ensureDiscoveryDocument().then(() => {
this.oauthService.setupAutomaticSilentRefresh();
return void this.allowRefreshTokenAndSilentRefreshOnMultipleTabs();
}).catch(() => {
// catch error to prevent the app from crashing when trying to access unprotected routes
});
}
/**
* Fix a known issue (https://github.com/manfredsteyer/angular-oauth2-oidc/issues/850)
* where multiple tabs can cause the token refresh and the silent refresh to fail.
* This patch is based on the solutions provided in the following comments:
* https://github.com/manfredsteyer/angular-oauth2-oidc/issues/850#issuecomment-889921776 fix silent refresh for the implicit flow
* https://github.com/manfredsteyer/angular-oauth2-oidc/issues/850#issuecomment-1557286966 fix refresh token for the code flow
*/
private allowRefreshTokenAndSilentRefreshOnMultipleTabs() {
let lastUpdatedAccessToken: string | undefined;
if (this.oauthService.hasValidAccessToken()) {
lastUpdatedAccessToken = this.oauthService.getAccessToken();
ensureDiscoveryDocument(): Promise<boolean> {
this._loadDiscoveryDocumentPromise = this._loadDiscoveryDocumentPromise
.catch(() => false)
.then((loaded) => {
if (!loaded) {
return this.oauthService.loadDiscoveryDocument().then(() => true);
}
return true;
});
return this._loadDiscoveryDocumentPromise;
}
const originalRefreshToken = this.oauthService.refreshToken.bind(this.oauthService);
this.oauthService.refreshToken = (): Promise<TokenResponse> =>
navigator.locks.request(`refresh_tokens_${location.origin}`, () => {
if (!!lastUpdatedAccessToken && lastUpdatedAccessToken !== this.oauthService.getAccessToken()) {
(this.oauthService as any).eventsSubject.next(new OAuthSuccessEvent('token_received'));
(this.oauthService as any).eventsSubject.next(new OAuthSuccessEvent('token_refreshed'));
lastUpdatedAccessToken = this.oauthService.getAccessToken();
return;
login(currentUrl?: string): void {
let stateKey: string | undefined;
if (currentUrl) {
const randomValue = window.crypto.getRandomValues(new Uint32Array(1))[0];
stateKey = `auth_state_${randomValue}${Date.now()}`;
this._oauthStorage.setItem(stateKey, JSON.stringify(currentUrl || {}));
}
// initLoginFlow will initialize the login flow in either code or implicit depending on the configuration
this.ensureDiscoveryDocument().then(() => void this.oauthService.initLoginFlow(stateKey));
}
baseAuthLogin(username: string, password: string): Observable<TokenResponse> {
this.oauthService.useHttpBasicAuth = true;
return from(this.oauthService.fetchTokenUsingPasswordFlow(username, password)).pipe(
map((response) => {
const props = new Map<string, string>();
props.set('id_token', response.id_token);
// for backward compatibility we need to set the response in our storage
this.oauthService['storeAccessTokenResponse'](
response.access_token,
response.refresh_token,
response.expires_in,
response.scope,
props
);
return response;
})
);
}
async loginCallback(loginOptions?: LoginOptions): Promise<string | undefined> {
return this.ensureDiscoveryDocument()
.then(() => this.oauthService.tryLogin({ ...loginOptions, preventClearHashAfterLogin: this.authModuleConfig.preventClearHashAfterLogin }))
.then(() => this._getRedirectUrl());
}
private _getRedirectUrl() {
const DEFAULT_REDIRECT = '/';
const stateKey = this.oauthService.state;
if (stateKey) {
const stateStringified = this._oauthStorage.getItem(stateKey);
if (stateStringified) {
// cleanup state from storage
this._oauthStorage.removeItem(stateKey);
return JSON.parse(stateStringified);
}
}
return originalRefreshToken().then((resp) => (lastUpdatedAccessToken = resp.access_token));
});
return DEFAULT_REDIRECT;
}
const originalSilentRefresh = this.oauthService.silentRefresh.bind(this.oauthService);
this.oauthService.silentRefresh = async (params: any = {}, noPrompt = true): Promise<OAuthEvent> =>
navigator.locks.request(`silent_refresh_${location.origin}`, async (): Promise<OAuthEvent> => {
if (lastUpdatedAccessToken !== this.oauthService.getAccessToken()) {
(this.oauthService as any).eventsSubject.next(new OAuthSuccessEvent('token_received'));
(this.oauthService as any).eventsSubject.next(new OAuthSuccessEvent('token_refreshed'));
const event = new OAuthSuccessEvent('silently_refreshed');
(this.oauthService as any).eventsSubject.next(event);
lastUpdatedAccessToken = this.oauthService.getAccessToken();
return event;
} else {
return originalSilentRefresh(params, noPrompt);
}
});
}
private configureAuth(config: AuthConfig): Promise<boolean> {
this.oauthService.configure(config);
this.oauthService.tokenValidationHandler = new JwksValidationHandler();
updateIDPConfiguration(config: AuthConfig) {
this.oauthService.configure(config);
}
if (config.sessionChecksEnabled) {
this.oauthService.events.pipe(filter((event) => event.type === 'session_terminated')).subscribe(() => {
this.oauthService.logOut();
});
}
reloadPage() {
window.location.reload();
}
return this.ensureDiscoveryDocument()
.then(() => {
this.oauthService.setupAutomaticSilentRefresh();
return void this.allowRefreshTokenAndSilentRefreshOnMultipleTabs();
})
.catch(() => {
// catch error to prevent the app from crashing when trying to access unprotected routes
});
}
/**
* Fix a known issue (https://github.com/manfredsteyer/angular-oauth2-oidc/issues/850)
* where multiple tabs can cause the token refresh and the silent refresh to fail.
* This patch is based on the solutions provided in the following comments:
* https://github.com/manfredsteyer/angular-oauth2-oidc/issues/850#issuecomment-889921776 fix silent refresh for the implicit flow
* https://github.com/manfredsteyer/angular-oauth2-oidc/issues/850#issuecomment-1557286966 fix refresh token for the code flow
*/
private allowRefreshTokenAndSilentRefreshOnMultipleTabs() {
let lastUpdatedAccessToken: string | undefined;
if (this.oauthService.hasValidAccessToken()) {
lastUpdatedAccessToken = this.oauthService.getAccessToken();
}
const originalRefreshToken = this.oauthService.refreshToken.bind(this.oauthService);
this.oauthService.refreshToken = (): Promise<TokenResponse> =>
navigator.locks.request(`refresh_tokens_${location.origin}`, () => {
if (!!lastUpdatedAccessToken && lastUpdatedAccessToken !== this.oauthService.getAccessToken()) {
(this.oauthService as any).eventsSubject.next(new OAuthSuccessEvent('token_received'));
(this.oauthService as any).eventsSubject.next(new OAuthSuccessEvent('token_refreshed'));
lastUpdatedAccessToken = this.oauthService.getAccessToken();
return;
}
return originalRefreshToken().then((resp) => (lastUpdatedAccessToken = resp.access_token));
});
const originalSilentRefresh = this.oauthService.silentRefresh.bind(this.oauthService);
this.oauthService.silentRefresh = async (params: any = {}, noPrompt = true): Promise<OAuthEvent> =>
navigator.locks.request(`silent_refresh_${location.origin}`, async (): Promise<OAuthEvent> => {
if (lastUpdatedAccessToken !== this.oauthService.getAccessToken()) {
(this.oauthService as any).eventsSubject.next(new OAuthSuccessEvent('token_received'));
(this.oauthService as any).eventsSubject.next(new OAuthSuccessEvent('token_refreshed'));
const event = new OAuthSuccessEvent('silently_refreshed');
(this.oauthService as any).eventsSubject.next(event);
lastUpdatedAccessToken = this.oauthService.getAccessToken();
return event;
} else {
return originalSilentRefresh(params, noPrompt);
}
});
}
updateIDPConfiguration(config: AuthConfig) {
this.oauthService.configure(config);
}
reloadPage() {
window.location.reload();
}
}
@@ -1,35 +0,0 @@
/*!
* @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 { NoopTranslateModule } from '@alfresco/adf-core';
import { AppListCloudModule } from './app-list-cloud.module';
import { TestBed } from '@angular/core/testing';
describe('AppListCloudModule', () => {
let appListCloudModule: AppListCloudModule;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [AppListCloudModule, NoopTranslateModule]
});
appListCloudModule = TestBed.inject(AppListCloudModule);
});
it('should create an instance', () => {
expect(appListCloudModule).toBeTruthy();
});
});
@@ -16,15 +16,14 @@
*/
import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { CommonModule } from '@angular/common';
import { AppDetailsCloudComponent } from './components/app-details-cloud.component';
import { AppListCloudComponent } from './components/app-list-cloud.component';
import { TEMPLATE_DIRECTIVES, CoreModule } from '@alfresco/adf-core';
export const APP_LIST_CLOUD_DIRECTIVES = [AppListCloudComponent, AppDetailsCloudComponent] as const;
/** @deprecated use `...APP_LIST_CLOUD_DIRECTIVES` instead. */
@NgModule({
imports: [CommonModule, ...TEMPLATE_DIRECTIVES, MaterialModule, CoreModule],
declarations: [AppListCloudComponent, AppDetailsCloudComponent],
imports: [AppListCloudComponent, AppDetailsCloudComponent],
exports: [AppListCloudComponent, AppDetailsCloudComponent]
})
export class AppListCloudModule {}
@@ -19,7 +19,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { fakeApplicationInstance } from '../mock/app-model.mock';
import { AppDetailsCloudComponent } from './app-details-cloud.component';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { AppListCloudModule } from '../app-list-cloud.module';
import { DEFAULT_APP_INSTANCE_THEME } from '../models/application-instance.model';
describe('AppDetailsCloudComponent', () => {
@@ -29,7 +28,7 @@ describe('AppDetailsCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, AppListCloudModule]
imports: [ProcessServiceCloudTestingModule, AppDetailsCloudComponent]
});
fixture = TestBed.createComponent(AppDetailsCloudComponent);
component = fixture.componentInstance;
@@ -18,7 +18,7 @@
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { AppDetailsCloudComponent } from './app-details-cloud.component';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { AppListCloudModule } from '../app-list-cloud.module';
import { APP_LIST_CLOUD_DIRECTIVES } from '../app-list-cloud.module';
import { fakeApplicationInstance } from '../mock/app-model.mock';
import { importProvidersFrom } from '@angular/core';
@@ -27,7 +27,7 @@ export default {
title: 'Process Services Cloud/App List Cloud/App Details Cloud',
decorators: [
moduleMetadata({
imports: [AppListCloudModule]
imports: [...APP_LIST_CLOUD_DIRECTIVES]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
@@ -17,46 +17,49 @@
import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
import { ApplicationInstanceModel, DEFAULT_APP_INSTANCE_ICON, DEFAULT_APP_INSTANCE_THEME } from '../models/application-instance.model';
import { CommonModule } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
@Component({
selector: 'adf-cloud-app-details',
templateUrl: './app-details-cloud.component.html',
styleUrls: ['./app-details-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
selector: 'adf-cloud-app-details',
standalone: true,
imports: [CommonModule, MatCardModule, MatIconModule],
templateUrl: './app-details-cloud.component.html',
styleUrls: ['./app-details-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class AppDetailsCloudComponent {
@Input()
applicationInstance: ApplicationInstanceModel;
@Input()
applicationInstance: ApplicationInstanceModel;
@Output()
selectedApp = new EventEmitter<ApplicationInstanceModel>();
@Output()
selectedApp = new EventEmitter<ApplicationInstanceModel>();
/**
* Pass the selected app as next
*
* @param app application model
*/
onSelectApp(app: ApplicationInstanceModel): void {
this.selectedApp.emit(app);
}
/**
* Pass the selected app as next
*
* @param app application model
*/
onSelectApp(app: ApplicationInstanceModel): void {
this.selectedApp.emit(app);
}
/**
* Get application instance theme
*
* @returns the name of the theme
*/
getTheme(): string {
return this.applicationInstance.theme || DEFAULT_APP_INSTANCE_THEME;
}
/**
* Get application instance theme
*
* @returns the name of the theme
*/
getTheme(): string {
return this.applicationInstance.theme || DEFAULT_APP_INSTANCE_THEME;
}
/**
* Get application instance icon
*
* @returns the name of the icon
*/
getIcon(): string {
return this.applicationInstance.icon || DEFAULT_APP_INSTANCE_ICON;
}
/**
* Get application instance icon
*
* @returns the name of the icon
*/
getIcon(): string {
return this.applicationInstance.icon || DEFAULT_APP_INSTANCE_ICON;
}
}
@@ -23,6 +23,8 @@ import { fakeApplicationInstance } from '../mock/app-model.mock';
import { AppListCloudComponent, LAYOUT_GRID, LAYOUT_LIST } from './app-list-cloud.component';
import { AppsProcessCloudService } from '../services/apps-process-cloud.service';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { MatIconModule } from '@angular/material/icon';
import { CustomEmptyContentTemplateDirective } from '@alfresco/adf-core';
describe('AppListCloudComponent', () => {
let component: AppListCloudComponent;
@@ -40,6 +42,8 @@ describe('AppListCloudComponent', () => {
};
@Component({
standalone: true,
imports: [MatIconModule, CustomEmptyContentTemplateDirective, AppListCloudComponent],
template: `
<adf-cloud-app-list>
<adf-custom-empty-content-template>
@@ -53,8 +57,7 @@ describe('AppListCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule],
declarations: [CustomEmptyAppListCloudTemplateComponent]
imports: [ProcessServiceCloudTestingModule, CustomEmptyAppListCloudTemplateComponent]
});
fixture = TestBed.createComponent(AppListCloudComponent);
component = fixture.componentInstance;
@@ -17,7 +17,7 @@
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { AppListCloudModule } from '../app-list-cloud.module';
import { APP_LIST_CLOUD_DIRECTIVES } from '../app-list-cloud.module';
import { AppListCloudComponent } from './app-list-cloud.component';
import { importProvidersFrom } from '@angular/core';
@@ -26,7 +26,7 @@ export default {
title: 'Process Services Cloud/App List Cloud/App List Cloud',
decorators: [
moduleMetadata({
imports: [AppListCloudModule]
imports: [...APP_LIST_CLOUD_DIRECTIVES]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
@@ -15,21 +15,19 @@
* limitations under the License.
*/
import { CustomEmptyContentTemplateDirective } from '@alfresco/adf-core';
import {
AfterContentInit,
Component,
ContentChild,
EventEmitter,
Input,
OnInit,
Output,
ViewEncapsulation
} from '@angular/core';
import { CustomEmptyContentTemplateDirective, EmptyContentComponent } from '@alfresco/adf-core';
import { AfterContentInit, Component, ContentChild, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { Observable, of, Subject } from 'rxjs';
import { AppsProcessCloudService } from '../services/apps-process-cloud.service';
import { ApplicationInstanceModel } from '../models/application-instance.model';
import { catchError } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { MatLineModule } from '@angular/material/core';
import { MatListModule } from '@angular/material/list';
import { AppDetailsCloudComponent } from './app-details-cloud.component';
import { TranslateModule } from '@ngx-translate/core';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
export const LAYOUT_LIST: string = 'LIST';
export const LAYOUT_GRID: string = 'GRID';
@@ -37,6 +35,17 @@ export const RUNNING_STATUS: string = 'RUNNING';
@Component({
selector: 'adf-cloud-app-list',
standalone: true,
imports: [
CommonModule,
MatIconModule,
MatLineModule,
MatListModule,
AppDetailsCloudComponent,
TranslateModule,
EmptyContentComponent,
MatProgressSpinnerModule
],
templateUrl: './app-list-cloud.component.html',
styleUrls: ['./app-list-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -60,20 +69,19 @@ export class AppListCloudComponent implements OnInit, AfterContentInit {
loadingError$ = new Subject<boolean>();
hasEmptyCustomContentTemplate: boolean = false;
constructor(private appsProcessCloudService: AppsProcessCloudService) { }
constructor(private appsProcessCloudService: AppsProcessCloudService) {}
ngOnInit() {
if (!this.isValidType()) {
this.setDefaultLayoutType();
}
this.apps$ = this.appsProcessCloudService.getDeployedApplicationsByStatus(RUNNING_STATUS)
.pipe(
catchError(() => {
this.loadingError$.next(true);
return of();
})
);
this.apps$ = this.appsProcessCloudService.getDeployedApplicationsByStatus(RUNNING_STATUS).pipe(
catchError(() => {
this.loadingError$.next(true);
return of();
})
);
}
ngAfterContentInit() {
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { Observable, from, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { AppConfigService } from '@alfresco/adf-core';
@@ -26,9 +26,12 @@ import { RequestOptions } from '@alfresco/js-api';
@Injectable({ providedIn: 'root' })
export class AppsProcessCloudService {
private adfHttpClient = inject(AdfHttpClient);
private appConfigService = inject(AppConfigService);
deployedApps: ApplicationInstanceModel[];
constructor(private adfHttpClient: AdfHttpClient, private appConfigService: AppConfigService) {
constructor() {
this.loadApps();
}
@@ -37,11 +37,11 @@ describe('DateRangeFilterComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule]
imports: [ProcessServiceCloudTestingModule, DateRangeFilterComponent]
});
fixture = TestBed.createComponent(DateRangeFilterComponent);
component = fixture.componentInstance;
service = TestBed.inject(DateRangeFilterService);
service = new DateRangeFilterService();
component.processFilterProperty = {
key: 'createdDate',
@@ -18,7 +18,6 @@
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { mockFilterProperty } from '../mock/date-range-filter.mock';
import { ProcessCommonModule } from '../process-common.module';
import { DateRangeFilterComponent } from './date-range-filter.component';
import { importProvidersFrom } from '@angular/core';
@@ -27,7 +26,7 @@ export default {
title: 'Process Services Cloud/Process Common/Date Range Filter',
decorators: [
moduleMetadata({
imports: [ProcessCommonModule]
imports: [DateRangeFilterComponent]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
@@ -16,13 +16,17 @@
*/
import { Component, Input, EventEmitter, Output, OnInit } from '@angular/core';
import { MatSelectChange } from '@angular/material/select';
import { MatSelectChange, MatSelectModule } from '@angular/material/select';
import { ProcessFilterProperties, ProcessFilterOptions } from '../../process/process-filters/models/process-filter-cloud.model';
import { FormGroup, FormControl } from '@angular/forms';
import { FormGroup, FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { DateRangeFilter, DateCloudFilterType } from '../../models/date-cloud-filter.model';
import { endOfDay, isValid, startOfDay } from 'date-fns';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { DateAdapter, MAT_DATE_FORMATS, MatOptionModule } from '@angular/material/core';
import { ADF_DATE_FORMATS, AdfDateFnsAdapter } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field';
interface DateRangeFormProps {
from: FormControl<Date>;
@@ -31,6 +35,17 @@ interface DateRangeFormProps {
@Component({
selector: 'adf-cloud-date-range-filter',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatDatepickerModule,
MatFormFieldModule,
FormsModule,
ReactiveFormsModule,
MatOptionModule,
MatSelectModule
],
styleUrls: ['./date-range-filter.component.scss'],
templateUrl: './date-range-filter.component.html',
providers: [
@@ -15,17 +15,15 @@
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
import { DateRangeFilterService } from './date-range-filter.service';
import { DateCloudFilterType } from '../../models/date-cloud-filter.model';
import { add, endOfDay, endOfMonth, endOfQuarter, endOfYear, startOfDay, startOfMonth, startOfQuarter, startOfYear } from 'date-fns';
describe('Date Range Filter service', () => {
let service: DateRangeFilterService;
beforeEach(() => {
service = TestBed.inject(DateRangeFilterService);
service = new DateRangeFilterService();
});
it('should return today range', () => {
@@ -15,27 +15,42 @@
* limitations under the License.
*/
import { Injectable } from '@angular/core';
import { DateRangeFilter, DateCloudFilterType } from '../../models/date-cloud-filter.model';
import { add, endOfDay, endOfMonth, endOfQuarter, endOfWeek, endOfYear, startOfDay, startOfMonth, startOfQuarter, startOfWeek, startOfYear } from 'date-fns';
import {
add,
endOfDay,
endOfMonth,
endOfQuarter,
endOfWeek,
endOfYear,
startOfDay,
startOfMonth,
startOfQuarter,
startOfWeek,
startOfYear
} from 'date-fns';
@Injectable({
providedIn: 'root'
})
export class DateRangeFilterService {
currentDate = new Date();
getDateRange(type: DateCloudFilterType): DateRangeFilter {
switch (type) {
case DateCloudFilterType.TODAY: return this.getTodayDateRange();
case DateCloudFilterType.TOMORROW: return this.getTomorrowDateRange();
case DateCloudFilterType.NEXT_7_DAYS: return this.getNext7DaysDateRange();
case DateCloudFilterType.WEEK: return this.getCurrentWeekRange();
case DateCloudFilterType.MONTH: return this.getCurrentMonthDateRange();
case DateCloudFilterType.QUARTER: return this.getQuarterDateRange();
case DateCloudFilterType.YEAR: return this.getCurrentYearDateRange();
default: return this.resetDateRange();
case DateCloudFilterType.TODAY:
return this.getTodayDateRange();
case DateCloudFilterType.TOMORROW:
return this.getTomorrowDateRange();
case DateCloudFilterType.NEXT_7_DAYS:
return this.getNext7DaysDateRange();
case DateCloudFilterType.WEEK:
return this.getCurrentWeekRange();
case DateCloudFilterType.MONTH:
return this.getCurrentMonthDateRange();
case DateCloudFilterType.QUARTER:
return this.getQuarterDateRange();
case DateCloudFilterType.YEAR:
return this.getCurrentYearDateRange();
default:
return this.resetDateRange();
}
}
@@ -79,7 +94,7 @@ export class DateRangeFilterService {
}
private getCurrentWeekRange(): DateRangeFilter {
return {
return {
startDate: startOfWeek(new Date()).toISOString(),
endDate: endOfWeek(new Date()).toISOString()
};
@@ -16,17 +16,11 @@
*/
import { NgModule } from '@angular/core';
import { CoreModule } from '@alfresco/adf-core';
import { DateRangeFilterComponent } from './date-range-filter/date-range-filter.component';
import { MaterialModule } from '../material.module';
import { CommonModule } from '@angular/common';
import { DateRangeFilterService } from './date-range-filter/date-range-filter.service';
import { ReactiveFormsModule } from '@angular/forms';
/** @deprecated use DateRangeFilterComponent instead */
@NgModule({
declarations: [DateRangeFilterComponent],
imports: [CommonModule, CoreModule, MaterialModule, ReactiveFormsModule],
exports: [DateRangeFilterComponent],
providers: [DateRangeFilterService]
imports: [DateRangeFilterComponent],
exports: [DateRangeFilterComponent]
})
export class ProcessCommonModule {}
@@ -19,6 +19,7 @@ import { Component } from '@angular/core';
@Component({
selector: 'adf-cloud-form-custom-outcomes',
standalone: true,
template: '<ng-content></ng-content>'
})
export class FormCustomOutcomesComponent {}
@@ -46,7 +46,6 @@ import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { Observable, of, throwError } from 'rxjs';
import { FormCloudModule } from '../form-cloud.module';
import {
cloudFormMock,
conditionalUploadWidgetsMock,
@@ -98,7 +97,7 @@ describe('FormCloudComponent', () => {
const resolver = formRenderingService.getComponentTypeResolver(type);
const widgetType = resolver(null);
const factoryResolver: ComponentFactoryResolver = TestBed.inject(ComponentFactoryResolver);
const factoryResolver = TestBed.inject(ComponentFactoryResolver);
const factory = factoryResolver.resolveComponentFactory(widgetType);
const componentRef = factory.create(injector);
@@ -107,7 +106,7 @@ describe('FormCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule, FormCloudComponent],
providers: [
{
provide: VersionCompatibilityService,
@@ -1539,7 +1538,7 @@ describe('retrieve metadata on submit', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [AuthModule.forRoot({ useHash: true }), NoopAnimationsModule, TranslateModule.forRoot(), CoreModule.forRoot(), FormCloudModule],
imports: [ProcessServiceCloudTestingModule, FormCloudComponent],
providers: [
provideTranslations('app', 'resources'),
{
@@ -44,7 +44,12 @@ import {
ContentLinkModel,
UploadWidgetContentLinkModel,
FormEvent,
ConfirmDialogComponent
ConfirmDialogComponent,
FormatSpacePipe,
FormRendererComponent,
ToolbarDividerComponent,
ToolbarComponent,
FormStylePipe
} from '@alfresco/adf-core';
import { FormCloudService } from '../services/form-cloud.service';
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
@@ -54,9 +59,29 @@ 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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
import { A11yModule } from '@angular/cdk/a11y';
@Component({
selector: 'adf-cloud-form',
standalone: true,
imports: [
CommonModule,
TranslateModule,
FormatSpacePipe,
MatButtonModule,
MatCardModule,
FormRendererComponent,
MatIconModule,
ToolbarDividerComponent,
ToolbarComponent,
A11yModule,
FormStylePipe
],
templateUrl: './form-cloud.component.html',
styleUrls: ['./form-cloud.component.scss']
})
@@ -17,7 +17,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormDefinitionSelectorCloudComponent } from './form-definition-selector-cloud.component';
import { of } from 'rxjs';
import { FormDefinitionSelectorCloudService } from '../services/form-definition-selector-cloud.service';
@@ -33,8 +32,7 @@ describe('FormDefinitionCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
imports: [ProcessServiceCloudTestingModule, FormDefinitionSelectorCloudComponent]
});
fixture = TestBed.createComponent(FormDefinitionSelectorCloudComponent);
service = TestBed.inject(FormDefinitionSelectorCloudService);
@@ -16,7 +16,7 @@
*/
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { FormCloudModule } from '../form-cloud.module';
import { FORM_CLOUD_DIRECTIVES } from '../form-cloud.module';
import { FormDefinitionSelectorCloudComponent } from './form-definition-selector-cloud.component';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { FormDefinitionSelectorCloudService } from '../services/form-definition-selector-cloud.service';
@@ -28,7 +28,7 @@ export default {
title: 'Process Services Cloud/Form Cloud/Form Definition Selector Cloud',
decorators: [
moduleMetadata({
imports: [FormCloudModule],
imports: [...FORM_CLOUD_DIRECTIVES],
providers: [{ provide: FormDefinitionSelectorCloudService, useClass: FormDefinitionSelectorCloudServiceMock }]
}),
applicationConfig({
@@ -18,17 +18,21 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Observable } from 'rxjs';
import { FormDefinitionSelectorCloudService } from '../services/form-definition-selector-cloud.service';
import { MatSelectChange } from '@angular/material/select';
import { MatSelectChange, MatSelectModule } from '@angular/material/select';
import { FormRepresentation } from '../../services/form-fields.interfaces';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatOptionModule } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
@Component({
selector: 'adf-cloud-form-definition-selector',
standalone: true,
imports: [CommonModule, TranslateModule, MatOptionModule, MatFormFieldModule, MatSelectModule],
templateUrl: './form-definition-selector-cloud.component.html',
styleUrls: ['./form-definition-selector-cloud.component.scss']
})
export class FormDefinitionSelectorCloudComponent implements OnInit {
/** Name of the application. If specified, this shows the users who have access to the app. */
@Input()
appName: string = '';
@@ -39,8 +43,7 @@ export class FormDefinitionSelectorCloudComponent implements OnInit {
forms$: Observable<FormRepresentation[]>;
constructor(private formDefinitionCloudService: FormDefinitionSelectorCloudService) {
}
constructor(private formDefinitionCloudService: FormDefinitionSelectorCloudService) {}
ngOnInit(): void {
this.forms$ = this.formDefinitionCloudService.getStandAloneTaskForms(this.appName);
@@ -49,5 +52,4 @@ export class FormDefinitionSelectorCloudComponent implements OnInit {
onSelect(event: MatSelectChange) {
this.selectForm.emit(event.value);
}
}
@@ -16,8 +16,12 @@
*/
import { Component, Input } from '@angular/core';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { TranslateModule } from '@ngx-translate/core';
@Component({
standalone: true,
imports: [MatProgressSpinnerModule, TranslateModule],
templateUrl: './form-spinner.component.html',
styleUrls: ['./form-spinner.component.scss']
})
@@ -61,16 +61,9 @@ import {
mockMyNodeId
} from '../../../mocks/attach-file-cloud-widget.mock';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import {
ContentModule,
ContentNodeSelectorPanelService,
NewVersionUploaderDataAction,
NewVersionUploaderService
} from '@alfresco/adf-content-services';
import { ContentNodeSelectorPanelService, NewVersionUploaderDataAction, NewVersionUploaderService } from '@alfresco/adf-content-services';
import { By } from '@angular/platform-browser';
import { of, throwError } from 'rxjs';
import { FormCloudModule } from '../../../form-cloud.module';
const mockNodeToBeVersioned: any = {
isFile: true,
@@ -150,8 +143,7 @@ describe('AttachFileCloudWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, FormCloudModule, ContentModule.forRoot()],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
imports: [ProcessServiceCloudTestingModule, AttachFileCloudWidgetComponent]
});
notificationService = TestBed.inject(NotificationService);
downloadService = TestBed.inject(DownloadService);
@@ -26,7 +26,8 @@ import {
ContentLinkModel,
AppConfigService,
UploadWidgetContentLinkModel,
DestinationFolderPath
DestinationFolderPath,
ErrorWidgetComponent
} from '@alfresco/adf-core';
import { Node, NodesApi, RelatedContentRepresentation } from '@alfresco/js-api';
import { ContentCloudNodeSelectorService } from '../../../services/content-cloud-node-selector.service';
@@ -41,15 +42,22 @@ import {
NewVersionUploaderService,
VersionManagerUploadData
} from '@alfresco/adf-content-services';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { FilePropertiesTableCloudComponent } from './file-properties-table-cloud.component';
export const RETRIEVE_METADATA_OPTION = 'retrieveMetadata';
export const ALIAS_ROOT_FOLDER = '-root-';
export const ALIAS_USER_FOLDER = '-my-';
export const APP_NAME = '-appname-';
export const VALID_ALIAS = [ALIAS_ROOT_FOLDER, ALIAS_USER_FOLDER, '-shared-'];
const RETRIEVE_METADATA_OPTION = 'retrieveMetadata';
const ALIAS_ROOT_FOLDER = '-root-';
const ALIAS_USER_FOLDER = '-my-';
const APP_NAME = '-appname-';
const VALID_ALIAS = [ALIAS_ROOT_FOLDER, ALIAS_USER_FOLDER, '-shared-'];
@Component({
selector: 'adf-cloud-attach-file-cloud-widget',
standalone: true,
imports: [CommonModule, TranslateModule, ErrorWidgetComponent, MatButtonModule, MatIconModule, FilePropertiesTableCloudComponent],
templateUrl: './attach-file-cloud-widget.component.html',
styleUrls: ['./attach-file-cloud-widget.component.scss'],
host: {
@@ -20,21 +20,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { FilePropertiesTableCloudComponent } from './file-properties-table-cloud.component';
import { By } from '@angular/platform-browser';
import { MatTableModule } from '@angular/material/table';
import { MatIconModule } from '@angular/material/icon';
describe('FilePropertiesTableCloudComponent', () => {
let widget: FilePropertiesTableCloudComponent;
let fixture: ComponentFixture<FilePropertiesTableCloudComponent>;
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, MatTableModule, MatIconModule],
declarations: [FilePropertiesTableCloudComponent]
}).compileComponents();
});
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, FilePropertiesTableCloudComponent]
});
fixture = TestBed.createComponent(FilePropertiesTableCloudComponent);
widget = fixture.componentInstance;
@@ -64,9 +59,7 @@ describe('FilePropertiesTableCloudComponent', () => {
];
widget.hasFile = true;
widget.displayedColumns = ['icon', 'fileName'];
fixture.detectChanges();
});
@@ -18,14 +18,34 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { LocalizedDatePipe, ThumbnailService } from '@alfresco/adf-core';
import { LocalizedDatePipe, ThumbnailService, UploadDirective } from '@alfresco/adf-core';
import { Node } from '@alfresco/js-api';
import { NewVersionUploaderDialogData } from '@alfresco/adf-content-services';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { MatTableModule } from '@angular/material/table';
import { MatLineModule } from '@angular/material/core';
import { MatListModule } from '@angular/material/list';
export const RETRIEVE_METADATA_OPTION = 'retrieveMetadata';
const RETRIEVE_METADATA_OPTION = 'retrieveMetadata';
@Component({
selector: 'adf-cloud-file-properties-table',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatIconModule,
MatButtonModule,
MatMenuModule,
UploadDirective,
MatTableModule,
MatLineModule,
MatListModule
],
templateUrl: './file-properties-table-cloud.component.html',
styleUrls: ['./file-properties-table-cloud.component.scss']
})
@@ -9,8 +9,8 @@
<img matListItemLine class="adf-upload-widget__icon" [id]="'file-'+file.id+'-icon'"
[src]="getIcon(file.content.mimeType)" [alt]="mimeTypeIcon" (click)="fileClicked(file)"
(keyup.enter)="fileClicked(file)" role="button" tabindex="0" />
<span class="adf-upload-widget__button" matLine id="{{'file-'+file.id}}" (click)="fileClicked(file)" (keyup.enter)="fileClicked(file)"
role="button" tabindex="0" class="adf-file">{{file.name}}</span>
<span class="adf-upload-widget__button adf-file" matLine id="{{'file-'+file.id}}" (click)="fileClicked(file)" (keyup.enter)="fileClicked(file)"
role="button" tabindex="0">{{file.name}}</span>
<button *ngIf="!field.readOnly" mat-icon-button [id]="'file-'+file.id+'-remove'"
(click)="removeFile(file);" (keyup.enter)="removeFile(file);">
<mat-icon class="mat-24">highlight_off</mat-icon>
@@ -21,13 +21,21 @@ import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild, ViewEnc
import { Node } from '@alfresco/js-api';
import { Observable, from } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { WidgetComponent, FormService, ThumbnailService, NotificationService } from '@alfresco/adf-core';
import { WidgetComponent, FormService, ThumbnailService, NotificationService, ErrorWidgetComponent } from '@alfresco/adf-core';
import { ProcessCloudContentService } from '../../../services/process-cloud-content.service';
import { FileSourceTypes, DestinationFolderPathType } from '../../../models/form-cloud-representation.model';
import { VersionManagerUploadData } from '@alfresco/adf-content-services';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatLineModule } from '@angular/material/core';
import { MatListModule } from '@angular/material/list';
@Component({
selector: 'upload-cloud-widget',
standalone: true,
imports: [CommonModule, TranslateModule, MatIconModule, MatButtonModule, ErrorWidgetComponent, MatLineModule, MatListModule],
templateUrl: './upload-cloud.widget.html',
styleUrls: ['./upload-cloud.widget.scss'],
host: {
@@ -81,7 +81,7 @@ describe('DisplayRichTextWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule]
imports: [CoreTestingModule, DisplayRichTextWidgetComponent]
});
fixture = TestBed.createComponent(DisplayRichTextWidgetComponent);
widget = fixture.componentInstance;
@@ -94,7 +94,7 @@ describe('DisplayRichTextWidgetComponent', () => {
expect(widget).toBeTruthy();
});
it('should parse editorjs data to html', async () => {
it('should parse editor.js data to html', async () => {
const expectedHtml =
'<h1>Editor.js</h1><p class="ce-tune-alignment--left">Display some <font color="#ff1300">formatted</font> <mark class="cdx-marker">text</mark></p>';
@@ -24,6 +24,7 @@ import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'display-rich-text',
standalone: true,
templateUrl: './display-rich-text.widget.html',
styleUrls: ['./display-rich-text.widget.scss'],
host: {
@@ -15,10 +15,9 @@
* limitations under the License.
*/
import { TranslateModule } from '@ngx-translate/core';
import { FileViewerWidgetComponent } from './file-viewer.widget';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormModel, FormService, FormFieldModel } from '@alfresco/adf-core';
import { FormModel, FormService, FormFieldModel, NoopTranslateModule, NoopAuthModule } from '@alfresco/adf-core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
describe('FileViewerWidgetComponent', () => {
@@ -44,8 +43,7 @@ describe('FileViewerWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [FileViewerWidgetComponent],
imports: [NoopTranslateModule, NoopAuthModule, FileViewerWidgetComponent],
providers: [{ provide: FormService, useValue: formServiceStub }],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
@@ -16,12 +16,17 @@
*/
import { Component, ViewEncapsulation } from '@angular/core';
import { FormService, BaseViewerWidgetComponent } from '@alfresco/adf-core';
import { FormService, BaseViewerWidgetComponent, ErrorWidgetComponent } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { AlfrescoViewerComponent } from '@alfresco/adf-content-services';
/* eslint-disable @angular-eslint/component-selector */
@Component({
selector: 'file-viewer-widget',
standalone: true,
imports: [CommonModule, TranslateModule, AlfrescoViewerComponent, ErrorWidgetComponent],
templateUrl: './file-viewer.widget.html',
styleUrls: ['./file-viewer.widget.scss'],
host: {
@@ -33,8 +33,7 @@ describe('GroupCloudWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule],
declarations: [GroupCloudWidgetComponent],
imports: [ProcessServiceCloudTestingModule, GroupCloudWidgetComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
fixture = TestBed.createComponent(GroupCloudWidgetComponent);
@@ -16,17 +16,22 @@
*/
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { WidgetComponent, FormService } from '@alfresco/adf-core';
import { WidgetComponent, FormService, ErrorWidgetComponent } from '@alfresco/adf-core';
import { UntypedFormControl } from '@angular/forms';
import { filter, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { ComponentSelectionMode } from '../../../../types';
import { IdentityGroupModel } from '../../../../group/models/identity-group.model';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { GroupCloudComponent } from '../../../../group/components/group-cloud.component';
/* eslint-disable @angular-eslint/component-selector */
@Component({
selector: 'group-cloud-widget',
standalone: true,
imports: [CommonModule, TranslateModule, ErrorWidgetComponent, GroupCloudComponent],
templateUrl: './group-cloud.widget.html',
host: {
'(click)': 'event($event)',
@@ -42,7 +47,6 @@ import { IdentityGroupModel } from '../../../../group/models/identity-group.mode
encapsulation: ViewEncapsulation.None
})
export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
typeId = 'GroupCloudWidgetComponent';
@@ -65,9 +69,7 @@ export class GroupCloudWidgetComponent extends WidgetComponent implements OnInit
this.preSelectGroup = this.field.value ? this.field.value : [];
this.validate = this.field.readOnly ? false : true;
}
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
this.search = new UntypedFormControl({value: '', disabled: this.field.readOnly}, []),
this.search = new UntypedFormControl({ value: '', disabled: this.field.readOnly }, []);
this.search.statusChanges
.pipe(
filter((value: string) => value === 'INVALID'),
@@ -18,7 +18,6 @@
import { FormFieldModel, FormFieldTypes, FormModel, IdentityUserModel } from '@alfresco/adf-core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PeopleCloudWidgetComponent } from './people-cloud.widget';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { IdentityUserService } from '../../../../people/services/identity-user.service';
import { mockShepherdsPie, mockYorkshirePudding } from '../../../../people/mock/people-cloud.mock';
@@ -36,9 +35,7 @@ describe('PeopleCloudWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule],
declarations: [PeopleCloudWidgetComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
imports: [ProcessServiceCloudTestingModule, PeopleCloudWidgetComponent]
});
identityUserService = TestBed.inject(IdentityUserService);
fixture = TestBed.createComponent(PeopleCloudWidgetComponent);
@@ -16,18 +16,23 @@
*/
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { WidgetComponent, FormService } from '@alfresco/adf-core';
import { WidgetComponent, FormService, ErrorWidgetComponent } from '@alfresco/adf-core';
import { UntypedFormControl } from '@angular/forms';
import { filter, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { ComponentSelectionMode } from '../../../../types';
import { IdentityUserModel } from '../../../../people/models/identity-user.model';
import { IdentityUserService } from '../../../../people/services/identity-user.service';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { PeopleCloudComponent } from '../../../../people/components/people-cloud.component';
/* eslint-disable @angular-eslint/component-selector */
@Component({
selector: 'people-cloud-widget',
standalone: true,
imports: [CommonModule, TranslateModule, ErrorWidgetComponent, PeopleCloudComponent],
templateUrl: './people-cloud.widget.html',
host: {
'(click)': 'event($event)',
@@ -43,7 +48,6 @@ import { IdentityUserService } from '../../../../people/services/identity-user.s
encapsulation: ViewEncapsulation.None
})
export class PeopleCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
typeId = 'PeopleCloudWidgetComponent';
@@ -70,7 +74,7 @@ export class PeopleCloudWidgetComponent extends WidgetComponent implements OnIni
this.validate = this.field.readOnly ? false : true;
}
this.search = new UntypedFormControl({value: '', disabled: this.field.readOnly}, []);
this.search = new UntypedFormControl({ value: '', disabled: this.field.readOnly }, []);
this.search.statusChanges
.pipe(
@@ -94,7 +98,7 @@ export class PeopleCloudWidgetComponent extends WidgetComponent implements OnIni
if (this.field.selectLoggedUser && !this.field.value) {
const userInfo = this.identityUserService.getCurrentUserInfo();
this.preSelectUsers = [ userInfo ];
this.preSelectUsers = [userInfo];
this.onChangedUser(this.preSelectUsers);
}
}
@@ -16,13 +16,17 @@
*/
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewEncapsulation } from '@angular/core';
import { PresetConfig, NodesApiService } from '@alfresco/adf-content-services';
import { PresetConfig, NodesApiService, ContentMetadataComponent } from '@alfresco/adf-content-services';
import { Node } from '@alfresco/js-api';
import { CommonModule } from '@angular/common';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
/* eslint-disable @angular-eslint/component-selector */
@Component({
selector: 'adf-properties-viewer-wrapper',
standalone: true,
imports: [CommonModule, ContentMetadataComponent, MatProgressSpinnerModule],
templateUrl: './properties-viewer-wrapper.component.html',
encapsulation: ViewEncapsulation.None
})
@@ -29,7 +29,7 @@ describe('PropertiesViewerWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule, PropertiesViewerWrapperComponent],
providers: [NodesApiService, { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }]
});
fixture = TestBed.createComponent(PropertiesViewerWrapperComponent);
@@ -47,8 +47,7 @@ describe('PropertiesViewerWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule],
declarations: [PropertiesViewerWrapperComponent],
imports: [ProcessServiceCloudTestingModule, PropertiesViewerWrapperComponent],
providers: [NodesApiService, { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }]
});
fixture = TestBed.createComponent(PropertiesViewerWidgetComponent);
@@ -16,13 +16,18 @@
*/
import { Component, EventEmitter, Output, ViewEncapsulation } from '@angular/core';
import { BaseViewerWidgetComponent, FormService } from '@alfresco/adf-core';
import { BaseViewerWidgetComponent, ErrorWidgetComponent, FormService } from '@alfresco/adf-core';
import { Node } from '@alfresco/js-api';
import { CommonModule } from '@angular/common';
import { PropertiesViewerWrapperComponent } from './properties-viewer-wrapper/properties-viewer-wrapper.component';
import { TranslateModule } from '@ngx-translate/core';
/* eslint-disable @angular-eslint/component-selector */
@Component({
selector: 'adf-properties-viewer-widget',
standalone: true,
imports: [CommonModule, PropertiesViewerWrapperComponent, ErrorWidgetComponent, TranslateModule],
templateUrl: './properties-viewer.widget.html',
styleUrls: ['./properties-viewer.widget.scss'],
host: {
@@ -39,7 +44,6 @@ import { Node } from '@alfresco/js-api';
encapsulation: ViewEncapsulation.None
})
export class PropertiesViewerWidgetComponent extends BaseViewerWidgetComponent {
@Output()
nodeContentLoaded: EventEmitter<Node> = new EventEmitter();
@@ -44,7 +44,7 @@ describe('RadioButtonsCloudWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule]
imports: [ProcessServiceCloudTestingModule, RadioButtonsCloudWidgetComponent]
});
formCloudService = TestBed.inject(FormCloudService);
fixture = TestBed.createComponent(RadioButtonsCloudWidgetComponent);
@@ -18,14 +18,19 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { WidgetComponent, FormService, FormFieldOption, ErrorMessageModel } from '@alfresco/adf-core';
import { WidgetComponent, FormService, FormFieldOption, ErrorMessageModel, ErrorWidgetComponent } 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 { TranslateModule, TranslateService } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { MatRadioModule } from '@angular/material/radio';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'radio-buttons-cloud-widget',
standalone: true,
imports: [CommonModule, TranslateModule, ErrorWidgetComponent, MatRadioModule, FormsModule],
templateUrl: './radio-buttons-cloud.widget.html',
styleUrls: ['./radio-buttons-cloud.widget.scss'],
host: {
@@ -16,87 +16,41 @@
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CoreModule, FormatSpacePipe, TOOLBAR_DIRECTIVES, FormStylePipe } from '@alfresco/adf-core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MaterialModule } from '../material.module';
import { FormCloudComponent } from './components/form-cloud.component';
import { FormDefinitionSelectorCloudComponent } from './components/form-definition-selector-cloud.component';
import { FormCustomOutcomesComponent } from './components/form-cloud-custom-outcomes.component';
import {
AlfrescoViewerComponent,
CONTENT_METADATA_DIRECTIVES,
CONTENT_UPLOAD_DIRECTIVES,
ContentNodeSelectorModule
} from '@alfresco/adf-content-services';
import { GroupCloudWidgetComponent } from './components/widgets/group/group-cloud.widget';
import { PeopleCloudWidgetComponent } from './components/widgets/people/people-cloud.widget';
import { AttachFileCloudWidgetComponent } from './components/widgets/attach-file/attach-file-cloud-widget.component';
import { UploadCloudWidgetComponent } from './components/widgets/attach-file/upload-cloud.widget';
import { PeopleCloudModule } from '../people/people-cloud.module';
import { GroupCloudModule } from '../group/group-cloud.module';
import { PropertiesViewerWidgetComponent } from './components/widgets/properties-viewer/properties-viewer.widget';
import { PropertiesViewerWrapperComponent } from './components/widgets/properties-viewer/properties-viewer-wrapper/properties-viewer-wrapper.component';
import { RadioButtonsCloudWidgetComponent } from './components/widgets/radio-buttons/radio-buttons-cloud.widget';
import { FilePropertiesTableCloudComponent } from './components/widgets/attach-file/file-properties-table-cloud.component';
import { FileViewerWidgetComponent } from './components/widgets/file-viewer/file-viewer.widget';
import { DisplayRichTextWidgetComponent } from './components/widgets/display-rich-text/display-rich-text.widget';
import { RichTextEditorModule } from '../rich-text-editor';
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';
export const FORM_CLOUD_DIRECTIVES = [
FormSpinnerComponent,
UploadCloudWidgetComponent,
AttachFileCloudWidgetComponent,
FilePropertiesTableCloudComponent,
DisplayRichTextWidgetComponent,
FileViewerWidgetComponent,
GroupCloudWidgetComponent,
PeopleCloudWidgetComponent,
FormCustomOutcomesComponent,
RadioButtonsCloudWidgetComponent,
FormDefinitionSelectorCloudComponent,
PropertiesViewerWrapperComponent,
PropertiesViewerWidgetComponent,
FormCloudComponent
] as const;
/** @deprecated use individual standalone components instead */
@NgModule({
imports: [
CommonModule,
OverlayModule,
MaterialModule,
FormsModule,
ReactiveFormsModule,
CoreModule,
ContentNodeSelectorModule,
PeopleCloudModule,
GroupCloudModule,
RichTextEditorModule,
...TOOLBAR_DIRECTIVES,
A11yModule,
FormatSpacePipe,
AlfrescoViewerComponent,
...CONTENT_UPLOAD_DIRECTIVES,
...CONTENT_METADATA_DIRECTIVES,
FormStylePipe
],
declarations: [
FormCloudComponent,
UploadCloudWidgetComponent,
FormDefinitionSelectorCloudComponent,
FormCustomOutcomesComponent,
RadioButtonsCloudWidgetComponent,
AttachFileCloudWidgetComponent,
PeopleCloudWidgetComponent,
GroupCloudWidgetComponent,
PropertiesViewerWrapperComponent,
PropertiesViewerWidgetComponent,
FilePropertiesTableCloudComponent,
FileViewerWidgetComponent,
DisplayRichTextWidgetComponent,
FormSpinnerComponent
],
exports: [
FormCloudComponent,
UploadCloudWidgetComponent,
FormDefinitionSelectorCloudComponent,
FormCustomOutcomesComponent,
RadioButtonsCloudWidgetComponent,
AttachFileCloudWidgetComponent,
PeopleCloudWidgetComponent,
GroupCloudWidgetComponent,
PropertiesViewerWidgetComponent,
FileViewerWidgetComponent,
DisplayRichTextWidgetComponent
],
providers: [FormCloudSpinnerService]
imports: [...FORM_CLOUD_DIRECTIVES],
exports: [...FORM_CLOUD_DIRECTIVES]
})
export class FormCloudModule {}
@@ -17,18 +17,20 @@
export * from './models/task-variable-cloud.model';
export * from './components/spinner/form-spinner.component';
export * from './components/form-cloud-custom-outcomes.component';
export * from './components/form-cloud.component';
export * from './components/form-definition-selector-cloud.component';
export * from './components/cloud-form-rendering.service';
export * from './components/widgets/attach-file/attach-file-cloud-widget.component';
export * from './components/widgets/attach-file/file-properties-table-cloud.component';
export * from './components/widgets/attach-file/upload-cloud.widget';
export * from './components/widgets/date/date-cloud.widget';
export * from './components/widgets/dropdown/dropdown-cloud.widget';
export * from './components/widgets/group/group-cloud.widget';
export * from './components/widgets/people/people-cloud.widget';
export * from './components/widgets/properties-viewer/properties-viewer.widget';
export * from './components/widgets/properties-viewer/properties-viewer-wrapper/properties-viewer-wrapper.component';
export * from './components/widgets/file-viewer/file-viewer.widget';
export * from './components/widgets/display-rich-text/display-rich-text.widget';
@@ -18,18 +18,17 @@
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 { FormService, FormSpinnerEvent, NoopTranslateModule } 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({
standalone: true,
selector: 'adf-cloud-overlay-test',
template: `<div>adf-cloud-overlay-test</div>`
})
@@ -48,17 +47,15 @@ describe('FormCloudSpinnerService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [FormSpinnerComponent, SpinnerTestComponent],
imports: [NoopTranslateModule, FormSpinnerComponent, SpinnerTestComponent, OverlayModule, PortalModule],
providers: [
FormCloudSpinnerService,
{
provide: FormService,
useValue: {
toggleFormSpinner: new Subject()
}
}
],
imports: [OverlayModule, PortalModule, MatProgressSpinnerModule, TranslateModule.forRoot()]
]
});
fixture = TestBed.createComponent(SpinnerTestComponent);
@@ -23,7 +23,7 @@ import { Observable } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FormSpinnerComponent } from '../../components/spinner/form-spinner.component';
@Injectable()
@Injectable({ providedIn: 'root' })
export class FormCloudSpinnerService {
private formService = inject(FormService);
private overlay = inject(Overlay);
@@ -18,9 +18,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of } from 'rxjs';
import { GroupCloudModule } from '../group-cloud.module';
import { GroupCloudComponent } from './group-cloud.component';
import { CoreTestingModule } from '@alfresco/adf-core';
import { DebugElement, SimpleChange } from '@angular/core';
import { IdentityGroupService } from '../services/identity-group.service';
import { mockFoodGroups, mockMeatChicken, mockVegetableAubergine } from '../mock/group-cloud.mock';
@@ -29,6 +27,7 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipGridHarness, MatChipHarness } from '@angular/material/chips/testing';
import { MatIconHarness } from '@angular/material/icon/testing';
import { MatInputHarness } from '@angular/material/input/testing';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
describe('GroupCloudComponent', () => {
let loader: HarnessLoader;
@@ -72,7 +71,7 @@ describe('GroupCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, GroupCloudModule]
imports: [ProcessServiceCloudTestingModule, GroupCloudComponent]
});
fixture = TestBed.createComponent(GroupCloudComponent);
component = fixture.componentInstance;
@@ -16,7 +16,6 @@
*/
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { GroupCloudModule } from '../group-cloud.module';
import { GroupCloudComponent } from './group-cloud.component';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { IdentityGroupService } from '../services/identity-group.service';
@@ -28,13 +27,10 @@ export default {
title: 'Process Services Cloud/Group Cloud/Group Cloud',
decorators: [
moduleMetadata({
imports: [GroupCloudModule]
imports: [GroupCloudComponent]
}),
applicationConfig({
providers: [
{ provide: IdentityGroupService, useClass: IdentityGroupServiceMock },
importProvidersFrom(ProcessServicesCloudStoryModule)
]
providers: [{ provide: IdentityGroupService, useClass: IdentityGroupServiceMock }, importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
@@ -102,7 +98,7 @@ export default {
description: 'FormControl to list of group.',
table: {
type: { summary: 'FormControl' },
defaultValue: { summary: 'new FormControl({ value: \'\', disabled: false })' },
defaultValue: { summary: `new FormControl({ value: '', disabled: false })` },
category: 'Form Controls'
}
},
@@ -111,7 +107,7 @@ export default {
description: 'FormControl to search the group.',
table: {
type: { summary: 'FormControl' },
defaultValue: { summary: 'new FormControl({ value: \'\', disabled: false })' },
defaultValue: { summary: `new FormControl({ value: '', disabled: false })` },
category: 'Form Controls'
}
},
@@ -29,7 +29,7 @@ import {
OnDestroy,
Inject
} from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { ReactiveFormsModule, 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';
@@ -37,9 +37,35 @@ 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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatSelectModule } from '@angular/material/select';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatChipsModule } from '@angular/material/chips';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { InitialGroupNamePipe } from '../pipe/group-initial.pipe';
@Component({
selector: 'adf-cloud-group',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatIconModule,
MatFormFieldModule,
MatProgressBarModule,
MatSelectModule,
MatAutocompleteModule,
MatChipsModule,
MatInputModule,
ReactiveFormsModule,
MatButtonModule,
InitialGroupNamePipe
],
templateUrl: './group-cloud.component.html',
styleUrls: ['./group-cloud.component.scss'],
animations: [
@@ -16,21 +16,11 @@
*/
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { CoreModule } from '@alfresco/adf-core';
import { MaterialModule } from '../material.module';
import { GroupCloudComponent } from './components/group-cloud.component';
import { InitialGroupNamePipe } from './pipe/group-initial.pipe';
import { IDENTITY_GROUP_SERVICE_TOKEN } from './services/identity-group-service.token';
import { IdentityGroupService } from './services/identity-group.service';
import { MatProgressBarModule } from '@angular/material/progress-bar';
/** @deprecated use GroupCloudComponent instead */
@NgModule({
imports: [CommonModule, MaterialModule, FormsModule, ReactiveFormsModule, CoreModule, MatProgressBarModule],
declarations: [GroupCloudComponent, InitialGroupNamePipe],
providers: [{ provide: IDENTITY_GROUP_SERVICE_TOKEN, useExisting: IdentityGroupService }],
exports: [GroupCloudComponent, InitialGroupNamePipe]
imports: [GroupCloudComponent],
exports: [GroupCloudComponent]
})
export class GroupCloudModule {}
@@ -19,10 +19,10 @@ import { Pipe, PipeTransform } from '@angular/core';
import { IdentityGroupModel } from '../models/identity-group.model';
@Pipe({
name: 'groupNameInitial'
name: 'groupNameInitial',
standalone: true
})
export class InitialGroupNamePipe implements PipeTransform {
transform(group: IdentityGroupModel): string {
let result = '';
if (group) {
@@ -32,7 +32,7 @@ export class InitialGroupNamePipe implements PipeTransform {
}
getInitialGroupName(groupName: string) {
groupName = (groupName ? groupName[0] : '');
groupName = groupName ? groupName[0] : '';
return groupName;
}
}
@@ -22,7 +22,6 @@ import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatNativeDateModule, MatRippleModule, MatOptionModule } from '@angular/material/core';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatExpansionModule } from '@angular/material/expansion';
@@ -38,8 +37,8 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
/** @deprecated this module should not be used */
@NgModule({
providers: [{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { floatLabel: 'never' } }],
imports: [
MatAutocompleteModule,
MatButtonModule,
@@ -19,7 +19,6 @@ import { PeopleCloudComponent } from './people-cloud.component';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreTestingModule } from '@alfresco/adf-core';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { PeopleCloudModule } from '../people-cloud.module';
import { DebugElement, SimpleChange } from '@angular/core';
import { By } from '@angular/platform-browser';
import { of } from 'rxjs';
@@ -83,13 +82,13 @@ describe('PeopleCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, ProcessServiceCloudTestingModule, PeopleCloudModule]
imports: [CoreTestingModule, ProcessServiceCloudTestingModule, PeopleCloudComponent]
});
fixture = TestBed.createComponent(PeopleCloudComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
identityUserService = TestBed.inject(IDENTITY_USER_SERVICE_TOKEN);
identityUserService = fixture.debugElement.injector.get(IDENTITY_USER_SERVICE_TOKEN);
loader = TestbedHarnessEnvironment.loader(fixture);
});
@@ -17,7 +17,6 @@
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { PeopleCloudComponent } from './people-cloud.component';
import { PeopleCloudModule } from '../people-cloud.module';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { IdentityUserService } from '../services/identity-user.service';
import { IdentityUserServiceMock, mockFoodUsers, mockKielbasaSausage, mockShepherdsPie, mockYorkshirePudding } from '../mock/people-cloud.mock';
@@ -28,13 +27,10 @@ export default {
title: 'Process Services Cloud/People Cloud/People Cloud',
decorators: [
moduleMetadata({
imports: [PeopleCloudModule]
imports: [PeopleCloudComponent]
}),
applicationConfig({
providers: [
{ provide: IdentityUserService, useClass: IdentityUserServiceMock },
importProvidersFrom(ProcessServicesCloudStoryModule)
]
providers: [{ provide: IdentityUserService, useClass: IdentityUserServiceMock }, importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
@@ -119,7 +115,7 @@ export default {
description: 'FormControl to list of users.',
table: {
type: { summary: 'FormControl' },
defaultValue: { summary: 'new FormControl({ value: \'\', disabled: false })' },
defaultValue: { summary: `new FormControl({ value: '', disabled: false })` },
category: 'Form Controls'
}
},
@@ -128,7 +124,7 @@ export default {
description: 'FormControl to search the user.',
table: {
type: { summary: 'FormControl' },
defaultValue: { summary: 'new FormControl({ value: \'\', disabled: false })' },
defaultValue: { summary: `new FormControl({ value: '', disabled: false })` },
category: 'Form Controls'
}
},
@@ -173,7 +169,7 @@ export default {
}
} as Meta<PeopleCloudComponent>;
const template: StoryFn<PeopleCloudComponent> = args => ({
const template: StoryFn<PeopleCloudComponent> = (args) => ({
props: args
});
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { UntypedFormControl } from '@angular/forms';
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
import {
Component,
OnInit,
@@ -33,16 +33,36 @@ import {
} from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { switchMap, debounceTime, distinctUntilChanged, mergeMap, tap, filter, takeUntil } from 'rxjs/operators';
import { FullNamePipe } from '@alfresco/adf-core';
import { FullNamePipe, InitialUsernamePipe } from '@alfresco/adf-core';
import { trigger, state, style, transition, animate } 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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { MatChipsModule } from '@angular/material/chips';
import { MatInputModule } from '@angular/material/input';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatProgressBarModule } from '@angular/material/progress-bar';
@Component({
selector: 'adf-cloud-people',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatIconModule,
MatChipsModule,
MatInputModule,
FullNamePipe,
ReactiveFormsModule,
MatAutocompleteModule,
InitialUsernamePipe,
MatProgressBarModule
],
templateUrl: './people-cloud.component.html',
styleUrls: ['./people-cloud.component.scss'],
animations: [
@@ -17,18 +17,10 @@
import { NgModule } from '@angular/core';
import { PeopleCloudComponent } from './components/people-cloud.component';
import { CommonModule } from '@angular/common';
import { MaterialModule } from '../material.module';
import { CoreModule, FullNamePipe, InitialUsernamePipe } from '@alfresco/adf-core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { IdentityUserService } from './services/identity-user.service';
import { IDENTITY_USER_SERVICE_TOKEN } from './services/identity-user-service.token';
import { MatProgressBarModule } from '@angular/material/progress-bar';
/** @deprecated Use `PeopleCloudComponent` instead */
@NgModule({
imports: [CommonModule, MaterialModule, FormsModule, ReactiveFormsModule, CoreModule, FullNamePipe, InitialUsernamePipe, MatProgressBarModule],
declarations: [PeopleCloudComponent],
exports: [PeopleCloudComponent],
providers: [{ provide: IDENTITY_USER_SERVICE_TOKEN, useExisting: IdentityUserService }]
imports: [PeopleCloudComponent],
exports: [PeopleCloudComponent]
})
export class PeopleCloudModule {}
@@ -17,7 +17,7 @@
import { TestBed } from '@angular/core/testing';
import { ProcessNameCloudPipe } from './process-name-cloud.pipe';
import { LocalizedDatePipe, CoreTestingModule } from '@alfresco/adf-core';
import { CoreTestingModule } from '@alfresco/adf-core';
import { ProcessInstanceCloud } from '../process/start-process/models/process-instance-cloud.model';
describe('ProcessNameCloudPipe', () => {
@@ -35,10 +35,9 @@ describe('ProcessNameCloudPipe', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule],
providers: [LocalizedDatePipe]
providers: [ProcessNameCloudPipe]
});
const localizedDatePipe = TestBed.inject(LocalizedDatePipe);
processNamePipe = new ProcessNameCloudPipe(localizedDatePipe);
processNamePipe = TestBed.inject(ProcessNameCloudPipe);
});
it('should not modify the name when there is no identifier', () => {
@@ -23,27 +23,26 @@ import { getTime } from 'date-fns';
export const DATE_TIME_IDENTIFIER_REG_EXP = new RegExp('%{datetime}', 'i');
export const PROCESS_DEFINITION_IDENTIFIER_REG_EXP = new RegExp('%{processdefinition}', 'i');
@Pipe({ name: 'processNameCloud' })
/**
* TODO: This pipe is not used in the HTML templates, only instantiated from code.
*/
@Pipe({
name: 'processNameCloud',
standalone: true
})
export class ProcessNameCloudPipe implements PipeTransform {
constructor(private localizedDatePipe: LocalizedDatePipe) {
}
constructor(private localizedDatePipe: LocalizedDatePipe) {}
transform(processNameFormat: string, processInstance?: ProcessInstanceCloud): string {
let processName = processNameFormat;
if (processName.match(DATE_TIME_IDENTIFIER_REG_EXP)) {
const presentDateTime = getTime(new Date());
processName = processName.replace(
DATE_TIME_IDENTIFIER_REG_EXP,
this.localizedDatePipe.transform(presentDateTime, 'medium')
);
processName = processName.replace(DATE_TIME_IDENTIFIER_REG_EXP, this.localizedDatePipe.transform(presentDateTime, 'medium'));
}
if (processName.match(PROCESS_DEFINITION_IDENTIFIER_REG_EXP)) {
const selectedProcessDefinitionName = processInstance ? processInstance.processDefinitionName : '';
processName = processName.replace(
PROCESS_DEFINITION_IDENTIFIER_REG_EXP,
selectedProcessDefinitionName
);
processName = processName.replace(PROCESS_DEFINITION_IDENTIFIER_REG_EXP, selectedProcessDefinitionName);
}
return processName;
}
@@ -1,30 +0,0 @@
/*!
* @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 { NgModule } from '@angular/core';
import { ProcessNameCloudPipe } from './process-name-cloud.pipe';
@NgModule({
declarations: [
ProcessNameCloudPipe
],
exports: [
ProcessNameCloudPipe
]
})
export class ProcessServicesCloudPipeModule {
}
@@ -17,53 +17,62 @@
import { NgModule, ModuleWithProviders } from '@angular/core';
import { CoreModule, FormRenderingService, provideTranslations } from '@alfresco/adf-core';
import { AppListCloudModule } from './app/app-list-cloud.module';
import { TaskCloudModule } from './task/task-cloud.module';
import { ProcessCloudModule } from './process/process-cloud.module';
import { GroupCloudModule } from './group/group-cloud.module';
import { FormCloudModule } from './form/form-cloud.module';
import { TaskFormModule } from './task/task-form/task-form.module';
import { APP_LIST_CLOUD_DIRECTIVES } from './app/app-list-cloud.module';
import { TASK_CLOUD_DIRECTIVES } from './task/task-cloud.module';
import { PROCESS_CLOUD_DIRECTIVES } from './process/process-cloud.module';
import { FORM_CLOUD_DIRECTIVES } from './form/form-cloud.module';
import {
LocalPreferenceCloudService,
PreferenceCloudServiceInterface,
PROCESS_FILTERS_SERVICE_TOKEN,
TASK_FILTERS_SERVICE_TOKEN,
PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN,
TASK_LIST_PREFERENCES_SERVICE_TOKEN
TASK_LIST_PREFERENCES_SERVICE_TOKEN,
TASK_LIST_CLOUD_TOKEN
} from './services/public-api';
import { PeopleCloudModule } from './people/people-cloud.module';
import { CloudFormRenderingService } from './form/components/cloud-form-rendering.service';
import { ProcessServicesCloudPipeModule } from './pipes/process-services-cloud-pipe.module';
import { ApolloModule } from 'apollo-angular';
import { RichTextEditorModule } from './rich-text-editor/rich-text-editor.module';
import { ProcessNameCloudPipe } from './pipes/process-name-cloud.pipe';
import { PeopleCloudComponent } from './people/components/people-cloud.component';
import { RichTextEditorComponent } from './rich-text-editor';
import { TaskFormCloudComponent } from './task/task-form/components/task-form-cloud.component';
import { GroupCloudComponent } from './group/components/group-cloud.component';
import { IDENTITY_GROUP_SERVICE_TOKEN } from './group/services/identity-group-service.token';
import { IdentityGroupService } from './group/services/identity-group.service';
import { IDENTITY_USER_SERVICE_TOKEN } from './people/services/identity-user-service.token';
import { IdentityUserService } from './people/services/identity-user.service';
import { TaskListCloudService } from './task/task-list/services/task-list-cloud.service';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
@NgModule({
imports: [
CoreModule,
AppListCloudModule,
ProcessCloudModule,
TaskCloudModule,
GroupCloudModule,
PeopleCloudModule,
FormCloudModule,
TaskFormModule,
ProcessServicesCloudPipeModule,
...APP_LIST_CLOUD_DIRECTIVES,
...PROCESS_CLOUD_DIRECTIVES,
...TASK_CLOUD_DIRECTIVES,
GroupCloudComponent,
PeopleCloudComponent,
...FORM_CLOUD_DIRECTIVES,
TaskFormCloudComponent,
ProcessNameCloudPipe,
ApolloModule,
RichTextEditorModule
RichTextEditorComponent
],
providers: [
provideTranslations('adf-process-services-cloud', 'assets/adf-process-services-cloud')
provideTranslations('adf-process-services-cloud', 'assets/adf-process-services-cloud'),
ProcessNameCloudPipe,
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { floatLabel: 'never' } }
],
exports: [
AppListCloudModule,
ProcessCloudModule,
TaskCloudModule,
GroupCloudModule,
FormCloudModule,
TaskFormModule,
PeopleCloudModule,
ProcessServicesCloudPipeModule,
RichTextEditorModule
...APP_LIST_CLOUD_DIRECTIVES,
...PROCESS_CLOUD_DIRECTIVES,
...TASK_CLOUD_DIRECTIVES,
GroupCloudComponent,
...FORM_CLOUD_DIRECTIVES,
TaskFormCloudComponent,
PeopleCloudComponent,
ProcessNameCloudPipe,
RichTextEditorComponent
]
})
export class ProcessServicesCloudModule {
@@ -79,6 +88,9 @@ export class ProcessServicesCloudModule {
{ provide: TASK_FILTERS_SERVICE_TOKEN, useExisting: filterPreferenceServiceInstance ?? LocalPreferenceCloudService },
{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useExisting: listPreferenceServiceInstance ?? LocalPreferenceCloudService },
{ provide: TASK_LIST_PREFERENCES_SERVICE_TOKEN, useExisting: listPreferenceServiceInstance ?? LocalPreferenceCloudService },
{ provide: IDENTITY_GROUP_SERVICE_TOKEN, useExisting: IdentityGroupService },
{ provide: IDENTITY_USER_SERVICE_TOKEN, useExisting: IdentityUserService },
{ provide: TASK_LIST_CLOUD_TOKEN, useClass: TaskListCloudService },
FormRenderingService,
{ provide: FormRenderingService, useClass: CloudFormRenderingService }
]
@@ -23,11 +23,11 @@ import { ProcessInstanceCloud } from '../start-process/models/process-instance-c
import { IdentityUserService } from '../../people/services/identity-user.service';
@Directive({
standalone: true,
// eslint-disable-next-line @angular-eslint/directive-selector
selector: '[adf-cloud-cancel-process]'
})
export class CancelProcessDirective implements OnInit, OnDestroy {
/** Emitted when the process is cancelled. */
@Output()
success = new EventEmitter<any>();
@@ -42,19 +42,14 @@ export class CancelProcessDirective implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
constructor(
private elementRef: ElementRef,
private processCloudService: ProcessCloudService,
private identityUserService: IdentityUserService) {}
constructor(private elementRef: ElementRef, private processCloudService: ProcessCloudService, private identityUserService: IdentityUserService) {}
ngOnInit() {
this.processCloudService.dataChangesDetected
.pipe(takeUntil(this.onDestroy$))
.subscribe((processDetails) => {
this.processInstanceDetails = processDetails;
this.canCancelProcess = this.checkCanCancelProcess();
this.setElementVisibility();
});
this.processCloudService.dataChangesDetected.pipe(takeUntil(this.onDestroy$)).subscribe((processDetails) => {
this.processInstanceDetails = processDetails;
this.canCancelProcess = this.checkCanCancelProcess();
this.setElementVisibility();
});
}
@HostListener('click')
@@ -73,11 +68,10 @@ export class CancelProcessDirective implements OnInit, OnDestroy {
cancelProcess() {
if (this.canCancelProcess) {
this.processCloudService.cancelProcess(this.processInstanceDetails.appName, this.processInstanceDetails.id)
.subscribe(
(response) => this.success.emit(response),
(error) => this.error.emit(error)
);
this.processCloudService.cancelProcess(this.processInstanceDetails.appName, this.processInstanceDetails.id).subscribe(
(response) => this.success.emit(response),
(error) => this.error.emit(error)
);
} else {
this.error.emit('Permission denied, only process initiator can cancel the process');
}
@@ -18,12 +18,9 @@
import { NgModule } from '@angular/core';
import { CancelProcessDirective } from './cancel-process.directive';
/** @deprecated use CancelProcessDirective instead */
@NgModule({
declarations: [
CancelProcessDirective
],
exports: [
CancelProcessDirective
]
imports: [CancelProcessDirective],
exports: [CancelProcessDirective]
})
export class ProcessDirectiveModule { }
export class ProcessDirectiveModule {}
@@ -16,24 +16,23 @@
*/
import { NgModule } from '@angular/core';
import { ProcessFiltersCloudModule } from './process-filters/process-filters-cloud.module';
import { ProcessListCloudModule } from './process-list/process-list-cloud.module';
import { StartProcessCloudModule } from './start-process/start-process-cloud.module';
import { CoreModule, LocalizedDatePipe } from '@alfresco/adf-core';
import { ProcessHeaderCloudModule } from './process-header/process-header-cloud.module';
import { ProcessDirectiveModule } from './directives/process-directive.module';
import { ProcessNameCloudPipe } from '../pipes/process-name-cloud.pipe';
import { PROCESS_FILTERS_CLOUD_DIRECTIVES } from './process-filters/process-filters-cloud.module';
import { ProcessListCloudComponent } from './process-list/components/process-list-cloud.component';
import { CancelProcessDirective } from './directives/cancel-process.directive';
import { StartProcessCloudComponent } from './start-process/components/start-process-cloud.component';
import { ProcessHeaderCloudComponent } from './process-header/components/process-header-cloud.component';
export const PROCESS_CLOUD_DIRECTIVES = [
...PROCESS_FILTERS_CLOUD_DIRECTIVES,
ProcessListCloudComponent,
StartProcessCloudComponent,
ProcessHeaderCloudComponent,
CancelProcessDirective
] as const;
/** @deprecated import individual standalone components instead */
@NgModule({
imports: [
CoreModule,
ProcessFiltersCloudModule,
ProcessListCloudModule,
StartProcessCloudModule,
ProcessHeaderCloudModule,
ProcessDirectiveModule
],
exports: [ProcessFiltersCloudModule, ProcessListCloudModule, StartProcessCloudModule, ProcessHeaderCloudModule, ProcessDirectiveModule],
providers: [ProcessNameCloudPipe, LocalizedDatePipe]
imports: [...PROCESS_CLOUD_DIRECTIVES],
exports: [...PROCESS_CLOUD_DIRECTIVES]
})
export class ProcessCloudModule {}
@@ -16,42 +16,31 @@
*/
import { AlfrescoApiService } from '@alfresco/adf-content-services';
import { ADF_DATE_FORMATS, FullNamePipe, NoopTranslateModule, UserPreferencesService } from '@alfresco/adf-core';
import { ADF_DATE_FORMATS, UserPreferencesService } from '@alfresco/adf-core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { SimpleChange } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { DateFnsAdapter } from '@angular/material-date-fns-adapter';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatChipsModule } from '@angular/material/chips';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { MatDialog } from '@angular/material/dialog';
import { MatExpansionPanelHarness } from '@angular/material/expansion/testing';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconTestingModule } from '@angular/material/icon/testing';
import { MatInputModule } from '@angular/material/input';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
import { MatSelectModule } from '@angular/material/select';
import { MatSelectHarness } from '@angular/material/select/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { endOfDay, format, isValid, startOfDay, subYears } from 'date-fns';
import { enUS } from 'date-fns/locale';
import { of } from 'rxjs';
import { ProcessFilterDialogCloudComponent } from './process-filter-dialog-cloud.component';
import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service';
import { DateRangeFilterComponent } from '../../../common/date-range-filter/date-range-filter.component';
import { fakeEnvironmentList } from '../../../common/mock/environment.mock';
import { DateCloudFilterType } from '../../../models/date-cloud-filter.model';
import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model';
import { PeopleCloudComponent } from '../../../people/components/people-cloud.component';
import { IdentityUserServiceMock } from '../../../people/mock/people-cloud.mock';
import { IDENTITY_USER_SERVICE_TOKEN } from '../../../people/services/identity-user-service.token';
import { PROCESS_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
import { NotificationCloudService } from '../../../services/notification-cloud.service';
import { ProcessCloudService } from '../../services/process-cloud.service';
import { DateCloudFilterType } from '../../../models/date-cloud-filter.model';
import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model';
import { mockAppVersions } from '../mock/process-filters-cloud.mock';
import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model';
import { ProcessFilterCloudService } from '../services/process-filter-cloud.service';
@@ -61,7 +50,7 @@ import {
PROCESS_FILTER_ACTION_RESTORE,
PROCESS_FILTER_ACTION_SAVE_DEFAULT
} from './edit-process-filter-cloud.component';
import { ProcessFilterDialogCloudComponent } from './process-filter-dialog-cloud.component';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
describe('EditProcessFilterCloudComponent', () => {
let loader: HarnessLoader;
@@ -101,29 +90,18 @@ describe('EditProcessFilterCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
MatIconTestingModule,
MatDialogModule,
NoopTranslateModule,
NoopAnimationsModule,
MatSelectModule,
MatDatepickerModule,
MatAutocompleteModule,
FullNamePipe,
MatFormFieldModule,
MatInputModule,
ReactiveFormsModule,
MatChipsModule,
MatProgressBarModule
ProcessServiceCloudTestingModule,
EditProcessFilterCloudComponent
],
providers: [
MatDialog,
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService },
{ provide: MAT_DATE_LOCALE, useValue: enUS },
{ provide: DateAdapter, useClass: DateFnsAdapter },
{ provide: NotificationCloudService, useValue: { makeGQLQuery: () => of([]) } },
{ provide: MAT_DATE_FORMATS, useValue: ADF_DATE_FORMATS },
{ provide: IDENTITY_USER_SERVICE_TOKEN, useExisting: IdentityUserServiceMock }
],
declarations: [PeopleCloudComponent, DateRangeFilterComponent]
]
});
fixture = TestBed.createComponent(EditProcessFilterCloudComponent);
component = fixture.componentInstance;
@@ -16,8 +16,8 @@
*/
import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges, OnDestroy, ViewEncapsulation } from '@angular/core';
import { FormBuilder, AbstractControl, FormGroup, FormControl } from '@angular/forms';
import { DateAdapter } from '@angular/material/core';
import { FormBuilder, AbstractControl, FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
import { DateAdapter, MatOptionModule } 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';
@@ -29,7 +29,7 @@ import {
ProcessFilterOptions,
ProcessSortFilterProperty
} from '../models/process-filter-cloud.model';
import { DateFnsUtils, TranslationService, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
import { DateFnsUtils, IconComponent, TranslationService, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
import { ProcessFilterCloudService } from '../services/process-filter-cloud.service';
import { ProcessFilterDialogCloudComponent } from './process-filter-dialog-cloud.component';
import { ProcessCloudService } from '../../services/process-cloud.service';
@@ -37,6 +37,18 @@ 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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { PeopleCloudComponent } from '../../../people/components/people-cloud.component';
import { DateRangeFilterComponent } from '../../../common/date-range-filter/date-range-filter.component';
import { MatIconModule } from '@angular/material/icon';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatButtonModule } from '@angular/material/button';
import { MatExpansionModule } from '@angular/material/expansion';
export const PROCESS_FILTER_ACTION_SAVE = 'save';
export const PROCESS_FILTER_ACTION_SAVE_AS = 'saveAs';
@@ -67,6 +79,24 @@ interface ProcessFilterFormProps {
@Component({
selector: 'adf-cloud-edit-process-filter',
standalone: true,
imports: [
CommonModule,
TranslateModule,
PeopleCloudComponent,
DateRangeFilterComponent,
MatIconModule,
MatDatepickerModule,
MatFormFieldModule,
ReactiveFormsModule,
MatInputModule,
MatOptionModule,
MatSelectModule,
MatProgressSpinnerModule,
IconComponent,
MatButtonModule,
MatExpansionModule
],
templateUrl: './edit-process-filter-cloud.component.html',
styleUrls: ['./edit-process-filter-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -19,7 +19,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ProcessFilterDialogCloudComponent } from './process-filter-dialog-cloud.component';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { ProcessFiltersCloudModule } from '../process-filters-cloud.module';
describe('ProcessFilterDialogCloudComponent', () => {
let component: ProcessFilterDialogCloudComponent;
@@ -36,7 +35,7 @@ describe('ProcessFilterDialogCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, ProcessFiltersCloudModule],
imports: [ProcessServiceCloudTestingModule, ProcessFilterDialogCloudComponent],
providers: [
{ provide: MatDialogRef, useValue: mockDialogRef },
{ provide: MAT_DIALOG_DATA, useValue: mockDialogData }
@@ -16,11 +16,28 @@
*/
import { ChangeDetectionStrategy, Component, inject, ViewEncapsulation } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
@Component({
selector: 'adf-cloud-process-filter-dialog-cloud',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatButtonModule,
MatCardModule,
MatFormFieldModule,
ReactiveFormsModule,
MatInputModule,
MatDialogModule
],
templateUrl: './process-filter-dialog-cloud.component.html',
styleUrls: ['./process-filter-dialog-cloud.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -21,15 +21,14 @@ import { of, throwError } from 'rxjs';
import { ProcessFilterCloudService } from '../services/process-filter-cloud.service';
import { ProcessFiltersCloudComponent } from './process-filters-cloud.component';
import { By } from '@angular/platform-browser';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { PROCESS_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
import { mockProcessFilters } from '../mock/process-filters-cloud.mock';
import { AppConfigService, AppConfigServiceMock, NoopTranslateModule } from '@alfresco/adf-core';
import { AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core';
import { ProcessListCloudService } from '../../../process/process-list/services/process-list-cloud.service';
import { NotificationCloudService } from '../../../services/notification-cloud.service';
import { ApolloModule } from 'apollo-angular';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatListModule } from '@angular/material/list';
const ProcessFilterCloudServiceMock = {
getProcessFilters: () => of(mockProcessFilters),
@@ -45,7 +44,7 @@ describe('ProcessFiltersCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopTranslateModule, NoopAnimationsModule, MatListModule],
imports: [ProcessServiceCloudTestingModule, ProcessFiltersCloudComponent],
providers: [
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService },
{ provide: AppConfigService, useClass: AppConfigServiceMock },
@@ -19,13 +19,19 @@ import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDes
import { Observable, Subject } 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 { IconComponent, TranslationService, AppConfigService } from '@alfresco/adf-core';
import { FilterParamsModel } from '../../../task/task-filters/models/filter-cloud.model';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatListModule } from '@angular/material/list';
import { debounceTime, takeUntil, tap } from 'rxjs/operators';
import { ProcessListCloudService } from '../../../process/process-list/services/process-list-cloud.service';
@Component({
selector: 'adf-cloud-process-filters',
standalone: true,
imports: [CommonModule, TranslateModule, MatProgressSpinnerModule, IconComponent, MatListModule],
templateUrl: './process-filters-cloud.component.html',
styleUrls: ['./process-filters-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -16,31 +16,19 @@
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ProcessFiltersCloudComponent } from './components/process-filters-cloud.component';
import { MaterialModule } from '../../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { HttpClientModule } from '@angular/common/http';
import { EditProcessFilterCloudComponent } from './components/edit-process-filter-cloud.component';
import { ProcessFilterDialogCloudComponent } from './components/process-filter-dialog-cloud.component';
import { AppListCloudModule } from './../../app/app-list-cloud.module';
import { ProcessCommonModule } from '../../common/process-common.module';
import { PeopleCloudModule } from '../../people/people-cloud.module';
export const PROCESS_FILTERS_CLOUD_DIRECTIVES = [
ProcessFiltersCloudComponent,
EditProcessFilterCloudComponent,
ProcessFilterDialogCloudComponent
] as const;
/** @deprecated import individual standalone components instead */
@NgModule({
imports: [
FormsModule,
ReactiveFormsModule,
HttpClientModule,
CommonModule,
MaterialModule,
AppListCloudModule,
CoreModule,
ProcessCommonModule,
PeopleCloudModule
],
declarations: [ProcessFiltersCloudComponent, EditProcessFilterCloudComponent, ProcessFilterDialogCloudComponent],
exports: [ProcessFiltersCloudComponent, EditProcessFilterCloudComponent, ProcessFilterDialogCloudComponent]
imports: [...PROCESS_FILTERS_CLOUD_DIRECTIVES],
exports: [...PROCESS_FILTERS_CLOUD_DIRECTIVES]
})
export class ProcessFiltersCloudModule { }
export class ProcessFiltersCloudModule {}
@@ -21,7 +21,6 @@ import { By } from '@angular/platform-browser';
import { of } from 'rxjs';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { ProcessHeaderCloudComponent } from './process-header-cloud.component';
import { ProcessHeaderCloudModule } from '../process-header-cloud.module';
import { ProcessCloudService } from '../../services/process-cloud.service';
import { processInstanceDetailsCloudMock } from '../../mock/process-instance-details-cloud.mock';
@@ -33,7 +32,7 @@ describe('ProcessHeaderCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, ProcessHeaderCloudModule]
imports: [ProcessServiceCloudTestingModule, ProcessHeaderCloudComponent]
});
fixture = TestBed.createComponent(ProcessHeaderCloudComponent);
component = fixture.componentInstance;
@@ -16,7 +16,6 @@
*/
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessHeaderCloudModule } from '../process-header-cloud.module';
import { ProcessServicesCloudStoryModule } from '../../../testing/process-services-cloud-story.module';
import { ProcessHeaderCloudComponent } from './process-header-cloud.component';
import { ProcessCloudServiceMock } from '../../mock/process-cloud.service.mock';
@@ -28,7 +27,7 @@ export default {
title: 'Process Services Cloud/Process Cloud/Process Header Cloud/Process Header Cloud',
decorators: [
moduleMetadata({
imports: [ProcessHeaderCloudModule]
imports: [ProcessHeaderCloudComponent]
}),
applicationConfig({
providers: [{ provide: ProcessCloudService, useClass: ProcessCloudServiceMock }, importProvidersFrom(ProcessServicesCloudStoryModule)]
@@ -22,15 +22,21 @@ import {
TranslationService,
AppConfigService,
CardViewDateItemModel,
CardViewBaseItemModel
CardViewBaseItemModel,
CardViewComponent
} 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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatCardModule } from '@angular/material/card';
@Component({
selector: 'adf-cloud-process-header',
standalone: true,
imports: [CommonModule, TranslateModule, CardViewComponent, MatCardModule],
templateUrl: './process-header-cloud.component.html',
encapsulation: ViewEncapsulation.None,
styleUrls: ['./process-header-cloud.component.scss'],
@@ -1,30 +0,0 @@
/*!
* @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 { ProcessHeaderCloudModule } from './process-header-cloud.module';
describe('ProcessHeaderCloudModule', () => {
let processHeaderCloudModule: ProcessHeaderCloudModule;
beforeEach(() => {
processHeaderCloudModule = new ProcessHeaderCloudModule();
});
it('should create an instance', () => {
expect(processHeaderCloudModule).toBeTruthy();
});
});
@@ -16,19 +16,11 @@
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MaterialModule } from '../../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { ProcessHeaderCloudComponent } from './components/process-header-cloud.component';
/** @deprecated use ProcessHeaderCloudComponent instead */
@NgModule({
imports: [
CommonModule,
MaterialModule,
CoreModule
],
declarations: [ProcessHeaderCloudComponent],
imports: [ProcessHeaderCloudComponent],
exports: [ProcessHeaderCloudComponent]
})
export class ProcessHeaderCloudModule { }
export class ProcessHeaderCloudModule {}
@@ -82,8 +82,9 @@ describe('ProcessListCloudComponent', () => {
});
appConfig = TestBed.inject(AppConfigService);
processListCloudService = TestBed.inject(ProcessListCloudService);
preferencesService = TestBed.inject<PreferenceCloudServiceInterface>(PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN);
fixture = TestBed.createComponent(ProcessListCloudComponent);
preferencesService = fixture.debugElement.injector.get<PreferenceCloudServiceInterface>(PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN);
component = fixture.componentInstance;
appConfig.config = Object.assign(appConfig.config, {
'adf-cloud-process-list': {
@@ -614,6 +615,8 @@ describe('ProcessListCloudComponent: Injecting custom columns for task list - Cu
describe('ProcessListCloudComponent: Creating an empty custom template - EmptyTemplateComponent', () => {
@Component({
standalone: true,
imports: [ProcessListCloudComponent, CustomEmptyContentTemplateDirective],
template: `
<adf-cloud-process-list #processListCloud>
<adf-custom-empty-content-template>
@@ -635,9 +638,14 @@ describe('ProcessListCloudComponent: Creating an empty custom template - EmptyTe
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, MatProgressSpinnerModule, CustomEmptyContentTemplateDirective],
providers: [{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useValue: preferencesService }],
declarations: [EmptyTemplateComponent, ProcessListCloudComponent]
imports: [
ProcessServiceCloudTestingModule,
MatProgressSpinnerModule,
CustomEmptyContentTemplateDirective,
ProcessListCloudComponent,
EmptyTemplateComponent
],
providers: [{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useValue: preferencesService }]
});
fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent);
fixtureEmpty.detectChanges();
@@ -42,7 +42,12 @@ import {
DataCellEvent,
DataRowActionEvent,
DataTableComponent,
DataColumn
DataColumn,
EmptyContentComponent,
NoContentTemplateDirective,
LoadingContentTemplateDirective,
MainMenuDataTableTemplateDirective,
ColumnsSelectorComponent
} from '@alfresco/adf-core';
import { ProcessListCloudService } from '../services/process-list-cloud.service';
import { BehaviorSubject, Subject, of } from 'rxjs';
@@ -56,11 +61,26 @@ 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 { VariableMapperService } from '../../../services/variable-mapper.sevice';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
const PRESET_KEY = 'adf-cloud-process-list.presets';
/* eslint-disable @typescript-eslint/brace-style */
@Component({
selector: 'adf-cloud-process-list',
standalone: true,
imports: [
CommonModule,
TranslateModule,
EmptyContentComponent,
NoContentTemplateDirective,
MatProgressSpinnerModule,
LoadingContentTemplateDirective,
MainMenuDataTableTemplateDirective,
ColumnsSelectorComponent,
DataTableComponent
],
templateUrl: './process-list-cloud.component.html',
styleUrls: ['./process-list-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -68,7 +88,6 @@ const PRESET_KEY = 'adf-cloud-process-list.presets';
export class ProcessListCloudComponent
extends DataTableSchema<ProcessListDataColumnCustomData>
implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy
// eslint-disable-next-line @typescript-eslint/brace-style
{
@ViewChild(DataTableComponent)
dataTable: DataTableComponent;
@@ -16,25 +16,11 @@
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProcessListCloudComponent } from './components/process-list-cloud.component';
import { MaterialModule } from '../../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { LocalPreferenceCloudService } from '../../services/local-preference-cloud.service';
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../services/cloud-token.service';
/** @deprecated use ProcessListCloudComponent instead */
@NgModule({
imports: [
CommonModule,
MaterialModule,
CoreModule
],
providers: [{
provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN,
useClass: LocalPreferenceCloudService
}],
declarations: [ProcessListCloudComponent],
imports: [ProcessListCloudComponent],
exports: [ProcessListCloudComponent]
})
export class ProcessListCloudModule { }
export class ProcessListCloudModule {}
@@ -48,7 +48,7 @@ export class ProcessCloudService extends BaseCloudService implements ProcessClou
})
);
} else {
return throwError('AppName/ProcessInstanceId not configured');
return throwError(() => new Error('AppName/ProcessInstanceId not configured'));
}
}
@@ -64,7 +64,7 @@ export class ProcessCloudService extends BaseCloudService implements ProcessClou
return this.get(url).pipe(map((res: any) => res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry))));
} else {
return throwError('AppName not configured');
return throwError(() => new Error('AppName not configured'));
}
}
@@ -80,7 +80,7 @@ export class ProcessCloudService extends BaseCloudService implements ProcessClou
return this.get(url).pipe(map((appEntities: ApplicationVersionResponseModel) => appEntities.list.entries));
} else {
return throwError('AppName not configured');
return throwError(() => new Error('AppName not configured'));
}
}
@@ -101,7 +101,7 @@ export class ProcessCloudService extends BaseCloudService implements ProcessClou
})
);
} else {
return throwError('App name and process id not configured');
return throwError(() => new Error('App name and process id not configured'));
}
}
}
@@ -22,14 +22,6 @@ import { of, throwError } from 'rxjs';
import { StartProcessCloudService } from '../services/start-process-cloud.service';
import { FormCloudService } from '../../../form/services/form-cloud.service';
import { StartProcessCloudComponent } from './start-process-cloud.component';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatRippleModule, MatCommonModule, MatOptionModule } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import {
fakeProcessDefinitions,
fakeStartForm,
@@ -49,13 +41,13 @@ import { ProcessServiceCloudTestingModule } from '../../../testing/process-servi
import { ProcessNameCloudPipe } from '../../../pipes/process-name-cloud.pipe';
import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
import { ESCAPE } from '@angular/cdk/keycodes';
import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model';
import { TaskVariableCloud } from '../../../form/models/task-variable-cloud.model';
import { first } from 'rxjs/operators';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
import { TaskVariableCloud } from '../../../form/models/task-variable-cloud.model';
import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model';
describe('StartProcessCloudComponent', () => {
let loader: HarnessLoader;
@@ -88,20 +80,7 @@ describe('StartProcessCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
ProcessServiceCloudTestingModule,
FormsModule,
MatCommonModule,
ReactiveFormsModule,
MatCardModule,
MatIconModule,
MatAutocompleteModule,
MatOptionModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatRippleModule
]
imports: [ProcessServiceCloudTestingModule, StartProcessCloudComponent]
});
processService = TestBed.inject(StartProcessCloudService);
formCloudService = TestBed.inject(FormCloudService);
@@ -30,9 +30,16 @@ import {
ViewEncapsulation
} from '@angular/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 {
ContentLinkModel,
FORM_FIELD_VALIDATORS,
FormFieldValidator,
FormModel,
InplaceFormInputComponent,
TranslationService
} from '@alfresco/adf-core';
import { AbstractControl, FormControl, FormGroup, FormsModule, ReactiveFormsModule, ValidatorFn, Validators } from '@angular/forms';
import { MatAutocompleteModule, MatAutocompleteTrigger } from '@angular/material/autocomplete';
import { catchError, debounceTime, takeUntil } from 'rxjs/operators';
import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
import { ProcessPayloadCloud } from '../models/process-payload-cloud.model';
@@ -42,12 +49,39 @@ import { forkJoin, of, Subject } 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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
import { FormCustomOutcomesComponent } from '../../../form/components/form-cloud-custom-outcomes.component';
import { FormCloudComponent } from '../../../form/components/form-cloud.component';
import { MatIconModule } from '@angular/material/icon';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
const MAX_NAME_LENGTH: number = 255;
const PROCESS_DEFINITION_DEBOUNCE: number = 300;
@Component({
selector: 'adf-cloud-start-process',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatProgressSpinnerModule,
MatCardModule,
MatButtonModule,
FormCustomOutcomesComponent,
FormCloudComponent,
InplaceFormInputComponent,
MatIconModule,
MatFormFieldModule,
MatAutocompleteModule,
MatInputModule,
FormsModule,
ReactiveFormsModule
],
templateUrl: './start-process-cloud.component.html',
styleUrls: ['./start-process-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -16,26 +16,11 @@
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MaterialModule } from '../../material.module';
import { FormCloudModule } from '../../form/form-cloud.module';
import { StartProcessCloudComponent } from './components/start-process-cloud.component';
import { CoreModule } from '@alfresco/adf-core';
/** @deprecated use StartProcessCloudComponent instead */
@NgModule({
imports: [
FormsModule,
CommonModule,
FormCloudModule,
MaterialModule,
ReactiveFormsModule,
CoreModule
],
declarations: [
StartProcessCloudComponent
],
exports: [
StartProcessCloudComponent
]
imports: [StartProcessCloudComponent],
exports: [StartProcessCloudComponent]
})
export class StartProcessCloudModule { }
export class StartProcessCloudModule {}
@@ -51,10 +51,10 @@ describe('RichTextEditorComponent', () => {
await fixture.whenStable();
};
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [RichTextEditorComponent]
}).compileComponents();
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RichTextEditorComponent]
});
fixture = TestBed.createComponent(RichTextEditorComponent);
component = fixture.componentInstance;
@@ -15,7 +15,6 @@
* limitations under the License.
*/
import { RichTextEditorModule } from './rich-text-editor.module';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessServicesCloudStoryModule } from '../testing/process-services-cloud-story.module';
import { RichTextEditorComponent } from './rich-text-editor.component';
@@ -26,7 +25,7 @@ export default {
title: 'Process Services Cloud/Rich Text Editor',
decorators: [
moduleMetadata({
imports: [RichTextEditorModule]
imports: [RichTextEditorComponent]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
@@ -20,9 +20,12 @@ import { AfterViewInit, Component, Input, OnDestroy, OnInit, ViewEncapsulation }
import EditorJS, { OutputData } from '@editorjs/editorjs';
import { Subject } from 'rxjs';
import { editorJsConfig } from './editorjs-config';
import { CommonModule } from '@angular/common';
@Component({
selector: 'adf-cloud-rich-text-editor',
standalone: true,
imports: [CommonModule],
templateUrl: './rich-text-editor.component.html',
styleUrls: ['./rich-text-editor.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -16,15 +16,11 @@
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RichTextEditorComponent } from './rich-text-editor.component';
/** @deprecated use RichTextEditorComponent instead */
@NgModule({
declarations: [RichTextEditorComponent],
imports: [
CommonModule
],
imports: [RichTextEditorComponent],
exports: [RichTextEditorComponent]
})
export class RichTextEditorModule { }
export class RichTextEditorModule {}
@@ -20,11 +20,11 @@ import { IdentityUserService } from '../../people/services/identity-user.service
import { TaskCloudService } from '../services/task-cloud.service';
@Directive({
standalone: true,
// eslint-disable-next-line @angular-eslint/directive-selector
selector: '[adf-cloud-claim-task]'
})
export class ClaimTaskCloudDirective implements OnInit {
/** (Required) The id of the task. */
@Input()
taskId: string;
@@ -47,14 +47,14 @@ export class ClaimTaskCloudDirective implements OnInit {
private readonly el: ElementRef,
private readonly renderer: Renderer2,
private taskListService: TaskCloudService,
private identityUserService: IdentityUserService) { }
private identityUserService: IdentityUserService
) {}
ngOnInit() {
this.validateInputs();
}
validateInputs() {
if (!this.isTaskValid()) {
this.invalidParams.push('taskId');
}
@@ -81,7 +81,6 @@ export class ClaimTaskCloudDirective implements OnInit {
} catch (error) {
this.error.emit(error);
}
}
private async claimTask() {
@@ -19,11 +19,11 @@ import { Directive, Input, HostListener, Output, EventEmitter, OnInit, ElementRe
import { TaskCloudService } from '../services/task-cloud.service';
@Directive({
standalone: true,
// eslint-disable-next-line @angular-eslint/directive-selector
selector: '[adf-cloud-complete-task]'
})
export class CompleteTaskDirective implements OnInit {
/** (Required) The id of the task. */
@Input()
taskId: string;
@@ -42,18 +42,13 @@ export class CompleteTaskDirective implements OnInit {
invalidParams: string[] = [];
constructor(
private readonly el: ElementRef,
private readonly renderer: Renderer2,
private readonly taskListService: TaskCloudService
) { }
constructor(private readonly el: ElementRef, private readonly renderer: Renderer2, private readonly taskListService: TaskCloudService) {}
ngOnInit() {
this.validateInputs();
}
validateInputs() {
if (!this.isTaskValid()) {
this.invalidParams.push('taskId');
}
@@ -85,6 +80,5 @@ export class CompleteTaskDirective implements OnInit {
this.renderer.removeAttribute(this.el.nativeElement, 'disabled');
this.error.emit(error);
}
}
}
@@ -20,16 +20,9 @@ import { CompleteTaskDirective } from './complete-task.directive';
import { ClaimTaskCloudDirective } from './claim-task-cloud.directive';
import { UnClaimTaskCloudDirective } from './unclaim-task-cloud.directive';
/** @deprecated import standalone directives from the individual files */
@NgModule({
declarations: [
CompleteTaskDirective,
ClaimTaskCloudDirective,
UnClaimTaskCloudDirective
],
exports: [
CompleteTaskDirective,
ClaimTaskCloudDirective,
UnClaimTaskCloudDirective
]
imports: [CompleteTaskDirective, ClaimTaskCloudDirective, UnClaimTaskCloudDirective],
exports: [CompleteTaskDirective, ClaimTaskCloudDirective, UnClaimTaskCloudDirective]
})
export class TaskDirectiveModule { }
export class TaskDirectiveModule {}
@@ -19,11 +19,11 @@ import { Directive, Input, HostListener, Output, EventEmitter, OnInit, ElementRe
import { TaskCloudService } from '../services/task-cloud.service';
@Directive({
standalone: true,
// eslint-disable-next-line @angular-eslint/directive-selector
selector: '[adf-cloud-unclaim-task]'
})
export class UnClaimTaskCloudDirective implements OnInit {
/** (Required) The id of the task. */
@Input()
taskId: string;
@@ -42,17 +42,13 @@ export class UnClaimTaskCloudDirective implements OnInit {
invalidParams: string[] = [];
constructor(
private readonly el: ElementRef,
private readonly renderer: Renderer2,
private taskListService: TaskCloudService) { }
constructor(private readonly el: ElementRef, private readonly renderer: Renderer2, private taskListService: TaskCloudService) {}
ngOnInit() {
this.validateInputs();
}
validateInputs() {
if (!this.isTaskValid()) {
this.invalidParams.push('taskId');
}
@@ -20,7 +20,6 @@ import { AlfrescoApiService } from '@alfresco/adf-content-services';
import { StartTaskCloudComponent } from './start-task-cloud.component';
import { of, throwError } from 'rxjs';
import { taskDetailsMock } from '../mock/task-details.mock';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ProcessServiceCloudTestingModule } from './../../../testing/process-service-cloud.testing.module';
import { FormDefinitionSelectorCloudService } from '../../../form/services/form-definition-selector-cloud.service';
import { TaskCloudService } from '../../services/task-cloud.service';
@@ -50,8 +49,7 @@ describe('StartTaskCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
imports: [ProcessServiceCloudTestingModule, StartTaskCloudComponent]
});
fixture = TestBed.createComponent(StartTaskCloudComponent);
component = fixture.componentInstance;
@@ -16,9 +16,9 @@
*/
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, OnDestroy, ViewChild } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { DateAdapter, MAT_DATE_FORMATS, MatOptionModule } from '@angular/material/core';
import { Observable, Subject } from 'rxjs';
import { UntypedFormBuilder, Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
import { UntypedFormBuilder, Validators, UntypedFormGroup, UntypedFormControl, FormsModule, ReactiveFormsModule } 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';
@@ -30,12 +30,40 @@ import { IdentityUserService } from '../../../people/services/identity-user.serv
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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { FormDefinitionSelectorCloudComponent } from '../../../form/components/form-definition-selector-cloud.component';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatIconModule } from '@angular/material/icon';
const MAX_NAME_LENGTH = 255;
const DATE_FORMAT: string = 'dd/MM/yyyy';
@Component({
selector: 'adf-cloud-start-task',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatButtonModule,
MatCardModule,
FormDefinitionSelectorCloudComponent,
GroupCloudComponent,
PeopleCloudComponent,
MatDatepickerModule,
MatFormFieldModule,
MatInputModule,
FormsModule,
MatOptionModule,
MatSelectModule,
ReactiveFormsModule,
MatIconModule
],
templateUrl: './start-task-cloud.component.html',
styleUrls: ['./start-task-cloud.component.scss'],
providers: [
@@ -16,30 +16,11 @@
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MaterialModule } from '../../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { StartTaskCloudComponent } from './components/start-task-cloud.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { GroupCloudModule } from '../../group/group-cloud.module';
import { FormCloudModule } from '../../form/form-cloud.module';
import { PeopleCloudModule } from '../../people/people-cloud.module';
/** @deprecated use StartTaskCloudComponent instead */
@NgModule({
imports: [
CommonModule,
MaterialModule,
FormsModule,
ReactiveFormsModule,
GroupCloudModule,
CoreModule,
FormCloudModule,
PeopleCloudModule
],
declarations: [StartTaskCloudComponent],
exports: [
StartTaskCloudComponent
]
imports: [StartTaskCloudComponent],
exports: [StartTaskCloudComponent]
})
export class StartTaskCloudModule {
}
export class StartTaskCloudModule {}
@@ -16,29 +16,31 @@
*/
import { NgModule } from '@angular/core';
import { TaskListCloudModule } from './task-list/task-list-cloud.module';
import { TaskFiltersCloudModule } from './task-filters/task-filters-cloud.module';
import { StartTaskCloudModule } from './start-task/start-task-cloud.module';
import { TaskHeaderCloudModule } from './task-header/task-header-cloud.module';
import { TaskDirectiveModule } from './directives/task-directive.module';
import { TaskFormModule } from './task-form/task-form.module';
import { TASK_FILTERS_CLOUD_DIRECTIVES } from './task-filters/task-filters-cloud.module';
import { TaskFormCloudComponent } from './task-form/components/task-form-cloud.component';
import { StartTaskCloudComponent } from './start-task/components/start-task-cloud.component';
import { TaskHeaderCloudComponent } from './task-header/components/task-header-cloud.component';
import { CompleteTaskDirective } from './directives/complete-task.directive';
import { ClaimTaskCloudDirective } from './directives/claim-task-cloud.directive';
import { UnClaimTaskCloudDirective } from './directives/unclaim-task-cloud.directive';
import { TaskListCloudComponent } from './task-list/components/task-list-cloud.component';
import { ServiceTaskListCloudComponent } from './task-list/components/service-task-list-cloud.component';
export const TASK_CLOUD_DIRECTIVES = [
TaskListCloudComponent,
ServiceTaskListCloudComponent,
...TASK_FILTERS_CLOUD_DIRECTIVES,
StartTaskCloudComponent,
TaskHeaderCloudComponent,
TaskFormCloudComponent,
CompleteTaskDirective,
ClaimTaskCloudDirective,
UnClaimTaskCloudDirective
] as const;
/** @deprecated import individual standalone components instead */
@NgModule({
imports: [
TaskListCloudModule,
TaskFiltersCloudModule,
StartTaskCloudModule,
TaskHeaderCloudModule,
TaskDirectiveModule,
TaskFormModule
],
exports: [
TaskListCloudModule,
TaskFiltersCloudModule,
StartTaskCloudModule,
TaskHeaderCloudModule,
TaskDirectiveModule,
TaskFormModule
]
imports: [...TASK_CLOUD_DIRECTIVES],
exports: [...TASK_CLOUD_DIRECTIVES]
})
export class TaskCloudModule { }
export class TaskCloudModule {}
@@ -24,12 +24,10 @@ import { LocalPreferenceCloudService } from '../../../../services/local-preferen
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { AppsProcessCloudService } from '../../../../app/services/apps-process-cloud.service';
import { fakeApplicationInstance, fakeApplicationInstanceWithEnvironment } from '../../../../app/mock/app-model.mock';
import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
import { ServiceTaskFilterCloudService } from '../../services/service-task-filter-cloud.service';
import { TaskCloudService } from '../../../services/task-cloud.service';
import { fakeServiceFilter } from '../../mock/task-filters-cloud.mock';
import { EditServiceTaskFilterCloudComponent } from './edit-service-task-filter-cloud.component';
import { MatIconTestingModule } from '@angular/material/icon/testing';
import { ProcessDefinitionCloud } from '../../../../models/process-definition-cloud.model';
import { TaskFilterDialogCloudComponent } from '../task-filter-dialog/task-filter-dialog-cloud.component';
import { fakeEnvironmentList } from '../../../../common/mock/environment.mock';
@@ -54,7 +52,7 @@ describe('EditServiceTaskFilterCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, TaskFiltersCloudModule, MatIconTestingModule],
imports: [ProcessServiceCloudTestingModule, EditServiceTaskFilterCloudComponent],
providers: [MatDialog, { provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
fixture = TestBed.createComponent(EditServiceTaskFilterCloudComponent);
@@ -21,9 +21,44 @@ import { Observable } from 'rxjs';
import { TaskFilterProperties, TaskFilterAction, ServiceTaskFilterCloudModel } 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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { IconComponent } from '@alfresco/adf-core';
import { MatButtonModule } from '@angular/material/button';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatIconModule } from '@angular/material/icon';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { DateRangeFilterComponent } from '../../../../common/date-range-filter/date-range-filter.component';
import { PeopleCloudComponent } from '../../../../people/components/people-cloud.component';
import { TaskAssignmentFilterCloudComponent } from '../task-assignment-filter/task-assignment-filter.component';
import { MatExpansionModule } from '@angular/material/expansion';
@Component({
selector: 'adf-cloud-edit-service-task-filter',
standalone: true,
imports: [
CommonModule,
TranslateModule,
IconComponent,
MatButtonModule,
MatProgressSpinnerModule,
ReactiveFormsModule,
MatFormFieldModule,
MatSelectModule,
MatInputModule,
MatDatepickerModule,
MatIconModule,
MatCheckboxModule,
DateRangeFilterComponent,
PeopleCloudComponent,
TaskAssignmentFilterCloudComponent,
MatExpansionModule
],
templateUrl: './base-edit-task-filter-cloud.component.html',
styleUrls: ['./base-edit-task-filter-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -62,9 +97,7 @@ export class EditServiceTaskFilterCloudComponent extends BaseEditTaskFilterCloud
}
protected addFilter(filterToAdd: ServiceTaskFilterCloudModel): Observable<any> {
return this.serviceTaskFilterCloudService
.addFilter(filterToAdd)
.pipe(takeUntil(this.onDestroy$));
return this.serviceTaskFilterCloudService.addFilter(filterToAdd).pipe(takeUntil(this.onDestroy$));
}
isDisabledForDefaultFilters(action: TaskFilterAction): boolean {
@@ -25,16 +25,13 @@ import { LocalPreferenceCloudService } from '../../../../services/local-preferen
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { AppsProcessCloudService } from '../../../../app/services/apps-process-cloud.service';
import { fakeApplicationInstance } from '../../../../app/mock/app-model.mock';
import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
import { EditTaskFilterCloudComponent } from './edit-task-filter-cloud.component';
import { TaskFilterCloudService } from '../../services/task-filter-cloud.service';
import { TaskCloudService } from '../../../services/task-cloud.service';
import { fakeFilter } from '../../mock/task-filters-cloud.mock';
import { DateCloudFilterType } from '../../../../models/date-cloud-filter.model';
import { AssignmentType, TaskFilterCloudModel, TaskStatusFilter } from '../../models/filter-cloud.model';
import { PeopleCloudModule } from '../../../../people/people-cloud.module';
import { ProcessDefinitionCloud } from '../../../../models/process-definition-cloud.model';
import { MatIconTestingModule } from '@angular/material/icon/testing';
import {
mockAlfrescoApi,
mockCompletedDateFilter,
@@ -74,7 +71,7 @@ describe('EditTaskFilterCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, TaskFiltersCloudModule, PeopleCloudModule, MatIconTestingModule],
imports: [ProcessServiceCloudTestingModule, EditTaskFilterCloudComponent],
providers: [MatDialog, { provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
fixture = TestBed.createComponent(EditTaskFilterCloudComponent);
@@ -23,9 +23,44 @@ 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 { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { IconComponent } from '@alfresco/adf-core';
import { MatButtonModule } from '@angular/material/button';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatIconModule } from '@angular/material/icon';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { DateRangeFilterComponent } from '../../../../common/date-range-filter/date-range-filter.component';
import { PeopleCloudComponent } from '../../../../people/components/people-cloud.component';
import { TaskAssignmentFilterCloudComponent } from '../task-assignment-filter/task-assignment-filter.component';
import { MatExpansionModule } from '@angular/material/expansion';
@Component({
selector: 'adf-cloud-edit-task-filter',
standalone: true,
imports: [
CommonModule,
TranslateModule,
IconComponent,
MatButtonModule,
MatProgressSpinnerModule,
ReactiveFormsModule,
MatFormFieldModule,
MatSelectModule,
MatInputModule,
MatDatepickerModule,
MatIconModule,
MatCheckboxModule,
DateRangeFilterComponent,
PeopleCloudComponent,
TaskAssignmentFilterCloudComponent,
MatExpansionModule
],
templateUrl: './base-edit-task-filter-cloud.component.html',
styleUrls: ['./base-edit-task-filter-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -45,21 +80,14 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
}
protected getTaskFilterById(appName: string, id: string) {
return this.taskFilterCloudService
.getTaskFilterById(appName, id)
.pipe(
map(response => new TaskFilterCloudModel(response))
);
return this.taskFilterCloudService.getTaskFilterById(appName, id).pipe(map((response) => new TaskFilterCloudModel(response)));
}
createAndFilterProperties() {
const result = super.createAndFilterProperties();
if (this.hasLastModifiedProperty()) {
return [
...result,
...this.createLastModifiedProperty()
];
return [...result, ...this.createLastModifiedProperty()];
}
return result;
@@ -75,14 +103,11 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
private setLastModifiedToFilter(formValues: TaskFilterCloudModel) {
if (formValues.lastModifiedTo && Date.parse(formValues.lastModifiedTo.toString())) {
const lastModifiedToFilterValue = set(
new Date(formValues.lastModifiedTo),
{
hours: 23,
minutes: 59,
seconds: 59
}
);
const lastModifiedToFilterValue = set(new Date(formValues.lastModifiedTo), {
hours: 23,
minutes: 59,
seconds: 59
});
formValues.lastModifiedTo = lastModifiedToFilterValue.toISOString();
}
}
@@ -96,9 +121,7 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
}
protected addFilter(filterToAdd: TaskFilterCloudModel): Observable<any> {
return this.taskFilterCloudService
.addFilter(filterToAdd)
.pipe(takeUntil(this.onDestroy$));
return this.taskFilterCloudService.addFilter(filterToAdd).pipe(takeUntil(this.onDestroy$));
}
isDisabledForDefaultFilters(action: TaskFilterAction): boolean {
@@ -244,7 +267,7 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_DATE',
type: 'date-range',
key: 'dueDateRange',
attributes: { dateType: 'dueDateType', from: '_dueDateFrom', to: '_dueDateTo'},
attributes: { dateType: 'dueDateType', from: '_dueDateFrom', to: '_dueDateTo' },
value: {
dueDateType: this.taskFilter.dueDateType || null,
_dueDateFrom: this.taskFilter.dueDateFrom || null,
@@ -262,7 +285,7 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.COMPLETED_DATE',
type: 'date-range',
key: 'completedDateRange',
attributes: { dateType: 'completedDateType', from: '_completedFrom', to: '_completedTo'},
attributes: { dateType: 'completedDateType', from: '_completedFrom', to: '_completedTo' },
value: {
completedDateType: this.taskFilter.completedDateType || null,
_completedFrom: this.taskFilter.completedFrom || null,
@@ -273,7 +296,7 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.CREATED_DATE',
type: 'date-range',
key: 'createdDateRange',
attributes: { dateType: 'createdDateType', from: '_createdFrom', to: '_createdTo'},
attributes: { dateType: 'createdDateType', from: '_createdFrom', to: '_createdTo' },
value: {
createdDateType: this.taskFilter.createdDateType || null,
_createdFrom: this.taskFilter.createdFrom || null,
@@ -291,7 +314,7 @@ export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudCompone
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.ASSIGNMENT',
type: 'assignment',
key: 'assignment',
attributes: { assignedUsers: 'assignedUsers', candidateGroups: 'candidateGroups'},
attributes: { assignedUsers: 'assignedUsers', candidateGroups: 'candidateGroups' },
value: {
assignedUsers: this.taskFilter.assignedUsers || [],
candidateGroups: this.taskFilter.candidateGroups || []
@@ -22,7 +22,6 @@ import { TASK_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.servic
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
import { By } from '@angular/platform-browser';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TaskFiltersCloudModule } from '../task-filters-cloud.module';
import { fakeGlobalServiceFilters } from '../mock/task-filters-cloud.mock';
import { ServiceTaskFilterCloudService } from '../services/service-task-filter-cloud.service';
import { ServiceTaskFiltersCloudComponent } from './service-task-filters-cloud.component';
@@ -36,7 +35,7 @@ describe('ServiceTaskFiltersCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule, TaskFiltersCloudModule],
imports: [ProcessServiceCloudTestingModule, ServiceTaskFiltersCloudComponent],
providers: [{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
fixture = TestBed.createComponent(ServiceTaskFiltersCloudComponent);

Some files were not shown because too many files have changed in this diff Show More