[ACS-7421] process: break app list dependency on material bundle (#9640)

* chore: break apps list dependency on material module bundle
This commit is contained in:
Denys Vuika 2024-05-06 10:34:31 -04:00 committed by GitHub
parent 70804088a1
commit 6f0bbe427e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 153 additions and 585 deletions

View File

@ -19,13 +19,13 @@ import { NgModule } from '@angular/core';
import { TaskListDemoComponent } from './task-list-demo.component';
import { Routes, RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { CoreModule, LocalizedDatePipe } from '@alfresco/adf-core';
import { CoreModule, FullNamePipe, LocalizedDatePipe } from '@alfresco/adf-core';
import { ProcessModule } from '@alfresco/adf-process-services';
const routes: Routes = [
{
path: '',
component: TaskListDemoComponent
path: '',
component: TaskListDemoComponent
},
{
path: ':id',
@ -34,13 +34,7 @@ const routes: Routes = [
];
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(routes),
CoreModule,
ProcessModule.forChild(),
LocalizedDatePipe
],
imports: [CommonModule, RouterModule.forChild(routes), CoreModule, ProcessModule.forChild(), LocalizedDatePipe, FullNamePipe],
declarations: [TaskListDemoComponent]
})
export class AppTaskListModule {}

View File

@ -453,12 +453,6 @@ for more information about installing and using the source code.
| [Task Audit Directive](process-services/directives/task-audit.directive.md) | Fetches the Task Audit information in PDF or JSON format. | [Source](../lib/process-services/src/lib/task-list/components/task-audit.directive.ts) |
| [Unclaim Task Directive](process-services/directives/unclaim-task.directive.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Unclaims a task | [Source](../lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.ts) |
### Pipes
| Name | Description | Source link |
| ---- | ----------- | ----------- |
| [Process name pipe](process-services/pipes/process-name.pipe.md) | When an identifier is specified, the input will be transformed replacing the identifiers with the values of the selected process definition provided. | [Source](../lib/process-services/src/lib/pipes/process-name.pipe.ts) |
### Services
| Name | Description | Source link |

View File

@ -1,49 +0,0 @@
---
Title: Process name pipe
Added: v3.9.0
Status: Active
Last reviewed: 2020-06-02
---
# [Process name pipe](../../../lib/process-services/src/lib/pipes/process-name.pipe.ts "Defined in process-name.pipe.ts")
When an identifier is specified, the input will be transformed replacing the identifiers with the values of the selected process definition provided.
## Basic Usage
processNamePipe.transform('Example - %{processDefinition} - %{datetime}', new ProcessDefinitionRepresentation({ name: 'upload-passport'}));
### Properties
| Name | Type | Default value | Description |
| ---- | ---- | ------------- | ----------- |
| processNameFormat | string | undefined | The process name format including the preferred identifiers to be used |
| selectedProcessDefinition | [`ProcessDefinitionRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/activiti-rest-api/docs/ProcessDefinitionRepresentation.md) | undefined | (optional) The selected process definition |
## Details
The pipe offers a convenient way to format a process name using a process name format template.
The supported identifiers that can be used in the process name format are the following:
- %{processDefinition}
- %{datetime}
When the %{processDefinition} identifier is used, the selected process definition provided
will be added and positioned in the same place as the identifier.
When the %{datetime} identifier is used, the current datetime will be added and positioned in the same place as the identifier.
Important Notes:
- All the identifiers are case-insensitive.
- The identifiers can be used in any position (beginning, middle, end, custom).
- The identifiers can NOT be used more than once each in the same processNameFormat (The second occurrence of each identifier will be ignored
and handled as a plain string).
#### Result
```ts
processNamePipe.transform('Example - %{processDefinition} - %{datetime}', new ProcessDefinitionRepresentation({ name: 'upload-passport'}));
//Returns 'Example - upload passport - June 02, 2020, 12:00:00 AM'
```

View File

@ -19,7 +19,7 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ContentUserInfoComponent } from './content-user-info.component';
import { TranslateModule } from '@ngx-translate/core';
import { PipeModule } from '@alfresco/adf-core';
import { FullNamePipe, InitialUsernamePipe, PipeModule } from '@alfresco/adf-core';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { MatTabsModule } from '@angular/material/tabs';
@ -34,7 +34,9 @@ import { MatCardModule } from '@angular/material/card';
MatTabsModule,
MatCardModule,
TranslateModule,
PipeModule
PipeModule,
InitialUsernamePipe,
FullNamePipe
],
exports: [ContentUserInfoComponent]
})

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { CoreModule, PipeModule } from '@alfresco/adf-core';
import { CoreModule, InitialUsernamePipe, PipeModule } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@ -34,15 +34,7 @@ import { PopOverDirective } from './components/pop-over.directive';
import { PermissionContainerComponent } from './components/permission-container/permission-container.component';
@NgModule({
imports: [
CoreModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MaterialModule,
SearchModule,
PipeModule
],
imports: [CoreModule, CommonModule, FormsModule, ReactiveFormsModule, MaterialModule, SearchModule, PipeModule, InitialUsernamePipe],
declarations: [
PermissionListComponent,
AddPermissionPanelComponent,

View File

@ -1,7 +1,7 @@
<ng-container *ngIf="isCustom; else: default">
<ng-container *ngIf="isCustom; else: defaultIcon">
<mat-icon [color]="color" [svgIcon]="value" aria-hidden="true"></mat-icon>
</ng-container>
<ng-template #default>
<ng-template #defaultIcon>
<mat-icon [fontSet]="fontSet" [color]="color" aria-hidden="true">{{ value }}</mat-icon>
</ng-template>

View File

@ -15,16 +15,15 @@
* limitations under the License.
*/
import {
Component,
Input,
ViewEncapsulation,
ChangeDetectionStrategy
} from '@angular/core';
import { Component, Input, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
import { ThemePalette } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon';
import { NgIf } from '@angular/common';
@Component({
selector: 'adf-icon',
standalone: true,
imports: [MatIconModule, NgIf],
templateUrl: './icon.component.html',
styleUrls: ['./icon.component.scss'],
encapsulation: ViewEncapsulation.None,

View File

@ -17,19 +17,13 @@
import { NgModule } from '@angular/core';
import { IconComponent } from './icon.component';
import { MatIconModule } from '@angular/material/icon';
import { CommonModule } from '@angular/common';
/**
* @deprecated this Module is deprecated and should no longer be used.
* Consider importing components directly instead.
*/
@NgModule({
imports: [
CommonModule,
MatIconModule
],
declarations: [
IconComponent
],
exports: [
IconComponent
]
imports: [IconComponent],
exports: [IconComponent]
})
export class IconModule {}

View File

@ -24,6 +24,7 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatTabsModule } from '@angular/material/tabs';
import { TranslateModule } from '@ngx-translate/core';
import { PipeModule } from '../pipes/pipe.module';
import { FullNamePipe, InitialUsernamePipe } from '../pipes';
@NgModule({
declarations: [IdentityUserInfoComponent],
@ -34,7 +35,9 @@ import { PipeModule } from '../pipes/pipe.module';
MatTabsModule,
MatCardModule,
TranslateModule,
PipeModule
PipeModule,
InitialUsernamePipe,
FullNamePipe
],
exports: [IdentityUserInfoComponent]
})

View File

@ -16,9 +16,13 @@
*/
import { Component, ChangeDetectionStrategy, ViewEncapsulation, Input } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { IconComponent } from '../../icon';
@Component({
selector: 'adf-empty-content',
standalone: true,
imports: [TranslateModule, IconComponent],
templateUrl: './empty-content.component.html',
styleUrls: ['./empty-content.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
@ -26,7 +30,6 @@ import { Component, ChangeDetectionStrategy, ViewEncapsulation, Input } from '@a
host: { class: 'adf-empty-content' }
})
export class EmptyContentComponent {
/** Material Icon to use. */
@Input()
icon = 'cake';
@ -38,5 +41,4 @@ export class EmptyContentComponent {
/** String or Resource Key for the subtitle. */
@Input()
subtitle = '';
}

View File

@ -15,21 +15,19 @@
* limitations under the License.
*/
import {
Component,
ChangeDetectionStrategy,
Input,
ViewEncapsulation,
OnInit
} from '@angular/core';
import { Component, ChangeDetectionStrategy, Input, ViewEncapsulation, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { TranslationService } from '../../translation/translation.service';
import { Observable } from 'rxjs';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { map } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
@Component({
selector: 'adf-error-content',
standalone: true,
imports: [CommonModule, TranslateModule],
templateUrl: './error-content.component.html',
styleUrls: ['./error-content.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
@ -37,7 +35,6 @@ import { map } from 'rxjs/operators';
host: { class: 'adf-error-content' }
})
export class ErrorContentComponent implements OnInit {
static UNKNOWN_ERROR = 'UNKNOWN';
/** Error code associated with this error. */
@ -47,27 +44,22 @@ export class ErrorContentComponent implements OnInit {
errorCodeTranslated: string;
isSmallScreen$: Observable<boolean>;
constructor(private route: ActivatedRoute,
private translateService: TranslationService,
private breakpointObserver: BreakpointObserver
) {
}
constructor(private route: ActivatedRoute, private translateService: TranslationService, private breakpointObserver: BreakpointObserver) {}
ngOnInit() {
if (this.route) {
this.route.params.subscribe(params => {
this.route.params.subscribe((params) => {
const code = params['id'] || this.errorCode;
const errorHasTranslation = this.checkErrorExists(code);
this.errorCodeTranslated = errorHasTranslation ? code : ErrorContentComponent.UNKNOWN_ERROR;
this.errorCodeTranslated = errorHasTranslation ? code : ErrorContentComponent.UNKNOWN_ERROR;
});
}
this.isSmallScreen$ = this.breakpointObserver.observe([Breakpoints.XSmall, Breakpoints.Small]).pipe(map(({ matches }) => matches));
}
checkErrorExists(errorCode: string ) {
checkErrorExists(errorCode: string) {
const errorMessage = this.translateService.instant('ERROR_CONTENT.' + errorCode);
return errorMessage !== ('ERROR_CONTENT.' + errorCode);
return errorMessage !== 'ERROR_CONTENT.' + errorCode;
}
}

View File

@ -15,17 +15,16 @@
* limitations under the License.
*/
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { ErrorContentComponent } from './error-content/error-content.component';
import { EmptyContentComponent } from './empty-content/empty-content.component';
import { IconModule } from '../icon/icon.module';
import { MatButtonModule } from '@angular/material/button';
/**
* @deprecated this Module is deprecated and should no longer be used.
* Consider importing components directly instead.
*/
@NgModule({
imports: [CommonModule, TranslateModule, IconModule],
declarations: [ErrorContentComponent, EmptyContentComponent],
exports: [ErrorContentComponent, EmptyContentComponent, MatButtonModule]
imports: [ErrorContentComponent, EmptyContentComponent],
exports: [ErrorContentComponent, EmptyContentComponent]
})
export class TemplateModule {}

View File

@ -17,7 +17,7 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CoreModule, ToolbarModule } from '@alfresco/adf-core';
import { CoreModule, FormatSpacePipe, ToolbarModule } from '@alfresco/adf-core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MaterialModule } from '../material.module';
import { FormCloudComponent } from './components/form-cloud.component';
@ -58,7 +58,8 @@ import { A11yModule } from '@angular/cdk/a11y';
AlfrescoViewerModule,
RichTextEditorModule,
ToolbarModule,
A11yModule
A11yModule,
FormatSpacePipe
],
declarations: [
FormCloudComponent,
@ -93,5 +94,4 @@ import { A11yModule } from '@angular/cdk/a11y';
DisplayRichTextWidgetComponent
]
})
export class FormCloudModule {
}
export class FormCloudModule {}

View File

@ -19,26 +19,15 @@ import { NgModule } from '@angular/core';
import { PeopleCloudComponent } from './components/people-cloud.component';
import { CommonModule } from '@angular/common';
import { MaterialModule } from '../material.module';
import { CoreModule } from '@alfresco/adf-core';
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';
@NgModule({
imports: [
CommonModule,
MaterialModule,
FormsModule,
ReactiveFormsModule,
CoreModule
],
imports: [CommonModule, MaterialModule, FormsModule, ReactiveFormsModule, CoreModule, FullNamePipe, InitialUsernamePipe],
declarations: [PeopleCloudComponent],
exports: [
PeopleCloudComponent
],
providers: [
{ provide: IDENTITY_USER_SERVICE_TOKEN, useExisting: IdentityUserService }
]
exports: [PeopleCloudComponent],
providers: [{ provide: IDENTITY_USER_SERVICE_TOKEN, useExisting: IdentityUserService }]
})
export class PeopleCloudModule {
}
export class PeopleCloudModule {}

View File

@ -2,7 +2,7 @@
<mat-list *ngIf="isList()" class="adf-app-list">
<mat-list-item class="adf-app-list-item" (click)="selectApp(app)" (keyup.enter)="selectApp(app)" *ngFor="let app of appList" tabindex="0" role="button" title="{{app.name}}">
<mat-icon matListIcon>touch_app</mat-icon>
<span matLine>{{getAppName(app) | async}}</span>
<span matLine>{{getAppName(app) | translate}}</span>
</mat-list-item>
</mat-list>
<div *ngIf="isGrid()" class="adf-app-listgrid">
@ -11,7 +11,7 @@
<mat-card tabindex="0"
role="button"
class="adf-app-listgrid-item-card"
title="{{getAppName(app) | async}}"
title="{{getAppName(app) | translate}}"
[ngClass]="[getTheme(app)]"
(click)="selectApp(app)"
(keyup.enter)="selectApp(app)">
@ -19,7 +19,7 @@
<mat-icon class="adf-app-listgrid-item-card-logo-icon">{{getBackgroundIcon(app)}}</mat-icon>
</div>
<div mat-card-title class="adf-app-listgrid-item-card-title">
<h1>{{getAppName(app) | async}}</h1>
<h1>{{getAppName(app) | translate}}</h1>
</div>
<mat-card-subtitle class="adf-app-listgrid-item-card-subtitle">
<div class="adf-line-clamp">{{app.description}}</div>
@ -41,7 +41,10 @@
<ng-template #empty>
<div class="adf-app-list-empty" *ngIf="isEmpty()">
<ng-content select="adf-custom-empty-content-template" *ngIf="hasEmptyCustomContentTemplate; else defaultEmptyTemplate" class="adf-custom-empty-template"></ng-content>
<ng-content select="adf-custom-empty-content-template"
*ngIf="hasEmptyCustomContentTemplate; else defaultEmptyTemplate"
class="adf-custom-empty-template">
</ng-content>
<ng-template #defaultEmptyTemplate>
<adf-empty-content

View File

@ -151,9 +151,8 @@ describe('AppsListComponent', () => {
defaultAppId: 'tasks',
name: null
} as AppDefinitionRepresentationModel;
component.getAppName(appDataMock).subscribe((name) => {
expect(name).toBe('ADF_TASK_LIST.APPS.TASK_APP_NAME');
});
expect(component.getAppName(appDataMock)).toBe('ADF_TASK_LIST.APPS.TASK_APP_NAME');
});
it('should provide the application name, when it exists', () => {
@ -162,9 +161,7 @@ describe('AppsListComponent', () => {
name: 'the-name'
} as AppDefinitionRepresentationModel;
component.getAppName(appDataMock).subscribe((name) => {
expect(name).toBe(appDataMock.name);
});
expect(component.getAppName(appDataMock)).toBe(appDataMock.name);
});
});

View File

@ -15,14 +15,20 @@
* limitations under the License.
*/
import { TranslationService, CustomEmptyContentTemplateDirective } from '@alfresco/adf-core';
import { CustomEmptyContentTemplateDirective, EmptyContentComponent } from '@alfresco/adf-core';
import { AppsProcessService } from './services/apps-process.service';
import { AfterContentInit, Component, EventEmitter, Input, OnInit, Output, ContentChild, OnDestroy, ViewEncapsulation } from '@angular/core';
import { Observable, Observer, of, Subject } from 'rxjs';
import { Observable, Observer, Subject } from 'rxjs';
import { AppDefinitionRepresentationModel } from '../task-list';
import { IconModel } from './icon.model';
import { share, takeUntil, finalize } from 'rxjs/operators';
import { AppDefinitionRepresentation } from '@alfresco/js-api';
import { CommonModule } from '@angular/common';
import { MatListModule } from '@angular/material/list';
import { MatIconModule } from '@angular/material/icon';
import { MatCardModule } from '@angular/material/card';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { TranslateModule } from '@ngx-translate/core';
const DEFAULT_TASKS_APP: string = 'tasks';
const DEFAULT_TASKS_APP_NAME: string = 'ADF_TASK_LIST.APPS.TASK_APP_NAME';
@ -34,6 +40,8 @@ export const APP_LIST_LAYOUT_GRID: string = 'GRID';
@Component({
selector: 'adf-apps',
standalone: true,
imports: [CommonModule, MatListModule, MatIconModule, MatCardModule, MatProgressSpinnerModule, TranslateModule, EmptyContentComponent],
templateUrl: './apps-list.component.html',
styleUrls: ['./apps-list.component.scss'],
encapsulation: ViewEncapsulation.None,
@ -72,7 +80,7 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
private iconsMDL: IconModel;
private onDestroy$ = new Subject<boolean>();
constructor(private appsProcessService: AppsProcessService, private translationService: TranslationService) {
constructor(private appsProcessService: AppsProcessService) {
this.apps$ = new Observable<AppDefinitionRepresentationModel>((observer) => (this.appsObserver = observer)).pipe(share());
}
@ -102,8 +110,8 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
return app.defaultAppId === DEFAULT_TASKS_APP;
}
getAppName(app: AppDefinitionRepresentationModel): Observable<string> {
return this.isDefaultApp(app) ? this.translationService.get(DEFAULT_TASKS_APP_NAME) : of(app.name);
getAppName(app: AppDefinitionRepresentationModel): string {
return this.isDefaultApp(app) ? DEFAULT_TASKS_APP_NAME : app.name;
}
/**

View File

@ -15,18 +15,16 @@
* limitations under the License.
*/
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { AppsListComponent } from './apps-list.component';
import { SelectAppsDialogComponent } from './select-apps-dialog.component';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
/**
* @deprecated this Module is deprecated and should no longer be used.
* Consider importing components directly instead.
*/
@NgModule({
imports: [CommonModule, MaterialModule, CoreModule, MatProgressSpinnerModule],
declarations: [AppsListComponent, SelectAppsDialogComponent],
imports: [AppsListComponent, SelectAppsDialogComponent],
exports: [AppsListComponent, SelectAppsDialogComponent]
})
export class AppsListModule {}

View File

@ -1,30 +0,0 @@
/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const fakeApps = {
size: 2, total: 2, start: 0,
data: [
{
id: 1, defaultAppId: null, name: 'Sales-Fakes-App', description: 'desc-fake1', modelId: 22,
theme: 'theme-1-fake', icon: 'glyphicon-asterisk', deploymentId: '111', tenantId: null
},
{
id: 2, defaultAppId: null, name: 'health-care-Fake', description: 'desc-fake2', modelId: 33,
theme: 'theme-2-fake', icon: 'glyphicon-asterisk', deploymentId: '444', tenantId: null
}
]
};

View File

@ -16,30 +16,34 @@
*/
import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { AppsProcessService } from './services/apps-process.service';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatSelectModule } from '@angular/material/select';
import { MatButtonModule } from '@angular/material/button';
@Component({
selector: 'adf-select-apps-dialog',
standalone: true,
imports: [CommonModule, TranslateModule, MatDialogModule, MatSelectModule, MatButtonModule],
templateUrl: './select-apps-dialog.component.html',
styleUrls: ['./select-apps-dialog.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class SelectAppsDialogComponent {
processApps: any;
selectedProcess: any;
constructor(private appsProcessService: AppsProcessService,
public dialogRef: MatDialogRef<SelectAppsDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any) {
this.appsProcessService.getDeployedApplications().subscribe(
(apps) => {
this.processApps = apps.filter((currentApp) => currentApp.id);
}
);
constructor(
private appsProcessService: AppsProcessService,
public dialogRef: MatDialogRef<SelectAppsDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {
this.appsProcessService.getDeployedApplications().subscribe((apps) => {
this.processApps = apps.filter((currentApp) => currentApp.id);
});
}
onStart(): void {

View File

@ -1,91 +0,0 @@
/*!
* @license
* Copyright © 2005-2023 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 { TestBed } from '@angular/core/testing';
import { fakeApps } from '../mocks/apps-service.mock';
import { AppsProcessService } from './apps-process.service';
import { CoreTestingModule } from '@alfresco/adf-core';
declare let jasmine: any;
describe('AppsProcessService', () => {
let service: AppsProcessService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule]
});
service = TestBed.inject(AppsProcessService);
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('should get the deployed apps ', (done) => {
service.getDeployedApplications().subscribe((res: any) => {
expect(res).toBeDefined();
expect(res.length).toEqual(2);
expect(res[0].name).toEqual('Sales-Fakes-App');
expect(res[0].description).toEqual('desc-fake1');
expect(res[0].deploymentId).toEqual('111');
expect(res[1].name).toEqual('health-care-Fake');
expect(res[1].description).toEqual('desc-fake2');
expect(res[1].deploymentId).toEqual('444');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeApps)
});
});
it('should get the filter deployed app ', (done) => {
service.getDeployedApplicationsByName('health-care-Fake').subscribe((res: any) => {
expect(res).toBeDefined();
expect(res.name).toEqual('health-care-Fake');
expect(res.description).toEqual('desc-fake2');
expect(res.deploymentId).toEqual('444');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeApps)
});
});
it('should get the deployed app details by id ', (done) => {
service.getApplicationDetailsById(1).subscribe((app: any) => {
expect(app).toBeDefined();
expect(app.name).toEqual('Sales-Fakes-App');
expect(app.description).toEqual('desc-fake1');
expect(app.deploymentId).toEqual('111');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeApps)
});
});
});

View File

@ -17,7 +17,7 @@
import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { CoreModule, FormatSpacePipe } from '@alfresco/adf-core';
import { FormComponent } from './form.component';
import { StartFormComponent } from './start-form.component';
import { FormCustomOutcomesComponent } from './form-custom-outcomes.component';
@ -35,12 +35,7 @@ import { FileViewerWidgetComponent } from './widgets/file-viewer/file-viewer.wid
import { AlfrescoViewerModule } from '@alfresco/adf-content-services';
@NgModule({
imports: [
DynamicTableModule,
CoreModule,
AlfrescoViewerModule,
MaterialModule
],
imports: [DynamicTableModule, CoreModule, AlfrescoViewerModule, MaterialModule, FormatSpacePipe],
declarations: [
UploadWidgetComponent,
FormComponent,
@ -69,5 +64,4 @@ import { AlfrescoViewerModule } from '@alfresco/adf-content-services';
FileViewerWidgetComponent
]
})
export class FormModule {
}
export class FormModule {}

View File

@ -1,69 +0,0 @@
/*!
* @license
* Copyright © 2005-2023 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 { TestBed } from '@angular/core/testing';
import { ProcessNamePipe } from './process-name.pipe';
import { LocalizedDatePipe, CoreTestingModule } from '@alfresco/adf-core';
import { ProcessInstance } from '../process-list';
describe('ProcessNamePipe', () => {
let processNamePipe: ProcessNamePipe;
const defaultName = 'default-name';
const datetimeIdentifier = '%{datetime}';
const processDefinitionIdentifier = '%{processDefinition}';
const mockCurrentDate: number = new Date('Wed Oct 23 2019').getTime();
const mockLocalizedCurrentDate = 'Oct 23, 2019, 12:00:00 AM';
const nameWithProcessDefinitionIdentifier = `${defaultName} - ${processDefinitionIdentifier}`;
const nameWithDatetimeIdentifier = `${defaultName} - ${datetimeIdentifier}`;
const nameWithAllIdentifiers = `${defaultName} ${processDefinitionIdentifier} - ${datetimeIdentifier}`;
const fakeProcessInstanceDetails = new ProcessInstance({ processDefinitionName: 'fake-process-def-name' });
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule]
});
const localizedDatePipe = TestBed.inject(LocalizedDatePipe);
processNamePipe = new ProcessNamePipe(localizedDatePipe);
});
it('should not modify the name when there is no identifier', () => {
const transformResult = processNamePipe.transform(defaultName);
expect(transformResult).toEqual(defaultName);
});
it('should add the selected process definition name to the process name', () => {
const transformResult = processNamePipe.transform(nameWithProcessDefinitionIdentifier, fakeProcessInstanceDetails);
expect(transformResult).toEqual(`${defaultName} - ${fakeProcessInstanceDetails.processDefinitionName}`);
});
it('should add the current datetime to the process name', () => {
spyOn(Date.prototype, 'getTime').and.returnValue(mockCurrentDate);
const transformResult = processNamePipe.transform(nameWithDatetimeIdentifier);
expect(transformResult).toEqual(`${defaultName} - ${mockLocalizedCurrentDate}`);
});
it('should add the current datetime and the selected process definition name when both identifiers are present', () => {
spyOn(Date.prototype, 'getTime').and.returnValue(mockCurrentDate);
const transformResult = processNamePipe.transform(nameWithAllIdentifiers, fakeProcessInstanceDetails);
expect(transformResult).toEqual(`${defaultName} ${fakeProcessInstanceDetails.processDefinitionName} - ${mockLocalizedCurrentDate}`);
});
it('should not modify the process name when processDefinition identifier is present but no process definition is selected', () => {
const transformResult = processNamePipe.transform(nameWithProcessDefinitionIdentifier);
expect(transformResult).toEqual(`${defaultName} - `);
});
});

View File

@ -1,50 +0,0 @@
/*!
* @license
* Copyright © 2005-2023 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 { Pipe, PipeTransform } from '@angular/core';
import { getTime } from 'date-fns';
import { LocalizedDatePipe } from '@alfresco/adf-core';
import { ProcessInstance } from '../process-list';
const DATE_TIME_IDENTIFIER_REG_EXP = new RegExp('%{datetime}', 'i');
const PROCESS_DEFINITION_IDENTIFIER_REG_EXP = new RegExp('%{processdefinition}', 'i');
@Pipe({ name: 'processName' })
export class ProcessNamePipe implements PipeTransform {
constructor(private localizedDatePipe: LocalizedDatePipe) {
}
transform(processNameFormat: string, processInstance?: ProcessInstance): 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')
);
}
if (processName.match(PROCESS_DEFINITION_IDENTIFIER_REG_EXP)) {
const selectedProcessDefinitionName = processInstance ? processInstance.processDefinitionName : '';
processName = processName.replace(
PROCESS_DEFINITION_IDENTIFIER_REG_EXP,
selectedProcessDefinitionName
);
}
return processName;
}
}

View File

@ -1,31 +0,0 @@
/*!
* @license
* Copyright © 2005-2023 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 { ProcessNamePipe } from './process-name.pipe';
@NgModule({
declarations: [
ProcessNamePipe
],
exports: [
ProcessNamePipe
]
})
export class ProcessServicesPipeModule {
}

View File

@ -27,8 +27,6 @@ import { newProcess, taskFormMock, testProcessDef, testMultipleProcessDefs, test
import { StartProcessInstanceComponent } from './start-process.component';
import { ProcessTestingModule } from '../../testing/process.testing.module';
import { deployedApps } from '../../mock/apps-list.mock';
import { ProcessNamePipe } from '../../pipes/process-name.pipe';
import { ProcessInstance } from '../models/process-instance.model';
import { ActivitiContentService } from '../../form/services/activiti-alfresco.service';
import { HarnessLoader } from '@angular/cdk/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
@ -515,21 +513,6 @@ describe('StartProcessComponent', () => {
expect(processDefinitionSelectionSpy).toHaveBeenCalledWith(testProcessDef);
});
it('should set the process name using the processName pipe when a process definition gets selected', async () => {
const processNamePipe = TestBed.inject(ProcessNamePipe);
const processNamePipeTransformSpy = spyOn(processNamePipe, 'transform').and.returnValue('fake-transformed-name');
const expectedProcessInstanceDetails = new ProcessInstance({ processDefinitionName: testProcessDef.name });
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
changeAppId(123);
await selectOptionByName(testProcessDef.name);
expect(processNamePipeTransformSpy).toHaveBeenCalledWith(component.name, expectedProcessInstanceDetails);
expect(component.nameController.dirty).toBe(true);
expect(component.nameController.touched).toBe(true);
expect(component.nameController.value).toEqual('fake-transformed-name');
});
it('should not emit start event when start the process without select a process and name', () => {
component.name = null;
component.selectedProcessDef = null;

View File

@ -16,7 +16,7 @@
*/
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild, ViewEncapsulation, OnDestroy } from '@angular/core';
import { AppConfigService, AppConfigValues, FormValues } from '@alfresco/adf-core';
import { AppConfigService, AppConfigValues, FormValues, LocalizedDatePipe } from '@alfresco/adf-core';
import { AppsProcessService } from '../../app-list/services/apps-process.service';
import { ProcessInstanceVariable } from '../models/process-instance-variable.model';
import { ProcessDefinitionRepresentation } from './../models/process-definition.model';
@ -30,10 +30,13 @@ import { MatSelectChange } from '@angular/material/select';
import { StartFormComponent } from '../../form';
import { Node, RelatedContentRepresentation } from '@alfresco/js-api';
import { AppDefinitionRepresentationModel } from '../../task-list';
import { ProcessNamePipe } from '../../pipes/process-name.pipe';
import { ActivitiContentService } from '../../form/services/activiti-alfresco.service';
import { getTime } from 'date-fns';
const MAX_LENGTH = 255;
const DATE_TIME_IDENTIFIER_REG_EXP = new RegExp('%{datetime}', 'i');
const PROCESS_DEFINITION_IDENTIFIER_REG_EXP = new RegExp('%{processdefinition}', 'i');
@Component({
selector: 'adf-start-process',
templateUrl: './start-process.component.html',
@ -129,7 +132,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
private activitiContentService: ActivitiContentService,
private appsProcessService: AppsProcessService,
private appConfig: AppConfigService,
private processNamePipe: ProcessNamePipe
private datePipe: LocalizedDatePipe
) {}
ngOnInit() {
@ -422,7 +425,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
processDefinitionSelectionChanged(processDefinition: ProcessDefinitionRepresentation) {
if (processDefinition) {
const processInstanceDetails = new ProcessInstance({ processDefinitionName: processDefinition.name });
const processName = this.processNamePipe.transform(this.name, processInstanceDetails);
const processName = this.formatProcessName(this.name, processInstanceDetails);
this.processNameInput.setValue(processName);
this.processNameInput.markAsDirty();
this.processNameInput.markAsTouched();
@ -491,4 +494,18 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
return [];
}
private formatProcessName(processNameFormat: string, processInstance?: ProcessInstance): 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.datePipe.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);
}
return processName;
}
}

View File

@ -32,7 +32,6 @@ import { ProcessInstanceTasksComponent } from './components/process-instance-tas
import { ProcessInstanceListComponent } from './components/process-list.component';
import { StartProcessInstanceComponent } from './components/start-process.component';
import { FormModule } from '../form/form.module';
import { ProcessNamePipe } from '../pipes/process-name.pipe';
@NgModule({
imports: [
@ -64,10 +63,6 @@ import { ProcessNamePipe } from '../pipes/process-name.pipe';
ProcessInstanceHeaderComponent,
ProcessInstanceTasksComponent,
StartProcessInstanceComponent
],
providers: [
ProcessNamePipe
]
})
export class ProcessListModule {
}
export class ProcessListModule {}

View File

@ -1,84 +0,0 @@
/*!
* @license
* Copyright © 2005-2023 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 { BpmUserModel } from '../../common/models/bpm-user.model';
export const fakeBpmUserNoImage = {
apps: [],
capabilities: 'fake-capability',
company: 'fake-company',
created: 'fake-create-date',
email: 'fakeBpm@fake.com',
externalId: 'fake-external-id',
firstName: 'fake-first-name',
lastName: 'fake-last-name',
groups: [],
id: 'fake-id',
lastUpdate: 'fake-update-date',
latestSyncTimeStamp: 'fake-timestamp',
password: 'fake-password',
pictureId: undefined,
status: 'fake-status',
tenantId: 'fake-tenant-id',
tenantName: 'fake-tenant-name',
tenantPictureId: 'fake-tenant-picture-id',
type: 'fake-type'
};
export const fakeBpmUser = new BpmUserModel({
apps: [],
capabilities: null,
company: 'fake-company',
created: 'fake-create-date',
email: 'fakeBpm@fake.com',
externalId: 'fake-external-id',
firstName: 'fake-bpm-first-name',
lastName: 'fake-bpm-last-name',
groups: [],
id: 'fake-id',
lastUpdate: 'fake-update-date',
latestSyncTimeStamp: 'fake-timestamp',
password: 'fake-password',
pictureId: 12,
status: 'fake-status',
tenantId: 'fake-tenant-id',
tenantName: 'fake-tenant-name',
tenantPictureId: 'fake-tenant-picture-id',
type: 'fake-type'
});
export const fakeBpmEditedUser = {
apps: [],
capabilities: 'fake-capability',
company: 'fake-company',
created: 'fake-create-date',
email: 'fakeBpm@fake.com',
externalId: 'fake-external-id',
firstName: 'fake-first-name',
lastName: 'fake-last-name',
groups: [],
id: 'fake-id',
lastUpdate: 'fake-update-date',
latestSyncTimeStamp: 'fake-timestamp',
password: 'fake-password',
pictureId: 'src/assets/images/bpmImg.gif',
status: 'fake-status',
tenantId: 'fake-tenant-id',
tenantName: 'fake-tenant-name',
tenantPictureId: 'fake-tenant-picture-id',
type: 'fake-type'
};

View File

@ -22,11 +22,32 @@ import { MatMenuModule } from '@angular/material/menu';
import { By } from '@angular/platform-browser';
import { BpmUserModel } from '../common/models/bpm-user.model';
import { ProcessUserInfoComponent } from './process-user-info.component';
import { fakeBpmUser } from './mocks/bpm-user.service.mock';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTabGroupHarness, MatTabHarness } from '@angular/material/tabs/testing';
const fakeBpmUser = new BpmUserModel({
apps: [],
capabilities: null,
company: 'fake-company',
created: 'fake-create-date',
email: 'fakeBpm@fake.com',
externalId: 'fake-external-id',
firstName: 'fake-bpm-first-name',
lastName: 'fake-bpm-last-name',
groups: [],
id: 'fake-id',
lastUpdate: 'fake-update-date',
latestSyncTimeStamp: 'fake-timestamp',
password: 'fake-password',
pictureId: 12,
status: 'fake-status',
tenantId: 'fake-tenant-id',
tenantName: 'fake-tenant-name',
tenantPictureId: 'fake-tenant-picture-id',
type: 'fake-type'
});
describe('ProcessUserInfoComponent', () => {
const profilePictureUrl = 'alfresco-logo.svg';

View File

@ -23,7 +23,7 @@ import { MatCardModule } from '@angular/material/card';
import { MatMenuModule } from '@angular/material/menu';
import { MatTabsModule } from '@angular/material/tabs';
import { TranslateModule } from '@ngx-translate/core';
import { PipeModule } from '@alfresco/adf-core';
import { FullNamePipe, InitialUsernamePipe, PipeModule } from '@alfresco/adf-core';
@NgModule({
declarations: [ProcessUserInfoComponent],
@ -34,7 +34,9 @@ import { PipeModule } from '@alfresco/adf-core';
MatTabsModule,
MatCardModule,
TranslateModule,
PipeModule
PipeModule,
FullNamePipe,
InitialUsernamePipe
],
exports: [ProcessUserInfoComponent]
})

View File

@ -30,7 +30,6 @@ import { AttachmentModule } from './attachment/attachment.module';
import { PeopleModule } from './people/people.module';
import { FormModule } from './form/form.module';
import { ProcessFormRenderingService } from './form/process-form-rendering.service';
import { ProcessServicesPipeModule } from './pipes/process-services-pipe.module';
import { TaskCommentsModule } from './task-comments/task-comments.module';
import { ProcessUserInfoModule } from './process-user-info/process-user-info.module';
@ -49,12 +48,9 @@ import { ProcessUserInfoModule } from './process-user-info/process-user-info.mod
ProcessUserInfoModule,
AttachmentModule,
PeopleModule,
FormModule,
ProcessServicesPipeModule
],
providers: [
provideTranslations('adf-process-services', 'assets/adf-process-services')
FormModule
],
providers: [provideTranslations('adf-process-services', 'assets/adf-process-services')],
exports: [
CommonModule,
ProcessCommentsModule,
@ -67,8 +63,7 @@ import { ProcessUserInfoModule } from './process-user-info/process-user-info.mod
ProcessUserInfoModule,
AttachmentModule,
PeopleModule,
FormModule,
ProcessServicesPipeModule
FormModule
]
})
export class ProcessModule {

View File

@ -25,10 +25,5 @@ export * from './lib/process-comments/index';
export * from './lib/people/index';
export * from './lib/form/index';
export * from './lib/task-comments/index';
export * from './lib/pipes/process-name.pipe';
export * from './lib/pipes/process-services-pipe.module';
export * from './lib/pipes/process-name.pipe';
export * from './lib/pipes/process-services-pipe.module';
export * from './lib/material.module';
export * from './lib/process.module';