[AAE-7243] fix process services eslint warnings (#7498)

* fix process services eslint warnings

* fix constants

* revert type changes
This commit is contained in:
Denys Vuika
2022-02-17 13:07:13 +00:00
committed by GitHub
parent 1a6746ff3c
commit e017423c8c
91 changed files with 1863 additions and 1920 deletions

View File

@@ -22,7 +22,7 @@ import { AppsProcessService, setupTestBed } from '@alfresco/adf-core';
import { of, throwError } from 'rxjs';
import { defaultApp, deployedApps, nonDeployedApps } from '../mock/apps-list.mock';
import { AppsListComponent } from './apps-list.component';
import { AppsListComponent, APP_LIST_LAYOUT_GRID, APP_LIST_LAYOUT_LIST } from './apps-list.component';
import { ProcessTestingModule } from '../testing/process.testing.module';
import { TranslateModule } from '@ngx-translate/core';
@@ -181,14 +181,14 @@ describe('AppsListComponent', () => {
});
it('should display a grid when configured to', () => {
component.layoutType = AppsListComponent.LAYOUT_GRID;
component.layoutType = APP_LIST_LAYOUT_GRID;
fixture.detectChanges();
expect(component.isGrid()).toBe(true);
expect(component.isList()).toBe(false);
});
it('should display a list when configured to', () => {
component.layoutType = AppsListComponent.LAYOUT_LIST;
component.layoutType = APP_LIST_LAYOUT_LIST;
fixture.detectChanges();
expect(component.isGrid()).toBe(false);
expect(component.isList()).toBe(true);

View File

@@ -22,6 +22,14 @@ import { AppDefinitionRepresentationModel } from '../task-list';
import { IconModel } from './icon.model';
import { share, takeUntil, finalize } from 'rxjs/operators';
const DEFAULT_TASKS_APP: string = 'tasks';
const DEFAULT_TASKS_APP_NAME: string = 'ADF_TASK_LIST.APPS.TASK_APP_NAME';
const DEFAULT_TASKS_APP_THEME: string = 'theme-2';
const DEFAULT_TASKS_APP_ICON: string = 'glyphicon-asterisk';
export const APP_LIST_LAYOUT_LIST: string = 'LIST';
export const APP_LIST_LAYOUT_GRID: string = 'GRID';
@Component({
selector: 'adf-apps',
templateUrl: './apps-list.component.html',
@@ -31,14 +39,6 @@ import { share, takeUntil, finalize } from 'rxjs/operators';
})
export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
public static LAYOUT_LIST: string = 'LIST';
public static LAYOUT_GRID: string = 'GRID';
public static DEFAULT_TASKS_APP: string = 'tasks';
public static DEFAULT_TASKS_APP_NAME: string = 'ADF_TASK_LIST.APPS.TASK_APP_NAME';
public static DEFAULT_TASKS_APP_THEME: string = 'theme-2';
public static DEFAULT_TASKS_APP_ICON: string = 'glyphicon-asterisk';
public static DEFAULT_TASKS_APP_MATERIAL_ICON: string = 'favorite_border';
@ContentChild(CustomEmptyContentTemplateDirective)
emptyCustomContent: CustomEmptyContentTemplateDirective;
@@ -46,7 +46,7 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
* values, "GRID" and "LIST".
*/
@Input()
layoutType: string = AppsListComponent.LAYOUT_GRID;
layoutType: string = APP_LIST_LAYOUT_GRID;
/** Provides a way to filter the apps to show. */
@Input()
@@ -54,22 +54,20 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
/** Emitted when an app entry is clicked. */
@Output()
appClick: EventEmitter<AppDefinitionRepresentationModel> = new EventEmitter<AppDefinitionRepresentationModel>();
appClick = new EventEmitter<AppDefinitionRepresentationModel>();
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
error = new EventEmitter<any>();
private appsObserver: Observer<AppDefinitionRepresentationModel>;
apps$: Observable<AppDefinitionRepresentationModel>;
currentApp: AppDefinitionRepresentationModel;
appList: AppDefinitionRepresentationModel [] = [];
private iconsMDL: IconModel;
loading: boolean = false;
hasEmptyCustomContentTemplate: boolean = false;
private appsObserver: Observer<AppDefinitionRepresentationModel>;
private iconsMDL: IconModel;
private onDestroy$ = new Subject<boolean>();
constructor(
@@ -103,6 +101,79 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
}
}
isDefaultApp(app) {
return app.defaultAppId === DEFAULT_TASKS_APP;
}
getAppName(app) {
return this.isDefaultApp(app)
? this.translationService.get(DEFAULT_TASKS_APP_NAME)
: of(app.name);
}
/**
* Pass the selected app as next
*
* @param app
*/
selectApp(app: AppDefinitionRepresentationModel) {
this.currentApp = app;
this.appClick.emit(app);
}
/**
* Return true if the appId is the current app
*
* @param appId
*/
isSelected(appId: number): boolean {
return (this.currentApp !== undefined && appId === this.currentApp.id);
}
/**
* Check if the value of the layoutType property is an allowed value
*/
isValidType(): boolean {
return this.layoutType && (this.layoutType === APP_LIST_LAYOUT_LIST || this.layoutType === APP_LIST_LAYOUT_GRID);
}
/**
* Assign the default value to LayoutType
*/
setDefaultLayoutType(): void {
this.layoutType = APP_LIST_LAYOUT_GRID;
}
/**
* Return true if the layout type is LIST
*/
isList(): boolean {
return this.layoutType === APP_LIST_LAYOUT_LIST;
}
/**
* Return true if the layout type is GRID
*/
isGrid(): boolean {
return this.layoutType === APP_LIST_LAYOUT_GRID;
}
isEmpty(): boolean {
return this.appList.length === 0;
}
isLoading(): boolean {
return this.loading;
}
getTheme(app: AppDefinitionRepresentationModel): string {
return app.theme ? app.theme : '';
}
getBackgroundIcon(app: AppDefinitionRepresentationModel): string {
return this.iconsMDL.mapGlyphiconToMaterialDesignIcons(app.icon);
}
private load() {
this.loading = true;
this.appsProcessService
@@ -112,8 +183,8 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
(res: AppDefinitionRepresentationModel[]) => {
this.filterApps(res).forEach((app) => {
if (this.isDefaultApp(app)) {
app.theme = AppsListComponent.DEFAULT_TASKS_APP_THEME;
app.icon = AppsListComponent.DEFAULT_TASKS_APP_ICON;
app.theme = DEFAULT_TASKS_APP_THEME;
app.icon = DEFAULT_TASKS_APP_ICON;
this.appsObserver.next(app);
} else if (app.deploymentId) {
this.appsObserver.next(app);
@@ -126,33 +197,6 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
);
}
isDefaultApp(app) {
return app.defaultAppId === AppsListComponent.DEFAULT_TASKS_APP;
}
getAppName(app) {
return this.isDefaultApp(app)
? this.translationService.get(AppsListComponent.DEFAULT_TASKS_APP_NAME)
: of(app.name);
}
/**
* Pass the selected app as next
* @param app
*/
public selectApp(app: AppDefinitionRepresentationModel) {
this.currentApp = app;
this.appClick.emit(app);
}
/**
* Return true if the appId is the current app
* @param appId
*/
isSelected(appId: number): boolean {
return (this.currentApp !== undefined && appId === this.currentApp.id);
}
private filterApps(apps: AppDefinitionRepresentationModel []): AppDefinitionRepresentationModel[] {
const filteredApps: AppDefinitionRepresentationModel[] = [];
if (this.filtersAppId) {
@@ -173,49 +217,4 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
}
return filteredApps;
}
/**
* Check if the value of the layoutType property is an allowed value
*/
isValidType(): boolean {
return this.layoutType && (this.layoutType === AppsListComponent.LAYOUT_LIST || this.layoutType === AppsListComponent.LAYOUT_GRID);
}
/**
* Assign the default value to LayoutType
*/
setDefaultLayoutType(): void {
this.layoutType = AppsListComponent.LAYOUT_GRID;
}
/**
* Return true if the layout type is LIST
*/
isList(): boolean {
return this.layoutType === AppsListComponent.LAYOUT_LIST;
}
/**
* Return true if the layout type is GRID
*/
isGrid(): boolean {
return this.layoutType === AppsListComponent.LAYOUT_GRID;
}
isEmpty(): boolean {
return this.appList.length === 0;
}
isLoading(): boolean {
return this.loading;
}
getTheme(app: AppDefinitionRepresentationModel): string {
return app.theme ? app.theme : '';
}
getBackgroundIcon(app: AppDefinitionRepresentationModel): string {
return this.iconsMDL.mapGlyphiconToMaterialDesignIcons(app.icon);
}
}

View File

@@ -15,10 +15,10 @@
* limitations under the License.
*/
const DEFAULT_TASKS_APP_MATERIAL_ICON: string = 'favorite_border';
/* spellchecker: disable */
export class IconModel {
public static DEFAULT_TASKS_APP_MATERIAL_ICON: string = 'favorite_border';
private iconsMDL: Map<string, string>;
constructor() {
@@ -26,7 +26,7 @@ export class IconModel {
}
mapGlyphiconToMaterialDesignIcons(icon: string) {
return this.iconsMDL.get(icon) ? this.iconsMDL.get(icon) : IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON;
return this.iconsMDL.get(icon) ? this.iconsMDL.get(icon) : DEFAULT_TASKS_APP_MATERIAL_ICON;
}
/**
@@ -114,51 +114,51 @@ export class IconModel {
this.iconsMDL.set('glyphicon-eye-close', 'remove_red_eye');
this.iconsMDL.set('glyphicon-warning-sign', 'warning');
this.iconsMDL.set('glyphicon-plane', 'airplanemode_active');
this.iconsMDL.set('glyphicon-calendar', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-calendar', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-random', 'shuffle');
this.iconsMDL.set('glyphicon-comment', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-magnet', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-retweet', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-shopping-cart', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-folder-close', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-folder-open', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-hdd', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-bullhorn', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-bell', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-certificate', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-thumbs-up', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-thumbs-down', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-hand-left', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-globe', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-wrench', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tasks', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-filter', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-briefcase', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-dashboard', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-paperclip', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-link', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-phone', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-pushpin', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-usd', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-gbp', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-sort', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-flash', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-comment', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-magnet', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-retweet', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-shopping-cart', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-folder-close', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-folder-open', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-hdd', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-bullhorn', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-bell', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-certificate', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-thumbs-up', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-thumbs-down', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-hand-left', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-globe', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-wrench', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tasks', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-filter', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-briefcase', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-dashboard', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-paperclip', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-link', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-phone', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-pushpin', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-usd', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-gbp', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-sort', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-flash', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-record', 'radio_button_checked');
this.iconsMDL.set('glyphicon-save', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-open', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-saved', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-save', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-open', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-saved', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-send', 'send');
this.iconsMDL.set('glyphicon-floppy-disk', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-credit-card', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cutlery', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-earphone', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-phone-alt', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tower', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-stats', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cloud-download', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cloud-upload', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tree-conifer', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tree-deciduous', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-floppy-disk', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-credit-card', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cutlery', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-earphone', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-phone-alt', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tower', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-stats', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cloud-download', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cloud-upload', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tree-conifer', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tree-deciduous', DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-align-left', 'format_align_left');
}
}

View File

@@ -34,10 +34,8 @@ export class SelectAppsDialogComponent {
@Inject(MAT_DIALOG_DATA) public data: any) {
this.appsProcessService.getDeployedApplications().subscribe(
(apps: any[]) => {
this.processApps = apps.filter((currentApp) => {
return currentApp.id;
});
(apps) => {
this.processApps = apps.filter((currentApp) => currentApp.id);
}
);
}

View File

@@ -31,7 +31,7 @@ describe('CreateProcessAttachmentComponent', () => {
let element: HTMLElement;
const file = new File([new Blob()], 'Test');
const fileObj = { entry: null, file: file, relativeFolder: '/' };
const fileObj = { entry: null, file, relativeFolder: '/' };
const customEvent = { detail: { files: [fileObj] } };
const fakeUploadResponse = {
@@ -76,7 +76,7 @@ describe('CreateProcessAttachmentComponent', () => {
component.processInstanceId = null;
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
expect(component.processInstanceId).toBe('123');
});
@@ -92,14 +92,14 @@ describe('CreateProcessAttachmentComponent', () => {
component.onFileUpload(customEvent);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeUploadResponse)
});
});
it('should allow user to upload files via button', (done) => {
const buttonUpload: HTMLElement = <HTMLElement> element.querySelector('#add_new_process_content_button');
const buttonUpload = element.querySelector<HTMLElement>('#add_new_process_content_button');
expect(buttonUpload).toBeDefined();
expect(buttonUpload).not.toBeNull();
@@ -115,7 +115,7 @@ describe('CreateProcessAttachmentComponent', () => {
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeUploadResponse)
});

View File

@@ -52,13 +52,13 @@ describe('AttachmentComponent', () => {
it('should not call createTaskRelatedContent service when taskId changed', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'taskId': change});
component.ngOnChanges({taskId: change});
expect(createTaskRelatedContentSpy).not.toHaveBeenCalled();
});
it('should not call createTaskRelatedContent service when there is no file uploaded', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'taskId': change});
component.ngOnChanges({taskId: change});
const customEvent: any = {
detail: {
files: []
@@ -70,7 +70,7 @@ describe('AttachmentComponent', () => {
it('should call createTaskRelatedContent service when there is a file uploaded', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'taskId': change});
component.ngOnChanges({taskId: change});
const file = new File([new Blob()], 'Test');
const customEvent = {
detail: {

View File

@@ -100,7 +100,7 @@ describe('ProcessAttachmentListComponent', () => {
afterEach(() => {
fixture.destroy();
const overlayContainers = <any> window.document.querySelectorAll('.cdk-overlay-container');
const overlayContainers = window.document.querySelectorAll('.cdk-overlay-container');
overlayContainers.forEach((overlayContainer) => {
overlayContainer.innerHTML = '';
@@ -109,7 +109,7 @@ describe('ProcessAttachmentListComponent', () => {
it('should load attachments when processInstanceId specified', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
expect(getProcessRelatedContentSpy).toHaveBeenCalled();
});
@@ -117,7 +117,7 @@ describe('ProcessAttachmentListComponent', () => {
const emitSpy = spyOn(component.error, 'emit');
getProcessRelatedContentSpy.and.returnValue(throwError({}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
expect(emitSpy).toHaveBeenCalled();
});
@@ -128,7 +128,7 @@ describe('ProcessAttachmentListComponent', () => {
expect(attachments[0].id).toEqual(mockAttachment.data[0].id);
});
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
});
it('should not attach when no processInstanceId is specified', () => {
@@ -138,7 +138,7 @@ describe('ProcessAttachmentListComponent', () => {
it('should display attachments when the process has attachments', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.debugElement.queryAll(By.css('.adf-datatable-body > .adf-datatable-row')).length).toBe(2);
@@ -146,7 +146,7 @@ describe('ProcessAttachmentListComponent', () => {
it('should display all actions if attachments are not read only', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -166,7 +166,7 @@ describe('ProcessAttachmentListComponent', () => {
it('should not display remove action if attachments are read only', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
component.disabled = true;
fixture.detectChanges();
@@ -186,13 +186,13 @@ describe('ProcessAttachmentListComponent', () => {
it('should show the empty list component when the attachments list is empty', async () => {
getProcessRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
size: 0,
total: 0,
start: 0,
data: []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
@@ -200,13 +200,13 @@ describe('ProcessAttachmentListComponent', () => {
it('should not show the empty list drag and drop component when is disabled', async () => {
getProcessRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
size: 0,
total: 0,
start: 0,
data: []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
component.disabled = true;
fixture.detectChanges();
@@ -217,13 +217,13 @@ describe('ProcessAttachmentListComponent', () => {
it('should show the empty list component when the attachments list is empty for completed process', async () => {
getProcessRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
size: 0,
total: 0,
start: 0,
data: []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
component.disabled = true;
fixture.detectChanges();
@@ -236,7 +236,7 @@ describe('ProcessAttachmentListComponent', () => {
it('should not show the empty list component when the attachments list is not empty for completed process', async () => {
getProcessRelatedContentSpy.and.returnValue(of(mockAttachment));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
component.disabled = true;
fixture.detectChanges();
@@ -248,7 +248,7 @@ describe('ProcessAttachmentListComponent', () => {
getProcessRelatedContentSpy.and.returnValue(of(mockAttachment));
const change = new SimpleChange(null, '123', true);
const isRelatedContent = 'true';
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
expect(getProcessRelatedContentSpy).toHaveBeenCalled();
expect(getProcessRelatedContentSpy).toHaveBeenCalledWith('123', { isRelatedContent });
});
@@ -265,7 +265,7 @@ describe('ProcessAttachmentListComponent', () => {
});
it('should fetch new attachments when processInstanceId changed', () => {
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
const isRelatedContent = 'true';
expect(getProcessRelatedContentSpy).toHaveBeenCalledWith('456', { isRelatedContent });
});
@@ -276,7 +276,7 @@ describe('ProcessAttachmentListComponent', () => {
});
it('should NOT fetch new attachments when processInstanceId changed to null', () => {
component.ngOnChanges({ 'processInstanceId': nullChange });
component.ngOnChanges({ processInstanceId: nullChange });
expect(getProcessRelatedContentSpy).not.toHaveBeenCalled();
});
});

View File

@@ -117,46 +117,6 @@ export class ProcessAttachmentListComponent implements OnChanges, AfterContentIn
});
}
private loadAttachmentsByProcessInstanceId(processInstanceId: string) {
if (processInstanceId) {
this.reset();
this.isLoading = true;
const isRelatedContent = 'true';
this.activitiContentService.getProcessRelatedContent(processInstanceId, { isRelatedContent }).subscribe(
(res: any) => {
res.data.forEach((content) => {
this.attachments.push({
id: content.id,
name: content.name,
created: content.created,
createdBy: content.createdBy.firstName + ' ' + content.createdBy.lastName,
icon: this.thumbnailService.getMimeTypeIcon(content.mimeType)
});
});
this.success.emit(this.attachments);
this.isLoading = false;
},
(err) => {
this.error.emit(err);
this.isLoading = false;
});
}
}
private deleteAttachmentById(contentId: number) {
if (contentId) {
this.activitiContentService.deleteRelatedContent(contentId).subscribe(
() => {
this.attachments = this.attachments.filter((content) => {
return content.id !== contentId;
});
},
(err) => {
this.error.emit(err);
});
}
}
isEmpty(): boolean {
return this.attachments && this.attachments.length === 0;
}
@@ -228,4 +188,42 @@ export class ProcessAttachmentListComponent implements OnChanges, AfterContentIn
isDisabled(): boolean {
return this.disabled;
}
private loadAttachmentsByProcessInstanceId(processInstanceId: string) {
if (processInstanceId) {
this.reset();
this.isLoading = true;
const isRelatedContent = 'true';
this.activitiContentService.getProcessRelatedContent(processInstanceId, { isRelatedContent }).subscribe(
(res: any) => {
res.data.forEach((content) => {
this.attachments.push({
id: content.id,
name: content.name,
created: content.created,
createdBy: content.createdBy.firstName + ' ' + content.createdBy.lastName,
icon: this.thumbnailService.getMimeTypeIcon(content.mimeType)
});
});
this.success.emit(this.attachments);
this.isLoading = false;
},
(err) => {
this.error.emit(err);
this.isLoading = false;
});
}
}
private deleteAttachmentById(contentId: number) {
if (contentId) {
this.activitiContentService.deleteRelatedContent(contentId).subscribe(
() => {
this.attachments = this.attachments.filter((content) => content.id !== contentId);
},
(err) => {
this.error.emit(err);
});
}
}
}

View File

@@ -98,7 +98,7 @@ describe('TaskAttachmentList', () => {
});
afterEach(() => {
const overlayContainers = <any> window.document.querySelectorAll('.cdk-overlay-container');
const overlayContainers = window.document.querySelectorAll('.cdk-overlay-container');
overlayContainers.forEach((overlayContainer) => {
overlayContainer.innerHTML = '';
});
@@ -110,7 +110,7 @@ describe('TaskAttachmentList', () => {
it('should load attachments when taskId specified', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
expect(getTaskRelatedContentSpy).toHaveBeenCalled();
});
@@ -118,7 +118,7 @@ describe('TaskAttachmentList', () => {
const emitSpy = spyOn(component.error, 'emit');
getTaskRelatedContentSpy.and.returnValue(throwError({}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
expect(emitSpy).toHaveBeenCalled();
});
@@ -129,7 +129,7 @@ describe('TaskAttachmentList', () => {
expect(attachments[0].id).toEqual(mockAttachment.data[0].id);
});
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
});
it('should not attach when no taskId is specified', () => {
@@ -139,7 +139,7 @@ describe('TaskAttachmentList', () => {
it('should display attachments when the task has attachments', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.debugElement.queryAll(By.css('.adf-datatable-body > .adf-datatable-row')).length).toBe(2);
@@ -159,13 +159,13 @@ describe('TaskAttachmentList', () => {
it('should show the empty default message when has no custom template', async () => {
getTaskRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
size: 0,
total: 0,
start: 0,
data: []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
component.hasCustomTemplate = false;
fixture.detectChanges();
@@ -177,7 +177,7 @@ describe('TaskAttachmentList', () => {
it('should display all actions if attachments are not read only', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -195,7 +195,7 @@ describe('TaskAttachmentList', () => {
it('should not display remove action if attachments are read only', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
component.disabled = true;
fixture.detectChanges();
await fixture.whenStable();
@@ -215,13 +215,13 @@ describe('TaskAttachmentList', () => {
it('should show the empty list component when the attachments list is empty', async () => {
getTaskRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
size: 0,
total: 0,
start: 0,
data: []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -231,13 +231,13 @@ describe('TaskAttachmentList', () => {
it('should show the empty list component when the attachments list is empty for completed task', async () => {
getTaskRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
size: 0,
total: 0,
start: 0,
data: []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
component.disabled = true;
fixture.whenStable().then(() => {
@@ -249,7 +249,7 @@ describe('TaskAttachmentList', () => {
it('should not show the empty list component when the attachments list is not empty for completed task', async () => {
getTaskRelatedContentSpy.and.returnValue(of(mockAttachment));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
component.disabled = true;
fixture.detectChanges();
@@ -281,7 +281,7 @@ describe('TaskAttachmentList', () => {
fixture.detectChanges();
await fixture.whenStable();
const isRelatedContent = 'true';
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
expect(getTaskRelatedContentSpy).toHaveBeenCalledWith('456', { isRelatedContent });
});
@@ -291,7 +291,7 @@ describe('TaskAttachmentList', () => {
});
it('should NOT fetch new attachments when taskId changed to null', () => {
component.ngOnChanges({ 'taskId': nullChange });
component.ngOnChanges({ taskId: nullChange });
expect(getTaskRelatedContentSpy).not.toHaveBeenCalled();
});
});

View File

@@ -114,41 +114,11 @@ export class TaskAttachmentListComponent implements OnChanges, AfterContentInit
});
}
private loadAttachmentsByTaskId(taskId: string) {
if (taskId) {
this.isLoading = true;
this.reset();
const isRelatedContent = 'true';
this.activitiContentService.getTaskRelatedContent(taskId, { isRelatedContent }).subscribe(
(res: any) => {
const attachList = [];
res.data.forEach((content) => {
attachList.push({
id: content.id,
name: content.name,
created: content.created,
createdBy: content.createdBy.firstName + ' ' + content.createdBy.lastName,
icon: this.thumbnailService.getMimeTypeIcon(content.mimeType)
});
});
this.attachments = attachList;
this.success.emit(this.attachments);
this.isLoading = false;
},
(err) => {
this.error.emit(err);
this.isLoading = false;
});
}
}
deleteAttachmentById(contentId: number) {
if (contentId) {
this.activitiContentService.deleteRelatedContent(contentId).subscribe(
() => {
this.attachments = this.attachments.filter((content) => {
return content.id !== contentId;
});
this.attachments = this.attachments.filter((content) => content.id !== contentId);
},
(err) => {
this.error.emit(err);
@@ -227,4 +197,32 @@ export class TaskAttachmentListComponent implements OnChanges, AfterContentInit
isDisabled(): boolean {
return this.disabled;
}
private loadAttachmentsByTaskId(taskId: string) {
if (taskId) {
this.isLoading = true;
this.reset();
const isRelatedContent = 'true';
this.activitiContentService.getTaskRelatedContent(taskId, { isRelatedContent }).subscribe(
(res: any) => {
const attachList = [];
res.data.forEach((content) => {
attachList.push({
id: content.id,
name: content.name,
created: content.created,
createdBy: content.createdBy.firstName + ' ' + content.createdBy.lastName,
icon: this.thumbnailService.getMimeTypeIcon(content.mimeType)
});
});
this.attachments = attachList;
this.success.emit(this.attachments);
this.isLoading = false;
},
(err) => {
this.error.emit(err);
this.isLoading = false;
});
}
}
}

View File

@@ -74,15 +74,13 @@ describe('AttachFileWidgetDialogComponent', () => {
matDialogRef = fixture.debugElement.injector.get(MatDialogRef);
apiService = fixture.debugElement.injector.get(AlfrescoApiService);
spyOn(documentListService, 'getFolderNode').and.returnValue(of(<NodeEntry> { entry: { path: { elements: [] } } }));
spyOn(documentListService, 'getFolderNode').and.returnValue(of({ entry: { path: { elements: [] } } } as NodeEntry));
spyOn(documentListService, 'getFolder').and.returnValue(throwError('No results for test'));
spyOn(nodeService, 'getNode').and.returnValue(of(new Node({ id: 'fake-node', path: { elements: [{ nodeType: 'st:site', name: 'fake-site'}] } })));
spyOn(siteService, 'getSite').and.returnValue(of(fakeSite));
spyOn(siteService, 'getSites').and.returnValue(of(new SitePaging({ list: { entries: [] } })));
spyOn(widget, 'isLoggedIn').and.callFake(() => {
return isLogged;
});
spyOn(widget, 'isLoggedIn').and.callFake(() => isLogged);
});
afterEach(() => {

View File

@@ -49,7 +49,7 @@ export class AttachFileWidgetDialogComponent {
private externalApiService: AlfrescoApiService,
private authenticationService: AuthenticationService,
private matDialogRef: MatDialogRef<AttachFileWidgetDialogComponent>) {
(<any> externalApiService).init(data.ecmHost, data.context);
(externalApiService as any).init(data.ecmHost, data.context);
this.action = data.actionName ? data.actionName.toUpperCase() : 'CHOOSE';
this.buttonActionName = `ATTACH-FILE.ACTIONS.${this.action}`;
this.updateTitle('DROPDOWN.MY_FILES_OPTION');
@@ -63,14 +63,6 @@ export class AttachFileWidgetDialogComponent {
}
}
private registerAndClose() {
this.data.registerExternalHost(this.data.accountIdentifier, this.externalApiService);
if (this.data.loginOnly) {
this.data.selected.complete();
this.matDialogRef.close();
}
}
isLoggedIn() {
return this.externalApiService.getInstance().isLoggedIn();
}
@@ -109,4 +101,12 @@ export class AttachFileWidgetDialogComponent {
hasNodeSelected(): boolean {
return this.chosenNode?.length > 0;
}
private registerAndClose() {
this.data.registerExternalHost(this.data.accountIdentifier, this.externalApiService);
if (this.data.loginOnly) {
this.data.selected.complete();
this.matDialogRef.close();
}
}
}

View File

@@ -29,11 +29,11 @@ import { switchMap } from 'rxjs/operators';
})
// eslint-disable-next-line @angular-eslint/directive-class-suffix
export class AttachFileWidgetDialogService {
private externalApis: { [key: string]: AlfrescoApiService } = {};
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
error = new EventEmitter<any>();
private externalApis: { [key: string]: AlfrescoApiService } = {};
constructor(private dialog: MatDialog,
private translation: TranslationService) {
@@ -41,6 +41,7 @@ export class AttachFileWidgetDialogService {
/**
* Opens a dialog to choose a file to upload.
*
* @param repository Alfresco endpoint that represents the content service
* @param currentFolderId Upload file from specific folder
* @returns Information about the chosen file(s)
@@ -62,19 +63,6 @@ export class AttachFileWidgetDialogService {
return selected;
}
private openLoginDialog(data: AttachFileWidgetDialogComponentData, currentPanelClass: string, chosenWidth: string) {
this.dialog.open(AttachFileWidgetDialogComponent, { data, panelClass: currentPanelClass, width: chosenWidth });
}
private showExternalHostLoginDialog(repository: AlfrescoEndpointRepresentation): Observable<AlfrescoApiService> {
const data = {
...this.constructPayload(repository),
loginOnly: true
};
return this.dialog.open(AttachFileWidgetDialogComponent, { data, panelClass: 'adf-attach-file-widget-dialog', width: '630px' })
.afterClosed();
}
downloadURL(repository: AlfrescoEndpointRepresentation, sourceId: string): Observable<string> {
const { accountIdentifier } = this.constructPayload(repository);
@@ -94,6 +82,30 @@ export class AttachFileWidgetDialogService {
);
}
addService(accountIdentifier: string, apiService: AlfrescoApiService) {
if (!this.externalApis[accountIdentifier]) {
this.externalApis[accountIdentifier] = apiService;
}
}
/** Closes the currently open dialog. */
close() {
this.dialog.closeAll();
}
private openLoginDialog(data: AttachFileWidgetDialogComponentData, currentPanelClass: string, chosenWidth: string) {
this.dialog.open(AttachFileWidgetDialogComponent, { data, panelClass: currentPanelClass, width: chosenWidth });
}
private showExternalHostLoginDialog(repository: AlfrescoEndpointRepresentation): Observable<AlfrescoApiService> {
const data = {
...this.constructPayload(repository),
loginOnly: true
};
return this.dialog.open(AttachFileWidgetDialogComponent, { data, panelClass: 'adf-attach-file-widget-dialog', width: '630px' })
.afterClosed();
}
private constructPayload(repository: AlfrescoEndpointRepresentation) {
const accountIdentifier = 'alfresco-' + repository.id + '-' + repository.name;
const ecmHost = repository.repositoryUrl.replace('/alfresco', '');
@@ -106,17 +118,6 @@ export class AttachFileWidgetDialogService {
return { ecmHost, accountIdentifier, selected, title, registerExternalHost };
}
addService(accountIdentifier: string, apiService: AlfrescoApiService) {
if (!this.externalApis[accountIdentifier]) {
this.externalApis[accountIdentifier] = apiService;
}
}
/** Closes the currently open dialog. */
close() {
this.dialog.closeAll();
}
private getLoginTitleTranslation(ecmHost: string): string {
return this.translation.instant(`ATTACH-FILE.DIALOG.LOGIN`, { ecmHost });
}

View File

@@ -38,27 +38,27 @@ import { AttachFileWidgetDialogService } from './attach-file-widget-dialog.servi
const fakeRepositoryListAnswer = [
{
'authorized': true,
'serviceId': 'alfresco-9999-SHAREME',
'metaDataAllowed': true,
'name': 'SHAREME',
'repositoryUrl': 'http://localhost:0000/SHAREME',
'id': 1000
authorized: true,
serviceId: 'alfresco-9999-SHAREME',
metaDataAllowed: true,
name: 'SHAREME',
repositoryUrl: 'http://localhost:0000/SHAREME',
id: 1000
},
{
'authorized': true,
'serviceId': 'alfresco-0000-GOKUSHARE',
'metaDataAllowed': true,
'name': 'GOKUSHARE',
'repositoryUrl': 'http://localhost:0000/GOKUSHARE'
authorized: true,
serviceId: 'alfresco-0000-GOKUSHARE',
metaDataAllowed: true,
name: 'GOKUSHARE',
repositoryUrl: 'http://localhost:0000/GOKUSHARE'
},
{
'authorized': true,
'serviceId': 'alfresco-2000-external',
'metaDataAllowed': true,
'name': 'external',
'repositoryUrl': 'http://externalhost.com/alfresco',
'id': 2000
authorized: true,
serviceId: 'alfresco-2000-external',
metaDataAllowed: true,
name: 'external',
repositoryUrl: 'http://externalhost.com/alfresco',
id: 2000
}
];
@@ -66,21 +66,21 @@ const onlyLocalParams = {
fileSource: {
serviceId: 'local-file'
}
};
} as FormFieldMetadata;
const allSourceParams = {
fileSource: {
serviceId: 'all-file-sources'
},
link: false
};
} as FormFieldMetadata;
const allSourceParamsWithLinkEnabled = {
fileSource: {
serviceId: 'all-file-sources'
},
link: true
};
} as FormFieldMetadata;
const definedSourceParams = {
fileSource: {
@@ -90,7 +90,7 @@ const definedSourceParams = {
accountId: 'goku-share-account-id'
}
}
};
} as FormFieldMetadata;
const externalDefinedSourceParams = {
fileSource: {
@@ -100,44 +100,44 @@ const externalDefinedSourceParams = {
accountId: 'external-account-id'
}
}
};
} as FormFieldMetadata;
const fakeMinimalNode: Node = <Node> {
const fakeMinimalNode: Node = {
id: 'fake',
name: 'fake-name',
content: {
mimeType: 'application/pdf'
}
};
} as Node;
const fakePngUpload: any = {
'id': 1166,
'name': 'fake-png.png',
'created': '2017-07-25T17:17:37.099Z',
'createdBy': { 'id': 1001, 'firstName': 'Admin', 'lastName': 'admin', 'email': 'admin' },
'relatedContent': false,
'contentAvailable': true,
'link': false,
'isExternal': false,
'mimeType': 'image/png',
'simpleType': 'image',
'previewStatus': 'queued',
'thumbnailStatus': 'queued'
id: 1166,
name: 'fake-png.png',
created: '2017-07-25T17:17:37.099Z',
createdBy: { id: 1001, firstName: 'Admin', lastName: 'admin', email: 'admin' },
relatedContent: false,
contentAvailable: true,
link: false,
isExternal: false,
mimeType: 'image/png',
simpleType: 'image',
previewStatus: 'queued',
thumbnailStatus: 'queued'
};
const fakePngAnswer: any = {
'id': 1155,
'name': 'a_png_file.png',
'created': '2017-07-25T17:17:37.099Z',
'createdBy': { 'id': 1001, 'firstName': 'Admin', 'lastName': 'admin', 'email': 'admin' },
'relatedContent': false,
'contentAvailable': true,
'isExternal': false,
'link': false,
'mimeType': 'image/png',
'simpleType': 'image',
'previewStatus': 'queued',
'thumbnailStatus': 'queued'
id: 1155,
name: 'a_png_file.png',
created: '2017-07-25T17:17:37.099Z',
createdBy: { id: 1001, firstName: 'Admin', lastName: 'admin', email: 'admin' },
relatedContent: false,
contentAvailable: true,
isExternal: false,
link: false,
mimeType: 'image/png',
simpleType: 'image',
previewStatus: 'queued',
thumbnailStatus: 'queued'
};
describe('AttachFileWidgetComponent', () => {
@@ -183,19 +183,19 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'simple-upload-button';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
widget.field.params = onlyLocalParams;
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('#simple-upload-button')).not.toBeNull();
});
it('should show up all the repository option on menu list', async() => {
it('should show up all the repository option on menu list', async () => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParams;
widget.field.params = allSourceParams;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
fixture.detectChanges();
await fixture.whenRenderingDone();
@@ -226,7 +226,7 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParamsWithLinkEnabled;
widget.field.params = allSourceParamsWithLinkEnabled;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
fixture.detectChanges();
await fixture.whenRenderingDone();
@@ -260,7 +260,7 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParamsWithLinkEnabled;
widget.field.params = allSourceParamsWithLinkEnabled;
fixture.detectChanges();
await fixture.whenRenderingDone();
@@ -285,7 +285,7 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParams;
widget.field.params = allSourceParams;
fixture.detectChanges();
await fixture.whenRenderingDone();
@@ -310,7 +310,7 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParams;
widget.field.params = allSourceParams;
fixture.detectChanges();
await fixture.whenStable();
@@ -345,7 +345,7 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParams;
widget.field.params = allSourceParams;
widget.field.params.multiple = true;
fixture.detectChanges();
@@ -373,7 +373,7 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> definedSourceParams;
widget.field.params = definedSourceParams;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValue(of(fakePngAnswer));
spyOn(contentNodeDialogService, 'openFileBrowseDialogByFolderId').and.returnValue(of([fakeMinimalNode]));
@@ -403,7 +403,7 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
widget.field.params = onlyLocalParams;
spyOn(processContentService, 'createTemporaryRawRelatedContent').and.returnValue(of(fakePngAnswer));
fixture.detectChanges();
@@ -423,7 +423,7 @@ describe('AttachFileWidgetComponent', () => {
});
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(null));
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
widget.field.params = onlyLocalParams;
fixture.detectChanges();
await fixture.whenStable();
@@ -439,7 +439,7 @@ describe('AttachFileWidgetComponent', () => {
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
widget.field.params = onlyLocalParams;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(null));
spyOn(processContentService, 'createTemporaryRawRelatedContent').and.returnValue(of(fakePngAnswer));
@@ -476,7 +476,7 @@ describe('AttachFileWidgetComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const removeOption = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-remove')).nativeElement;
const removeOption = fixture.debugElement.query(By.css('#file-1155-remove')).nativeElement as HTMLButtonElement;
removeOption.click();
fixture.detectChanges();
@@ -494,7 +494,7 @@ describe('AttachFileWidgetComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const downloadOption = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-download-file')).nativeElement;
const downloadOption = fixture.debugElement.query(By.css('#file-1155-download-file')).nativeElement as HTMLButtonElement;
downloadOption.click();
fixture.detectChanges();
@@ -503,7 +503,7 @@ describe('AttachFileWidgetComponent', () => {
expect(downloadService.downloadBlob).toHaveBeenCalled();
});
it('should raise formContentClicked event when show file is clicked', async() => {
it('should raise formContentClicked event when show file is clicked', async () => {
spyOn(processContentService, 'getFileRawContent').and.returnValue(of(fakePngAnswer));
formService.formContentClicked.subscribe((file) => {
expect(file).not.toBeNull();
@@ -516,13 +516,13 @@ describe('AttachFileWidgetComponent', () => {
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const showOption = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-show-file')).nativeElement;
const showOption = fixture.debugElement.query(By.css('#file-1155-show-file')).nativeElement as HTMLButtonElement;
showOption.click();
fixture.detectChanges();
await fixture.whenStable();
});
it('should not display the show button file when is an external file', async() => {
it('should not display the show button file when is an external file', async () => {
fakePngAnswer.isExternal = true;
spyOn(processContentService, 'getFileRawContent').and.returnValue(of(fakePngAnswer));
@@ -531,11 +531,11 @@ describe('AttachFileWidgetComponent', () => {
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const showOption = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-show-file')).nativeElement;
const showOption = fixture.debugElement.query(By.css('#file-1155-show-file')).nativeElement as HTMLButtonElement;
expect(showOption.disabled).toBeTruthy();
});
it('should not display the download button file when is an external file', async() => {
it('should not display the download button file when is an external file', async () => {
fakePngAnswer.isExternal = true;
spyOn(processContentService, 'getFileRawContent').and.returnValue(of(fakePngAnswer));
@@ -544,11 +544,11 @@ describe('AttachFileWidgetComponent', () => {
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const downloadOption = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-download-file')).nativeElement;
const downloadOption = fixture.debugElement.query(By.css('#file-1155-download-file')).nativeElement as HTMLButtonElement;
expect(downloadOption.disabled).toBeTruthy();
});
it('should display the download button file when is an internal file', async() => {
it('should display the download button file when is an internal file', async () => {
fakePngAnswer.isExternal = false;
spyOn(processContentService, 'getFileRawContent').and.returnValue(of(fakePngAnswer));
@@ -557,12 +557,12 @@ describe('AttachFileWidgetComponent', () => {
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const downloadOption: HTMLButtonElement = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-download-file')).nativeElement;
const downloadOption = fixture.debugElement.query(By.css('#file-1155-download-file')).nativeElement as HTMLButtonElement;
expect(downloadOption.disabled).toBeFalsy();
});
it('should not display the show button file when there is no contentAvailable', async() => {
it('should not display the show button file when there is no contentAvailable', async () => {
fakePngAnswer.contentAvailable = false;
spyOn(processContentService, 'getFileRawContent').and.returnValue(of(fakePngAnswer));
@@ -571,7 +571,7 @@ describe('AttachFileWidgetComponent', () => {
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
const showOption = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-show-file')).nativeElement;
const showOption = fixture.debugElement.query(By.css('#file-1155-show-file')).nativeElement as HTMLButtonElement;
expect(showOption.disabled).toBeTruthy();
});
});
@@ -579,7 +579,7 @@ describe('AttachFileWidgetComponent', () => {
it('should be able to upload files when a defined folder from external content service', async () => {
widget.field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [] });
widget.field.id = 'attach-external-file-attach';
widget.field.params = <FormFieldMetadata> externalDefinedSourceParams;
widget.field.params = externalDefinedSourceParams;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValue(of(fakePngAnswer));
spyOn(attachFileWidgetDialogService, 'openLogin').and.returnValue(of([fakeMinimalNode]));
@@ -604,7 +604,7 @@ describe('AttachFileWidgetComponent', () => {
it('should pass a valid repository id to open the external login', async () => {
widget.field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [] });
widget.field.id = 'attach-external-file-attach';
widget.field.params = <FormFieldMetadata> externalDefinedSourceParams;
widget.field.params = externalDefinedSourceParams;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValue(of(fakePngAnswer));
const openLoginSpy = spyOn(attachFileWidgetDialogService, 'openLogin').and.returnValue(of([fakeMinimalNode]));

View File

@@ -165,7 +165,7 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements
onRemoveAttachFile(file: File | RelatedContentRepresentation) {
if (this.isTemporaryFile(file)) {
this.tempFilesList.splice(this.tempFilesList.indexOf((<RelatedContentRepresentation> file).contentBlob), 1);
this.tempFilesList.splice(this.tempFilesList.indexOf((file as RelatedContentRepresentation).contentBlob), 1);
}
this.removeFile(file);
}
@@ -184,7 +184,7 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements
downloadContent(file: any | RelatedContentRepresentation): void {
if (this.isTemporaryFile(file)) {
const fileBlob = (<RelatedContentRepresentation> file).contentBlob;
const fileBlob = (file as RelatedContentRepresentation).contentBlob;
if (fileBlob) {
this.downloadService.downloadBlob(fileBlob, file.name);
} else {
@@ -204,9 +204,9 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements
this.downloadService.downloadUrl(nodeUrl, file.name);
}
} else {
this.processContentService.getFileRawContent((<any> file).id).subscribe(
this.processContentService.getFileRawContent(file.id).subscribe(
(blob: Blob) => {
this.downloadService.downloadBlob(blob, (<any> file).name);
this.downloadService.downloadBlob(blob, file.name);
},
() => {
this.logger.error('Impossible retrieve content for download');

View File

@@ -30,10 +30,10 @@ import { Node } from '@alfresco/js-api';
import { ProcessTestingModule } from '../testing/process.testing.module';
import { TranslateModule } from '@ngx-translate/core';
const fakeMinimalNode: Node = <Node> {
const fakeMinimalNode: Node = {
id: 'fake',
name: 'fake-name'
};
} as Node;
const definedSourceParams = {
folderSource : {

View File

@@ -61,7 +61,7 @@ describe('FormComponent', () => {
]
});
function buildWidget(type: string, injector: Injector): any {
const buildWidget = (type: string, injector: Injector): any => {
const resolver = formRenderingService.getComponentTypeResolver(type);
const widgetType = resolver(null);
@@ -70,7 +70,7 @@ describe('FormComponent', () => {
const componentRef = factory.create(injector);
return componentRef.instance;
}
};
beforeEach(() => {
visibilityService = TestBed.inject(WidgetVisibilityService);
@@ -230,20 +230,16 @@ describe('FormComponent', () => {
});
it('should get process variable if is a process task', () => {
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
});
});
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
}));
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(of(null));
spyOn(formService, 'getTask').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId, processDefinitionId: '10201' });
observer.complete();
});
});
spyOn(formService, 'getTask').and.callFake((currentTaskId) => new Observable((observer) => {
observer.next({ taskId: currentTaskId, processDefinitionId: '10201' });
observer.complete();
}));
const taskId = '123';
formComponent.taskId = taskId;
@@ -253,20 +249,16 @@ describe('FormComponent', () => {
});
it('should not get process variable if is not a process task', () => {
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
});
});
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
}));
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(of(null));
spyOn(formService, 'getTask').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId, processDefinitionId: 'null' });
observer.complete();
});
});
spyOn(formService, 'getTask').and.callFake((currentTaskId) => new Observable((observer) => {
observer.next({ taskId: currentTaskId, processDefinitionId: 'null' });
observer.complete();
}));
const taskId = '123';
formComponent.taskId = taskId;
@@ -311,7 +303,7 @@ describe('FormComponent', () => {
const taskId = '<task id>';
const change = new SimpleChange(null, taskId, true);
formComponent.ngOnChanges({ 'taskId': change });
formComponent.ngOnChanges({ taskId: change });
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId);
});
@@ -321,7 +313,7 @@ describe('FormComponent', () => {
const formId = '123';
const change = new SimpleChange(null, formId, true);
formComponent.ngOnChanges({ 'formId': change });
formComponent.ngOnChanges({ formId: change });
expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId);
});
@@ -331,7 +323,7 @@ describe('FormComponent', () => {
const formName = '<form>';
const change = new SimpleChange(null, formName, true);
formComponent.ngOnChanges({ 'formName': change });
formComponent.ngOnChanges({ formName: change });
expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName);
});
@@ -356,7 +348,7 @@ describe('FormComponent', () => {
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
formComponent.ngOnChanges({ 'tag': new SimpleChange(null, 'hello world', true) });
formComponent.ngOnChanges({ tag: new SimpleChange(null, 'hello world', true) });
expect(formComponent.getFormByTaskId).not.toHaveBeenCalled();
expect(formComponent.getFormDefinitionByFormId).not.toHaveBeenCalled();
@@ -479,12 +471,10 @@ describe('FormComponent', () => {
it('should fetch and parse form by task id', (done) => {
spyOn(formService, 'getTask').and.returnValue(of({}));
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
});
});
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
}));
const taskId = '456';
formComponent.formLoaded.subscribe(() => {
@@ -503,9 +493,7 @@ describe('FormComponent', () => {
spyOn(formService, 'getTask').and.returnValue(of({}));
spyOn(formComponent, 'handleError').and.stub();
spyOn(formService, 'getTaskForm').and.callFake(() => {
return throwError(error);
});
spyOn(formService, 'getTaskForm').and.callFake(() => throwError(error));
formComponent.getFormByTaskId('123').then((_) => {
expect(formComponent.handleError).toHaveBeenCalledWith(error);
@@ -515,12 +503,10 @@ describe('FormComponent', () => {
it('should apply readonly state when getting form by task id', (done) => {
spyOn(formService, 'getTask').and.returnValue(of({}));
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
return new Observable((observer) => {
observer.next({ taskId: taskId });
observer.complete();
});
});
spyOn(formService, 'getTaskForm').and.callFake((taskId) => new Observable((observer) => {
observer.next({ taskId });
observer.complete();
}));
formComponent.readOnly = true;
formComponent.getFormByTaskId('123').then((_) => {
@@ -531,12 +517,10 @@ describe('FormComponent', () => {
});
it('should fetch and parse form definition by id', () => {
spyOn(formService, 'getFormDefinitionById').and.callFake((currentFormId) => {
return new Observable((observer) => {
observer.next({ id: currentFormId });
observer.complete();
});
});
spyOn(formService, 'getFormDefinitionById').and.callFake((currentFormId) => new Observable((observer) => {
observer.next({ id: currentFormId });
observer.complete();
}));
const formId = 456;
let loaded = false;
@@ -561,19 +545,15 @@ describe('FormComponent', () => {
});
it('should fetch and parse form definition by form name', () => {
spyOn(formService, 'getFormDefinitionByName').and.callFake((currentFormName) => {
return new Observable((observer) => {
observer.next(currentFormName);
observer.complete();
});
});
spyOn(formService, 'getFormDefinitionByName').and.callFake((currentFormName) => new Observable((observer) => {
observer.next(currentFormName);
observer.complete();
}));
spyOn(formService, 'getFormDefinitionById').and.callFake((currentFormName) => {
return new Observable((observer) => {
observer.next({ name: currentFormName });
observer.complete();
});
});
spyOn(formService, 'getFormDefinitionById').and.callFake((currentFormName) => new Observable((observer) => {
observer.next({ name: currentFormName });
observer.complete();
}));
const formName = '<form>';
let loaded = false;
@@ -589,12 +569,10 @@ describe('FormComponent', () => {
});
it('should save task form and raise corresponding event', () => {
spyOn(formService, 'saveTaskForm').and.callFake(() => {
return new Observable((observer) => {
observer.next();
observer.complete();
});
});
spyOn(formService, 'saveTaskForm').and.callFake(() => new Observable((observer) => {
observer.next();
observer.complete();
}));
let saved = false;
let savedForm = null;
@@ -654,12 +632,10 @@ describe('FormComponent', () => {
});
it('should complete form and raise corresponding event', () => {
spyOn(formService, 'completeTaskForm').and.callFake(() => {
return new Observable((observer) => {
observer.next();
observer.complete();
});
});
spyOn(formService, 'completeTaskForm').and.callFake(() => new Observable((observer) => {
observer.next();
observer.complete();
}));
const outcome = 'complete';
let completed = false;
@@ -766,7 +742,7 @@ describe('FormComponent', () => {
const nodeId = '<id>';
const change = new SimpleChange(null, nodeId, false);
formComponent.ngOnChanges({ 'nodeId': change });
formComponent.ngOnChanges({ nodeId: change });
expect(nodeService.getNodeMetadata).toHaveBeenCalledWith(nodeId);
expect(formComponent.loadFormFromActiviti).toHaveBeenCalled();
@@ -987,7 +963,7 @@ describe('FormComponent', () => {
formValues.radio = { id: 'option_2', name: 'Option 2' };
const change = new SimpleChange(null, formValues, false);
formComponent.data = formValues;
formComponent.ngOnChanges({ 'data': change });
formComponent.ngOnChanges({ data: change });
formFields = formComponent.form.getFormFields();
dropdownField = formFields.find((field) => field.id === 'dropdownId');
@@ -1007,7 +983,7 @@ describe('FormComponent', () => {
formValues.radio = 'option_3';
const change = new SimpleChange(null, formValues, false);
formComponent.data = formValues;
formComponent.ngOnChanges({ 'data': change });
formComponent.ngOnChanges({ data: change });
formFields = formComponent.form.getFormFields();
radioFieldById = formFields.find((field) => field.id === 'radio');

View File

@@ -295,6 +295,7 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro
/**
* Get custom set of outcomes for a Form Definition.
*
* @param form Form definition model.
*/
getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] {
@@ -309,20 +310,6 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro
}
}
private refreshFormData() {
this.form = this.parseForm(this.form.json);
this.onFormLoaded(this.form);
this.onFormDataRefreshed(this.form);
}
private loadFormForEcmNode(nodeId: string): void {
this.nodeService.getNodeMetadata(nodeId).subscribe((data) => {
this.data = data.metadata;
this.loadFormFromActiviti(data.nodeType);
},
this.handleError);
}
loadFormFromActiviti(nodeType: string): any {
this.formService.searchFrom(nodeType).subscribe(
(form) => {
@@ -340,11 +327,6 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro
);
}
private loadFormFromFormId(formId: number) {
this.formId = formId;
this.loadForm();
}
protected storeFormAsMetadata() {
if (this.saveMetadata) {
this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe((type) => {
@@ -398,4 +380,23 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro
this.executeOutcome.emit(args);
return !args.defaultPrevented;
}
private refreshFormData() {
this.form = this.parseForm(this.form.json);
this.onFormLoaded(this.form);
this.onFormDataRefreshed(this.form);
}
private loadFormForEcmNode(nodeId: string): void {
this.nodeService.getNodeMetadata(nodeId).subscribe((data) => {
this.data = data.metadata;
this.loadFormFromActiviti(data.nodeType);
},
this.handleError);
}
private loadFormFromFormId(formId: number) {
this.formId = formId;
this.loadForm();
}
}

View File

@@ -34,10 +34,10 @@ describe('FormComponent UI and visibility', () => {
let service: FormService;
let fixture: ComponentFixture<FormComponent>;
function openSelect() {
const openSelect = () => {
const dropdown = fixture.debugElement.nativeElement.querySelector('.mat-select-trigger');
dropdown.click();
}
};
setupTestBed({
imports: [
@@ -64,7 +64,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).toBeDefined();
expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).not.toBeNull();
@@ -76,7 +76,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionRequiredField));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).toBeNull();
expect(fixture.debugElement.query(By.css('#adf-invalid-form-icon'))).toBeDefined();
@@ -88,7 +88,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
component.showValidationIcon = false;
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).toBeNull();
@@ -103,7 +103,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
const firstNameEl = fixture.debugElement.query(By.css('#firstname'));
@@ -120,7 +120,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionDropdownField));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -154,7 +154,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnNextOne));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
const firstEl = fixture.debugElement.query(By.css('#field-country-container'));
@@ -171,7 +171,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnPreviousOne));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
const firstEl = fixture.debugElement.query(By.css('#name'));
@@ -188,7 +188,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnNextOne));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
let firstEl = fixture.debugElement.query(By.css('#field-country-container'));
@@ -213,7 +213,7 @@ describe('FormComponent UI and visibility', () => {
spyOn(service, 'getTaskForm').and.returnValue(of(formReadonlyTwoTextFields));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
await fixture.whenStable();

View File

@@ -28,7 +28,7 @@ export class ProcessFormRenderingService extends FormRenderingService {
super();
this.register({
'upload': () => AttachFileWidgetComponent,
upload: () => AttachFileWidgetComponent,
'select-folder': () => AttachFolderWidgetComponent
}, true);
}

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
export let startFormDateWidgetMock = {
export const startFormDateWidgetMock = {
id: 4,
name: 'Claim Review Process',
processDefinitionId: 'ClaimReviewProcess:2: 93',
@@ -38,7 +38,7 @@ export let startFormDateWidgetMock = {
}]
};
export let startFormNumberWidgetMock = {
export const startFormNumberWidgetMock = {
id: 4,
name: 'Claim Review Process',
processDefinitionId: 'ClaimReviewProcess:2: 93',
@@ -61,7 +61,7 @@ export let startFormNumberWidgetMock = {
}]
};
export let startFormAmountWidgetMock = {
export const startFormAmountWidgetMock = {
id: 4,
name: 'Claim Review Process',
processDefinitionId: 'ClaimReviewProcess:2: 93',
@@ -84,7 +84,7 @@ export let startFormAmountWidgetMock = {
}]
};
export let startFormRadioButtonWidgetMock = {
export const startFormRadioButtonWidgetMock = {
id: 4,
name: 'Claim Review Process',
processDefinitionId: 'ClaimReviewProcess:2: 93',
@@ -107,7 +107,7 @@ export let startFormRadioButtonWidgetMock = {
}]
};
export let startFormTextDefinitionMock = {
export const startFormTextDefinitionMock = {
id: 4,
name: 'Claim Review Process',
processDefinitionId: 'ClaimReviewProcess:2: 93',
@@ -130,7 +130,7 @@ export let startFormTextDefinitionMock = {
}]
};
export let startFormDropdownDefinitionMock = {
export const startFormDropdownDefinitionMock = {
id: 4,
name: 'Claim Review Process',
processDefinitionId: 'ClaimReviewProcess:2: 93',
@@ -179,7 +179,7 @@ export let startFormDropdownDefinitionMock = {
}]
};
export let startMockForm = {
export const startMockForm = {
id: 4,
name: 'Claim Review Process',
processDefinitionId: 'ClaimReviewProcess:2: 93',
@@ -593,7 +593,7 @@ export let startMockForm = {
globalDateFormat: 'D - M - YYYY'
};
export let startMockFormWithTab = {
export const startMockFormWithTab = {
id: 4,
taskName: 'Mock Title',
processDefinitionId: 'ClaimReviewProcess:2: 93',
@@ -1056,7 +1056,7 @@ export const taskFormSingleUploadMock = {
visibilityCondition: null,
numberOfColumns: 2,
fields: {
'1': [
1: [
{
fieldType: 'AttachFileFieldRepresentation',
id: 'fake-single-upload',
@@ -1138,7 +1138,7 @@ export const taskFormMultipleUploadMock = {
visibilityCondition: null,
numberOfColumns: 2,
fields: {
'1': [
1: [
{
fieldType: 'AttachFileFieldRepresentation',
id: 'fake-multiple-upload',

View File

@@ -60,12 +60,8 @@ describe('StartFormComponent', () => {
processDefinitionName: 'my:process'
}));
spyOn(translate, 'instant').and.callFake((key) => {
return key;
});
spyOn(translate, 'get').and.callFake((key) => {
return of(key);
});
spyOn(translate, 'instant').and.callFake((key) => key);
spyOn(translate, 'get').and.callFake((key) => of(key));
});
afterEach(() => {

View File

@@ -17,7 +17,7 @@
import { AppDefinitionRepresentationModel } from '../task-list';
export let nonDeployedApps = [new AppDefinitionRepresentationModel({
export const nonDeployedApps = [new AppDefinitionRepresentationModel({
id: '1',
name: '1',
icon: 'icon1'
@@ -30,7 +30,7 @@ export let nonDeployedApps = [new AppDefinitionRepresentationModel({
name: '3',
icon: 'icon3'
})];
export let deployedApps = [new AppDefinitionRepresentationModel({
export const deployedApps = [new AppDefinitionRepresentationModel({
id: 1,
name: 'App1',
icon: 'icon1',
@@ -74,6 +74,6 @@ export let deployedApps = [new AppDefinitionRepresentationModel({
tenantId: 9,
modelId: 66
})];
export let defaultApp = [new AppDefinitionRepresentationModel({
export const defaultApp = [new AppDefinitionRepresentationModel({
defaultAppId: 'tasks'
})];

View File

@@ -17,7 +17,7 @@
import { CommentModel } from '@alfresco/adf-core';
export let mockProcessInstanceComments = [
export const mockProcessInstanceComments = [
new CommentModel({ message: 'Test1', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} }),
new CommentModel({ message: 'Test2', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} }),
new CommentModel({ message: 'Test3', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} })

View File

@@ -17,7 +17,7 @@
import { FilterProcessRepresentationModel } from '../../process-list/models/filter-process.model';
export let fakeProcessFilters = [
export const fakeProcessFilters = [
new FilterProcessRepresentationModel({
id: 10,
name: 'FakeCompleted',
@@ -38,14 +38,14 @@ export let fakeProcessFilters = [
})
];
export let fakeProcessFiltersResponse = {
export const fakeProcessFiltersResponse = {
size: 1, total: 1, start: 0,
data: [new FilterProcessRepresentationModel({
'name': 'Running',
'appId': '22',
'id': 333,
'recent': true,
'icon': 'glyphicon-random',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'running' }
name: 'Running',
appId: '22',
id: 333,
recent: true,
icon: 'glyphicon-random',
filter: { sort: 'created-desc', name: '', state: 'running' }
})]
};

View File

@@ -17,7 +17,7 @@
import { ProcessListModel } from '../../process-list/models/process-list.model';
export let fakeProcessInstance = new ProcessListModel({
export const fakeProcessInstance = new ProcessListModel({
size: 2,
total: 2,
start: 0,
@@ -85,7 +85,7 @@ export let fakeProcessInstance = new ProcessListModel({
]
});
export let fakeProcessInstancesWithNoName = {
export const fakeProcessInstancesWithNoName = {
size: 2,
total: 2,
start: 0,
@@ -125,14 +125,14 @@ export let fakeProcessInstancesWithNoName = {
]
};
export let fakeProcessInstancesEmpty = new ProcessListModel({
export const fakeProcessInstancesEmpty = new ProcessListModel({
size: 0,
total: 0,
start: 0,
data: []
});
export let fakeProcessCustomSchema = [
export const fakeProcessCustomSchema = [
{
key: 'fakeName',
type: 'text',
@@ -147,7 +147,7 @@ export let fakeProcessCustomSchema = [
}
];
export let fakeProcessColumnSchema = {
export const fakeProcessColumnSchema = {
default: [
{
key: 'default-name',

View File

@@ -34,13 +34,13 @@ export class SingleProcessList extends ProcessList {
constructor(name?: string) {
const instance = new ProcessInstance({
id: '123',
name: name
name
});
super([instance]);
}
}
export let exampleProcess = new ProcessInstance({
export const exampleProcess = new ProcessInstance({
id: '123',
name: 'Process 123',
started: '2016-11-10T03:37:30.010+0000',
@@ -52,7 +52,7 @@ export let exampleProcess = new ProcessInstance({
}
});
export let processEnded = new ProcessInstance({
export const processEnded = new ProcessInstance({
id: '123',
name: 'Process 123',
started: '2016-11-10T03:37:30.010+0000',
@@ -65,7 +65,7 @@ export let processEnded = new ProcessInstance({
ended: '2016-11-11T03:37:30.010+0000'
});
export let mockRunningProcess = new ProcessInstance({
export const mockRunningProcess = new ProcessInstance({
id: '123',
name: 'Process 123',
started: '2016-11-10T03:37:30.010+0000',
@@ -78,7 +78,7 @@ export let mockRunningProcess = new ProcessInstance({
ended: null
});
export let exampleProcessNoName = new ProcessInstance({
export const exampleProcessNoName = new ProcessInstance({
id: '123',
name: null,
started: '2016-11-10T03:37:30.010+0000',
@@ -91,7 +91,7 @@ export let exampleProcessNoName = new ProcessInstance({
processDefinitionName: 'My Process'
});
export let fakeProcessInstances = {
export const fakeProcessInstances = {
size: 2,
total: 2,
start: 0,

View File

@@ -18,12 +18,12 @@
import { AppDefinitionRepresentationModel, TaskDetailsModel } from '../../task-list';
import { ProcessDefinitionRepresentation } from '../../process-list/models/process-definition.model';
export let mockError = {
export const mockError = {
message: null,
messageKey: 'GENERAL.ERROR.FORBIDDEN'
};
export let fakeApp1 = new AppDefinitionRepresentationModel({
export const fakeApp1 = new AppDefinitionRepresentationModel({
deploymentId: 26,
name: 'HR processes',
icon: 'glyphicon-cloud',
@@ -33,7 +33,7 @@ export let fakeApp1 = new AppDefinitionRepresentationModel({
id: 1
});
export let fakeApp2 = new AppDefinitionRepresentationModel({
export const fakeApp2 = new AppDefinitionRepresentationModel({
deploymentId: 2501,
name: 'Sales onboarding',
icon: 'glyphicon-asterisk',
@@ -43,7 +43,7 @@ export let fakeApp2 = new AppDefinitionRepresentationModel({
id: 1000
});
export let fakeTasksList = {
export const fakeTasksList = {
data: [new TaskDetailsModel({
id: 1,
name: 'Task 1',
@@ -57,7 +57,7 @@ export let fakeTasksList = {
})]
};
export let fakeProcessDef = new ProcessDefinitionRepresentation({
export const fakeProcessDef = new ProcessDefinitionRepresentation({
id: '32323',
key: 'blah',
name: 'Process 1'

View File

@@ -18,24 +18,24 @@
import { ProcessDefinitionRepresentation } from '../../process-list/models/process-definition.model';
import { ProcessInstance } from '../../process-list/models/process-instance.model';
export let newProcess = new ProcessInstance({
export const newProcess = new ProcessInstance({
id: '32323',
name: 'Process'
});
export let testProcessDef = new ProcessDefinitionRepresentation({
export const testProcessDef = new ProcessDefinitionRepresentation({
id: 'my:process1',
name: 'My Process 1',
hasStartForm: false
});
export let testProcessDefinitions = [new ProcessDefinitionRepresentation({
export const testProcessDefinitions = [new ProcessDefinitionRepresentation({
id: 'my:process1',
name: 'My Process 1',
hasStartForm: false
})];
export let testMultipleProcessDefs = [new ProcessDefinitionRepresentation({
export const testMultipleProcessDefs = [new ProcessDefinitionRepresentation({
id: 'my:process1',
name: 'My Process 1',
hasStartForm: false
@@ -45,7 +45,7 @@ export let testMultipleProcessDefs = [new ProcessDefinitionRepresentation({
hasStartForm: true
})];
export let testProcessDefWithForm = [new ProcessDefinitionRepresentation({
export const testProcessDefWithForm = [new ProcessDefinitionRepresentation({
id: 'my:process1',
name: 'My Process 1',
hasStartForm: true

View File

@@ -15,20 +15,11 @@
* limitations under the License.
*/
export let startTaskMock = {
'name': 'fakeName',
'description': 'fakeDescription',
'assignee': null,
'dueDate': '2017-11-03T15:25:42.749+0000',
'formKey': null,
'category': 'fakeAppId'
export const startTaskMock = {
name: 'fakeName',
description: 'fakeDescription',
assignee: null,
dueDate: '2017-11-03T15:25:42.749+0000',
formKey: null,
category: 'fakeAppId'
};
//
// export let noDataMock = {
// 'name': '',
// 'description': '',
// 'assignee': {},
// 'dueDate': '',
// 'formKey': '',
// 'category': ';'
// };

View File

@@ -15,6 +15,6 @@
* limitations under the License.
*/
export let mockTaskDetailsComponent = {
export const mockTaskDetailsComponent = {
noTaskDetailsTemplateComponent: null
};

View File

@@ -18,7 +18,7 @@
import { UserRepresentation } from '@alfresco/js-api';
import { TaskDetailsModel } from '../../task-list/models/task-details.model';
export let standaloneTaskWithForm = new TaskDetailsModel({
export const standaloneTaskWithForm = new TaskDetailsModel({
id: '100',
name: 'Standalone Task With Form',
description: null,
@@ -58,7 +58,7 @@ export let standaloneTaskWithForm = new TaskDetailsModel({
memberOfCandidateGroup: false
});
export let standaloneTaskWithoutForm = new TaskDetailsModel({
export const standaloneTaskWithoutForm = new TaskDetailsModel({
id: '200',
name: 'Standalone Task Without Form',
description: null,
@@ -98,7 +98,7 @@ export let standaloneTaskWithoutForm = new TaskDetailsModel({
memberOfCandidateGroup: false
});
export let completedStandaloneTaskWithoutForm = new TaskDetailsModel({
export const completedStandaloneTaskWithoutForm = new TaskDetailsModel({
id: '200',
name: 'Standalone Task Without Form',
description: null,
@@ -138,7 +138,7 @@ export let completedStandaloneTaskWithoutForm = new TaskDetailsModel({
memberOfCandidateGroup: false
});
export let taskDetailsMock = new TaskDetailsModel({
export const taskDetailsMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -178,7 +178,7 @@ export let taskDetailsMock = new TaskDetailsModel({
memberOfCandidateGroup: false
});
export let initiatorCanCompleteTaskDetailsMock = new TaskDetailsModel({
export const initiatorCanCompleteTaskDetailsMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -213,7 +213,7 @@ export let initiatorCanCompleteTaskDetailsMock = new TaskDetailsModel({
memberOfCandidateGroup: false
});
export let initiatorWithCandidatesTaskDetailsMock = new TaskDetailsModel({
export const initiatorWithCandidatesTaskDetailsMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -261,7 +261,7 @@ export let initiatorWithCandidatesTaskDetailsMock = new TaskDetailsModel({
memberOfCandidateGroup: true
});
export let taskDetailsWithOutAssigneeMock = new TaskDetailsModel({
export const taskDetailsWithOutAssigneeMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -296,7 +296,7 @@ export let taskDetailsWithOutAssigneeMock = new TaskDetailsModel({
memberOfCandidateGroup: false
});
export let claimableTaskDetailsMock = new TaskDetailsModel({
export const claimableTaskDetailsMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -336,7 +336,7 @@ export let claimableTaskDetailsMock = new TaskDetailsModel({
memberOfCandidateUsers: false
});
export let claimedTaskDetailsMock = new TaskDetailsModel({
export const claimedTaskDetailsMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -389,7 +389,7 @@ export let claimedTaskDetailsMock = new TaskDetailsModel({
memberOfCandidateUsers: true
});
export let claimedByGroupMemberMock = new TaskDetailsModel({
export const claimedByGroupMemberMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -439,7 +439,7 @@ export let claimedByGroupMemberMock = new TaskDetailsModel({
memberOfCandidateUsers: true
});
export let taskDetailsWithOutCandidateGroup = new TaskDetailsModel({
export const taskDetailsWithOutCandidateGroup = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -481,7 +481,7 @@ export let taskDetailsWithOutCandidateGroup = new TaskDetailsModel({
]
});
export let completedTaskWithFormMock = new TaskDetailsModel({
export const completedTaskWithFormMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -511,7 +511,7 @@ export let completedTaskWithFormMock = new TaskDetailsModel({
memberOfCandidateUsers: false
});
export let completedTaskDetailsMock = new TaskDetailsModel({
export const completedTaskDetailsMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: null,
@@ -541,38 +541,38 @@ export let completedTaskDetailsMock = new TaskDetailsModel({
memberOfCandidateUsers: false
});
export let taskDetailsWithOutFormMock = new TaskDetailsModel({
'id': '91',
'name': 'Request translation',
'description': 'fake description',
'category': null,
'assignee': {'id': 1001, 'firstName': 'Admin', 'lastName': 'Paul', 'email': 'fake-email@gmail.com' },
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': '2016-11-03T15:25:42.749+0000',
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '86',
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'processDefinitionDescription': null,
'processDefinitionKey': 'TranslationProcess',
'processDefinitionCategory': 'http://www.activiti.org/processdef',
'processDefinitionVersion': 2,
'processDefinitionDeploymentId': '5',
'formKey': null,
'processInstanceStartUserId': '1001',
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
'executionId': '86',
'involvedPeople': [],
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false,
'memberOfCandidateGroup': false
export const taskDetailsWithOutFormMock = new TaskDetailsModel({
id: '91',
name: 'Request translation',
description: 'fake description',
category: null,
assignee: {id: 1001, firstName: 'Admin', lastName: 'Paul', email: 'fake-email@gmail.com' },
created: '2016-11-03T15:25:42.749+0000',
dueDate: '2016-11-03T15:25:42.749+0000',
endDate: null,
duration: null,
priority: 50,
parentTaskId: null,
parentTaskName: null,
processInstanceId: '86',
processInstanceName: null,
processDefinitionId: 'TranslationProcess:2:8',
processDefinitionName: 'Translation Process',
processDefinitionDescription: null,
processDefinitionKey: 'TranslationProcess',
processDefinitionCategory: 'http://www.activiti.org/processdef',
processDefinitionVersion: 2,
processDefinitionDeploymentId: '5',
formKey: null,
processInstanceStartUserId: '1001',
initiatorCanCompleteTask: false,
adhocTaskCanBeReassigned: false,
taskDefinitionKey: 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
executionId: '86',
involvedPeople: [],
memberOfCandidateUsers: false,
managerOfCandidateGroup: false,
memberOfCandidateGroup: false
});
export const taskFormMock = {
@@ -619,7 +619,7 @@ export const taskFormMock = {
visibilityCondition: null,
numberOfColumns: 2,
fields: {
'1': [
1: [
{
fieldType: 'FormFieldRepresentation',
id: 'text1',
@@ -655,7 +655,7 @@ export const taskFormMock = {
visibilityCondition: null
}
],
'2': [
2: [
{
fieldType: 'FormFieldRepresentation',
id: 'text2',
@@ -727,7 +727,7 @@ export const taskFormMock = {
visibilityCondition: null,
numberOfColumns: 2,
fields: {
'1': [
1: [
{
fieldType: 'FormFieldRepresentation',
id: 'text3',
@@ -773,7 +773,7 @@ export const taskFormMock = {
}
}
],
'2': [
2: [
{
fieldType: 'FormFieldRepresentation',
id: 'numberField',
@@ -831,9 +831,9 @@ export const taskFormMock = {
globalDateFormat: 'D-M-YYYY'
};
export let tasksMock = [new TaskDetailsModel(taskDetailsMock)];
export const tasksMock = [new TaskDetailsModel(taskDetailsMock)];
export let noDataMock = [
export const noDataMock = [
new TaskDetailsModel({
id: 1005,
message: 'example-message',

View File

@@ -15,9 +15,9 @@
* limitations under the License.
*/
import { FilterRepresentationModel } from '../../task-list/models/filter.model';
import { FilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../../task-list/models/filter.model';
export let fakeFiltersResponse: any = {
export const fakeFiltersResponse: any = {
size: 2, total: 2, start: 0,
data: [
{
@@ -31,7 +31,7 @@ export let fakeFiltersResponse: any = {
]
};
export let fakeTaskFilters = [
export const fakeTaskFilters = [
new FilterRepresentationModel({
name: 'FakeInvolvedTasks',
icon: 'glyphicon-align-left',
@@ -52,7 +52,7 @@ export let fakeTaskFilters = [
})
];
export let fakeAppFilter = {
export const fakeAppFilter = {
size: 1, total: 1, start: 0,
data: [
{
@@ -62,11 +62,14 @@ export let fakeAppFilter = {
]
};
export let fakeFilter = {
sort: 'created-desc', text: '', state: 'open', assignment: 'fake-assignee'
export const fakeFilter: TaskQueryRequestRepresentationModel = {
sort: 'created-desc',
text: '',
state: 'open',
assignment: 'fake-assignee'
};
export let fakeRepresentationFilter1: FilterRepresentationModel = new FilterRepresentationModel({
export const fakeRepresentationFilter1: FilterRepresentationModel = new FilterRepresentationModel({
appId: 1,
name: 'CONTAIN FILTER',
recent: true,
@@ -83,7 +86,7 @@ export let fakeRepresentationFilter1: FilterRepresentationModel = new FilterRepr
}
});
export let fakeRepresentationFilter2: FilterRepresentationModel = new FilterRepresentationModel({
export const fakeRepresentationFilter2: FilterRepresentationModel = new FilterRepresentationModel({
appId: 2,
name: 'NO TASK FILTER',
recent: false,

View File

@@ -78,7 +78,7 @@ export const fakeGlobalTask = new TaskListModel({
]
});
export let fakeCustomSchema = [
export const fakeCustomSchema = [
{
key: 'fakeName',
type: 'text',
@@ -93,7 +93,7 @@ export let fakeCustomSchema = [
}
];
export let fakeColumnSchema = {
export const fakeColumnSchema = {
default: [
{
key: 'default-name',
@@ -119,7 +119,7 @@ export let fakeColumnSchema = {
fakeCustomSchema
};
export let fakeEmptyTask = {
export const fakeEmptyTask = {
size: 0,
start: 0,
total: 0,
@@ -127,163 +127,163 @@ export let fakeEmptyTask = {
};
export const paginatedTask = new TaskListModel({
'size': 5,
'total': 9,
'start': 0,
'data': [{
'id': '69211',
'name': 'My Task Name',
'description': '',
'category': null,
'assignee': {'id': 1493, 'firstName': 'fake name', 'lastName': 'fake', 'email': 'abc@test.com'},
'created': '2020-02-06T18:41:21.587+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': null,
'processInstanceName': null,
'processDefinitionId': null,
'processDefinitionName': null,
'processDefinitionDescription': null,
'processDefinitionKey': null,
'processDefinitionCategory': null,
'processDefinitionVersion': 0,
'processDefinitionDeploymentId': null,
'formKey': null,
'processInstanceStartUserId': null,
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': null,
'executionId': null,
'memberOfCandidateGroup': false,
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false
size: 5,
total: 9,
start: 0,
data: [{
id: '69211',
name: 'My Task Name',
description: '',
category: null,
assignee: {id: 1493, firstName: 'fake name', lastName: 'fake', email: 'abc@test.com'},
created: '2020-02-06T18:41:21.587+0000',
dueDate: null,
endDate: null,
duration: null,
priority: 50,
parentTaskId: null,
parentTaskName: null,
processInstanceId: null,
processInstanceName: null,
processDefinitionId: null,
processDefinitionName: null,
processDefinitionDescription: null,
processDefinitionKey: null,
processDefinitionCategory: null,
processDefinitionVersion: 0,
processDefinitionDeploymentId: null,
formKey: null,
processInstanceStartUserId: null,
initiatorCanCompleteTask: false,
adhocTaskCanBeReassigned: false,
taskDefinitionKey: null,
executionId: null,
memberOfCandidateGroup: false,
memberOfCandidateUsers: false,
managerOfCandidateGroup: false
}, {
'id': '61054',
'name': null,
'description': null,
'category': null,
'assignee': {'id': 19, 'firstName': 'Mm9ntWGB', 'lastName': 'jfQOzSDL', 'email': 'c4jly@activiti.test.com'},
'created': '2020-02-06T15:26:32.488+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '61049',
'processInstanceName': null,
'processDefinitionId': 'upload:1:50118',
'processDefinitionName': 'upload',
'processDefinitionDescription': null,
'processDefinitionKey': 'upload',
'processDefinitionCategory': 'http://www.activiti.org/processdef',
'processDefinitionVersion': 1,
'processDefinitionDeploymentId': '50115',
'formKey': '8474',
'processInstanceStartUserId': null,
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': 'sid-7A12380E-28F8-4B15-9326-C5CFB8DD5BBC',
'executionId': '61049',
'memberOfCandidateGroup': false,
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false
id: '61054',
name: null,
description: null,
category: null,
assignee: {id: 19, firstName: 'Mm9ntWGB', lastName: 'jfQOzSDL', email: 'c4jly@activiti.test.com'},
created: '2020-02-06T15:26:32.488+0000',
dueDate: null,
endDate: null,
duration: null,
priority: 50,
parentTaskId: null,
parentTaskName: null,
processInstanceId: '61049',
processInstanceName: null,
processDefinitionId: 'upload:1:50118',
processDefinitionName: 'upload',
processDefinitionDescription: null,
processDefinitionKey: 'upload',
processDefinitionCategory: 'http://www.activiti.org/processdef',
processDefinitionVersion: 1,
processDefinitionDeploymentId: '50115',
formKey: '8474',
processInstanceStartUserId: null,
initiatorCanCompleteTask: false,
adhocTaskCanBeReassigned: false,
taskDefinitionKey: 'sid-7A12380E-28F8-4B15-9326-C5CFB8DD5BBC',
executionId: '61049',
memberOfCandidateGroup: false,
memberOfCandidateUsers: false,
managerOfCandidateGroup: false
}, {
'id': '61048',
'name': 'My Task Name',
'description': null,
'category': null,
'assignee': {'id': 1493, 'firstName': 'fake name', 'lastName': 'fake', 'email': 'abc@test.com'},
'created': '2020-02-06T15:26:03.012+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': null,
'processInstanceName': null,
'processDefinitionId': null,
'processDefinitionName': null,
'processDefinitionDescription': null,
'processDefinitionKey': null,
'processDefinitionCategory': null,
'processDefinitionVersion': 0,
'processDefinitionDeploymentId': null,
'formKey': null,
'processInstanceStartUserId': null,
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': null,
'executionId': null,
'memberOfCandidateGroup': false,
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false
id: '61048',
name: 'My Task Name',
description: null,
category: null,
assignee: {id: 1493, firstName: 'fake name', lastName: 'fake', email: 'abc@test.com'},
created: '2020-02-06T15:26:03.012+0000',
dueDate: null,
endDate: null,
duration: null,
priority: 50,
parentTaskId: null,
parentTaskName: null,
processInstanceId: null,
processInstanceName: null,
processDefinitionId: null,
processDefinitionName: null,
processDefinitionDescription: null,
processDefinitionKey: null,
processDefinitionCategory: null,
processDefinitionVersion: 0,
processDefinitionDeploymentId: null,
formKey: null,
processInstanceStartUserId: null,
initiatorCanCompleteTask: false,
adhocTaskCanBeReassigned: false,
taskDefinitionKey: null,
executionId: null,
memberOfCandidateGroup: false,
memberOfCandidateUsers: false,
managerOfCandidateGroup: false
}, {
'id': '54705',
'name': 'My Task Name',
'description': '',
'category': '1349',
'assignee': {'id': 1493, 'firstName': 'fake name', 'lastName': 'fake', 'email': 'abc@test.com'},
'created': '2020-02-06T13:01:23.403+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': null,
'processInstanceName': null,
'processDefinitionId': null,
'processDefinitionName': null,
'processDefinitionDescription': null,
'processDefinitionKey': null,
'processDefinitionCategory': null,
'processDefinitionVersion': 0,
'processDefinitionDeploymentId': null,
'formKey': null,
'processInstanceStartUserId': null,
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': null,
'executionId': null,
'memberOfCandidateGroup': false,
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false
id: '54705',
name: 'My Task Name',
description: '',
category: '1349',
assignee: {id: 1493, firstName: 'fake name', lastName: 'fake', email: 'abc@test.com'},
created: '2020-02-06T13:01:23.403+0000',
dueDate: null,
endDate: null,
duration: null,
priority: 50,
parentTaskId: null,
parentTaskName: null,
processInstanceId: null,
processInstanceName: null,
processDefinitionId: null,
processDefinitionName: null,
processDefinitionDescription: null,
processDefinitionKey: null,
processDefinitionCategory: null,
processDefinitionVersion: 0,
processDefinitionDeploymentId: null,
formKey: null,
processInstanceStartUserId: null,
initiatorCanCompleteTask: false,
adhocTaskCanBeReassigned: false,
taskDefinitionKey: null,
executionId: null,
memberOfCandidateGroup: false,
memberOfCandidateUsers: false,
managerOfCandidateGroup: false
}, {
'id': '50158',
'name': 'My Task Name',
'description': '',
'category': '1349',
'assignee': {'id': 1493, 'firstName': 'fake name', 'lastName': 'fake', 'email': 'abc@test.com'},
'created': '2020-02-06T09:13:55.532+0000',
'dueDate': '2019-01-09T11:53:00.000+0000',
'endDate': null,
'duration': null,
'priority': 0,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': null,
'processInstanceName': null,
'processDefinitionId': null,
'processDefinitionName': null,
'processDefinitionDescription': null,
'processDefinitionKey': null,
'processDefinitionCategory': null,
'processDefinitionVersion': 0,
'processDefinitionDeploymentId': null,
'formKey': '8484',
'processInstanceStartUserId': null,
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': null,
'executionId': null,
'memberOfCandidateGroup': false,
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false
id: '50158',
name: 'My Task Name',
description: '',
category: '1349',
assignee: {id: 1493, firstName: 'fake name', lastName: 'fake', email: 'abc@test.com'},
created: '2020-02-06T09:13:55.532+0000',
dueDate: '2019-01-09T11:53:00.000+0000',
endDate: null,
duration: null,
priority: 0,
parentTaskId: null,
parentTaskName: null,
processInstanceId: null,
processInstanceName: null,
processDefinitionId: null,
processDefinitionName: null,
processDefinitionDescription: null,
processDefinitionKey: null,
processDefinitionCategory: null,
processDefinitionVersion: 0,
processDefinitionDeploymentId: null,
formKey: '8484',
processInstanceStartUserId: null,
initiatorCanCompleteTask: false,
adhocTaskCanBeReassigned: false,
taskDefinitionKey: null,
executionId: null,
memberOfCandidateGroup: false,
memberOfCandidateUsers: false,
managerOfCandidateGroup: false
}]
});

View File

@@ -18,25 +18,25 @@
import { TaskListModel } from '../../task-list/models/task-list.model';
import { fakeAppFilter } from './task-filters.mock';
export let fakeApps = {
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
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
theme: 'theme-2-fake', icon: 'glyphicon-asterisk', deploymentId: '444', tenantId: null
}
]
};
export let fakeUser1 = { id: 1, email: 'fake-email@dom.com', firstName: 'firstName', lastName: 'lastName' };
export const fakeUser1 = { id: 1, email: 'fake-email@dom.com', firstName: 'firstName', lastName: 'lastName' };
export let fakeUser2 = { id: 1001, email: 'some-one@somegroup.com', firstName: 'some', lastName: 'one' };
export const fakeUser2 = { id: 1001, email: 'some-one@somegroup.com', firstName: 'some', lastName: 'one' };
export let fakeTaskList = new TaskListModel({
export const fakeTaskList = new TaskListModel({
size: 1, total: 1, start: 0,
data: [
{
@@ -47,7 +47,7 @@ export let fakeTaskList = new TaskListModel({
]
});
export let fakeTaskListDifferentProcessDefinitionKey = {
export const fakeTaskListDifferentProcessDefinitionKey = {
size: 2, total: 1, start: 0,
data: [
{
@@ -65,7 +65,7 @@ export let fakeTaskListDifferentProcessDefinitionKey = {
]
};
export let secondFakeTaskList = {
export const secondFakeTaskList = {
size: 1, total: 1, start: 0,
data: [
{
@@ -76,13 +76,13 @@ export let secondFakeTaskList = {
]
};
export let mockErrorTaskList = {
export const mockErrorTaskList = {
error: 'wrong request'
};
export let fakeTaskDetails = { id: '999', name: 'fake-task-name', formKey: '99', assignee: fakeUser1 };
export const fakeTaskDetails = { id: '999', name: 'fake-task-name', formKey: '99', assignee: fakeUser1 };
export let fakeTasksComment = {
export const fakeTasksComment = {
size: 2, total: 2, start: 0,
data: [
{
@@ -94,7 +94,7 @@ export let fakeTasksComment = {
]
};
export let fakeTasksChecklist = {
export const fakeTasksChecklist = {
size: 1, total: 1, start: 0,
data: [
{
@@ -110,11 +110,11 @@ export let fakeTasksChecklist = {
]
};
export let fakeAppPromise = new Promise(function (resolve) {
export const fakeAppPromise = new Promise((resolve) => {
resolve(fakeAppFilter);
});
export let fakeFormList = {
export const fakeFormList = {
size: 2,
total: 2,
start: 0,
@@ -157,7 +157,7 @@ export let fakeFormList = {
}]
};
export let fakeTaskOpen1 = {
export const fakeTaskOpen1 = {
id: '1', name: 'FakeOpenTask1', description: null, category: null,
assignee: fakeUser1,
created: '2017-07-15T11:19:17.440+0000',
@@ -165,7 +165,7 @@ export let fakeTaskOpen1 = {
endDate: null
};
export let fakeTaskOpen2 = {
export const fakeTaskOpen2 = {
id: '1', name: 'FakeOpenTask2', description: null, category: null,
assignee: { id: 1, email: 'fake-open-email@dom.com', firstName: 'firstName', lastName: 'lastName' },
created: '2017-07-15T11:19:17.440+0000',
@@ -173,7 +173,7 @@ export let fakeTaskOpen2 = {
endDate: null
};
export let fakeTaskCompleted1 = {
export const fakeTaskCompleted1 = {
id: '1', name: 'FakeCompletedTaskName1', description: null, category: null,
assignee: { id: 1, email: 'fake-completed-email@dom.com', firstName: 'firstName', lastName: 'lastName' },
created: '2016-07-15T11:19:17.440+0000',
@@ -181,7 +181,7 @@ export let fakeTaskCompleted1 = {
endDate: '2016-11-03T15:25:42.749+0000'
};
export let fakeTaskCompleted2 = {
export const fakeTaskCompleted2 = {
id: '1', name: 'FakeCompletedTaskName2', description: null, category: null,
assignee: fakeUser1,
created: null,
@@ -189,14 +189,14 @@ export let fakeTaskCompleted2 = {
endDate: '2016-11-03T15:25:42.749+0000'
};
export let fakeOpenTaskList = new TaskListModel({
export const fakeOpenTaskList = new TaskListModel({
size: 2,
total: 2,
start: 0,
data: [fakeTaskOpen1, fakeTaskOpen2]
});
export let fakeCompletedTaskList = new TaskListModel({
export const fakeCompletedTaskList = new TaskListModel({
size: 2,
total: 2,
start: 0,

View File

@@ -27,7 +27,7 @@ import { getDisplayUser } from '../../helpers/get-display-user';
selector: 'adf-people-search-field',
templateUrl: './people-search-field.component.html',
styleUrls: ['./people-search-field.component.scss'],
host: { 'class': 'adf-people-search-field' },
host: { class: 'adf-people-search-field' },
encapsulation: ViewEncapsulation.None
})

View File

@@ -102,7 +102,7 @@ describe('PeopleSearchComponent', () => {
fixture.whenStable()
.then(() => {
peopleSearchComponent.onRowClick(fakeUser);
const addUserButton = <HTMLElement> element.querySelector('#add-people');
const addUserButton = element.querySelector<HTMLElement>('#add-people');
addUserButton.click();
});
});
@@ -118,7 +118,7 @@ describe('PeopleSearchComponent', () => {
fixture.detectChanges();
peopleSearchComponent.onRowClick(fakeUser);
const addUserButton = <HTMLElement> element.querySelector('#add-people');
const addUserButton = element.querySelector<HTMLElement>('#add-people');
addUserButton.click();
fixture.detectChanges();

View File

@@ -26,7 +26,7 @@ import { map } from 'rxjs/operators';
templateUrl: './people-search.component.html',
styleUrls: ['./people-search.component.scss'],
host: {
'class': 'adf-people-search'
class: 'adf-people-search'
},
encapsulation: ViewEncapsulation.None
})
@@ -53,23 +53,14 @@ export class PeopleSearchComponent implements OnInit {
selectedUser: UserProcessModel = {};
performSearch: PerformSearchCallback;
constructor() {}
ngOnInit() {
this.filteredResults$ = this.results
.pipe(
map((users) => {
return users.filter((user) => user.id !== this.selectedUser.id);
})
map((users) => users.filter((user) => user.id !== this.selectedUser.id))
);
this.performSearch = this.performSearchCallback.bind(this);
}
private performSearchCallback(event: any): Observable<UserProcessModel[]> {
this.searchPeople.emit(event);
return this.filteredResults$;
}
onRowClick(user: UserProcessModel) {
this.selectedUser = user;
}
@@ -89,4 +80,9 @@ export class PeopleSearchComponent implements OnInit {
}
this.success.emit(this.selectedUser);
}
private performSearchCallback(event: any): Observable<UserProcessModel[]> {
this.searchPeople.emit(event);
return this.filteredResults$;
}
}

View File

@@ -29,7 +29,7 @@ const DEFAULT_ASSIGNEE_PLACEHOLDER = 'ADF_TASK_LIST.PEOPLE.ASSIGNEE';
selector: 'adf-people-selector',
templateUrl: './people-selector.component.html',
styleUrls: ['./people-selector.component.scss'],
host: { 'class': 'adf-people-selector' },
host: { class: 'adf-people-selector' },
encapsulation: ViewEncapsulation.None
})
@@ -66,11 +66,6 @@ export class PeopleSelectorComponent {
);
}
private onSearchUserError(): Observable<UserProcessModel[]> {
this.logService.error('getWorkflowUsers threw error');
return of([]);
}
userSelected(user: UserProcessModel): void {
this.updateUserSelection(user);
}
@@ -79,6 +74,11 @@ export class PeopleSelectorComponent {
this.updateUserSelection(undefined);
}
private onSearchUserError(): Observable<UserProcessModel[]> {
this.logService.error('getWorkflowUsers threw error');
return of([]);
}
private updateUserSelection(user: UserProcessModel): void {
this.selectedUser = user;
this.peopleIdChange.emit(user && user.id || undefined);

View File

@@ -46,9 +46,9 @@ export class PeopleComponent {
peopleSearch: PeopleSearchComponent;
showAssignment: boolean = false;
peopleSearch$: Observable<UserProcessModel[]>;
private peopleSearchObserver: Observer<UserProcessModel[]>;
peopleSearch$: Observable<UserProcessModel[]>;
constructor(private logService: LogService, public peopleProcessService: PeopleProcessService) {
this.peopleSearch$ = new Observable<UserProcessModel[]>((observer) => this.peopleSearchObserver = observer)

View File

@@ -15,8 +15,8 @@
* limitations under the License.
*/
export function getDisplayUser(firstName: string, lastName: string, delimiter: string = '-'): string {
export const getDisplayUser = (firstName: string, lastName: string, delimiter: string = '-'): string => {
firstName = (firstName !== null ? firstName : '');
lastName = (lastName !== null ? lastName : '');
return firstName + delimiter + lastName;
}
};

View File

@@ -20,28 +20,28 @@ import moment from 'moment-es6';
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 {
static DATE_TIME_IDENTIFIER_REG_EXP = new RegExp('%{datetime}', 'i');
static PROCESS_DEFINITION_IDENTIFIER_REG_EXP = new RegExp('%{processdefinition}', 'i');
constructor(private localizedDatePipe: LocalizedDatePipe) {
}
transform(processNameFormat: string, processInstance?: ProcessInstance): string {
let processName = processNameFormat;
if (processName.match(ProcessNamePipe.DATE_TIME_IDENTIFIER_REG_EXP)) {
if (processName.match(DATE_TIME_IDENTIFIER_REG_EXP)) {
const presentDateTime = moment.now();
processName = processName.replace(
ProcessNamePipe.DATE_TIME_IDENTIFIER_REG_EXP,
DATE_TIME_IDENTIFIER_REG_EXP,
this.localizedDatePipe.transform(presentDateTime, 'medium')
);
}
if (processName.match(ProcessNamePipe.PROCESS_DEFINITION_IDENTIFIER_REG_EXP)) {
if (processName.match(PROCESS_DEFINITION_IDENTIFIER_REG_EXP)) {
const selectedProcessDefinitionName = processInstance ? processInstance.processDefinitionName : '';
processName = processName.replace(
ProcessNamePipe.PROCESS_DEFINITION_IDENTIFIER_REG_EXP,
PROCESS_DEFINITION_IDENTIFIER_REG_EXP,
selectedProcessDefinitionName
);
}

View File

@@ -51,7 +51,7 @@ describe('ProcessCommentsComponent', () => {
it('should load comments when processInstanceId specified', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
expect(getCommentsSpy).toHaveBeenCalled();
});
@@ -61,7 +61,7 @@ describe('ProcessCommentsComponent', () => {
getCommentsSpy.and.returnValue(throwError({}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
expect(emitSpy).toHaveBeenCalled();
@@ -74,7 +74,7 @@ describe('ProcessCommentsComponent', () => {
it('should display comments when the process has comments', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -85,7 +85,7 @@ describe('ProcessCommentsComponent', () => {
it('should display comments count when the process has comments', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -96,7 +96,7 @@ describe('ProcessCommentsComponent', () => {
it('should not display comments when the process has no comments', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
getCommentsSpy.and.returnValue(of([]));
@@ -108,7 +108,7 @@ describe('ProcessCommentsComponent', () => {
it('should not display comments input by default', async () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
await fixture.whenStable();

View File

@@ -42,16 +42,13 @@ export class ProcessCommentsComponent implements OnChanges, OnDestroy {
error: EventEmitter<any> = new EventEmitter<any>();
comments: CommentModel [] = [];
comment$: Observable<CommentModel>;
message: string;
beingAdded: boolean = false;
private commentObserver: Observer<CommentModel>;
comment$: Observable<CommentModel>;
private onDestroy$ = new Subject<boolean>();
message: string;
beingAdded: boolean = false;
constructor(private commentProcessService: CommentProcessService) {
this.comment$ = new Observable<CommentModel>(observer => this.commentObserver = observer).pipe(share());
this.comment$
@@ -75,31 +72,6 @@ export class ProcessCommentsComponent implements OnChanges, OnDestroy {
}
}
private getProcessInstanceComments(processInstanceId: string): void {
this.resetComments();
if (processInstanceId) {
this.commentProcessService.getProcessInstanceComments(processInstanceId).subscribe(
(res: CommentModel[]) => {
res = res.sort((comment1: CommentModel, comment2: CommentModel) => {
const date1 = new Date(comment1.created);
const date2 = new Date(comment2.created);
return date1 > date2 ? -1 : date1 < date2 ? 1 : 0;
});
res.forEach((comment) => {
this.commentObserver.next(comment);
});
},
(err) => {
this.error.emit(err);
}
);
}
}
private resetComments(): void {
this.comments = [];
}
add(): void {
if (this.message && this.message.trim() && !this.beingAdded) {
this.beingAdded = true;
@@ -131,4 +103,28 @@ export class ProcessCommentsComponent implements OnChanges, OnDestroy {
this.error.emit(error);
}
private getProcessInstanceComments(processInstanceId: string): void {
this.resetComments();
if (processInstanceId) {
this.commentProcessService.getProcessInstanceComments(processInstanceId).subscribe(
(res: CommentModel[]) => {
res = res.sort((comment1: CommentModel, comment2: CommentModel) => {
const date1 = new Date(comment1.created);
const date2 = new Date(comment2.created);
return date1 > date2 ? -1 : date1 < date2 ? 1 : 0;
});
res.forEach((comment) => {
this.commentObserver.next(comment);
});
},
(err) => {
this.error.emit(err);
}
);
}
}
private resetComments(): void {
this.comments = [];
}
}

View File

@@ -51,7 +51,7 @@ describe('ProcessAuditDirective', () => {
let component: BasicButtonComponent;
let service: ProcessService;
function createFakePdfBlob(): Blob {
const createFakePdfBlob = (): Blob => {
const pdfData = atob(
'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' +
'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' +
@@ -67,7 +67,8 @@ describe('ProcessAuditDirective', () => {
'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G');
return new Blob([pdfData], {type: 'application/pdf'});
}
};
const blob = createFakePdfBlob();
setupTestBed({

View File

@@ -28,7 +28,7 @@ const PDF_FORMAT: string = 'pdf';
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'button[adf-process-audit]',
host: {
'role': 'button',
role: 'button',
'(click)': 'onClickAudit()'
}
})

View File

@@ -70,7 +70,7 @@ describe('ProcessFiltersComponent', () => {
spyOn(filterList, 'getFiltersByAppId').and.callThrough();
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -90,7 +90,7 @@ describe('ProcessFiltersComponent', () => {
done();
});
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -107,7 +107,7 @@ describe('ProcessFiltersComponent', () => {
done();
});
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
});
@@ -135,7 +135,7 @@ describe('ProcessFiltersComponent', () => {
filterList.currentFilter = nonExistingFilterParam;
filterList.filterParam = new FilterProcessRepresentationModel(nonExistingFilterParam);
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -147,7 +147,7 @@ describe('ProcessFiltersComponent', () => {
spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters));
const change = new SimpleChange(null, 'test', true);
filterList.ngOnChanges({ 'appName': change });
filterList.ngOnChanges({ appName: change });
filterList.success.subscribe((res) => {
const deployApp: any = appsProcessService.getDeployedApplicationsByName;
@@ -167,7 +167,7 @@ describe('ProcessFiltersComponent', () => {
const appId = '1';
const change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
filterList.error.subscribe((err) => {
expect(err).toBeDefined();
@@ -185,7 +185,7 @@ describe('ProcessFiltersComponent', () => {
const appId = 'fake-app';
const change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appName': change });
filterList.ngOnChanges({ appName: change });
filterList.error.subscribe((err) => {
expect(err).toBeDefined();
@@ -217,7 +217,7 @@ describe('ProcessFiltersComponent', () => {
const appId = '1';
const change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
expect(filterList.getFiltersByAppId).toHaveBeenCalledWith(appId);
});
@@ -227,7 +227,7 @@ describe('ProcessFiltersComponent', () => {
const appId = null;
const change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
expect(filterList.getFiltersByAppId).toHaveBeenCalledWith(appId);
});
@@ -237,7 +237,7 @@ describe('ProcessFiltersComponent', () => {
const appName = 'fake-app-name';
const change = new SimpleChange(null, appName, true);
filterList.ngOnChanges({ 'appName': change });
filterList.ngOnChanges({ appName: change });
expect(filterList.getFiltersByAppName).toHaveBeenCalledWith(appName);
});
@@ -260,7 +260,7 @@ describe('ProcessFiltersComponent', () => {
const appId = 1;
const change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -280,7 +280,7 @@ describe('ProcessFiltersComponent', () => {
const appId = 1;
const change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -296,7 +296,7 @@ describe('ProcessFiltersComponent', () => {
spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters));
filterList.showIcon = true;
const change = new SimpleChange(undefined, 1, true);
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -314,7 +314,7 @@ describe('ProcessFiltersComponent', () => {
spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters));
filterList.showIcon = false;
const change = new SimpleChange(undefined, 1, true);
filterList.ngOnChanges({ 'appId': change });
filterList.ngOnChanges({ appId: change });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();

View File

@@ -98,6 +98,7 @@ export class ProcessFiltersComponent implements OnInit, OnChanges {
/**
* Return the filter list filtered by appId
*
* @param appId - optional
*/
getFiltersByAppId(appId?: number) {
@@ -130,6 +131,7 @@ export class ProcessFiltersComponent implements OnInit, OnChanges {
/**
* Return the filter list filtered by appName
*
* @param appName
*/
getFiltersByAppName(appName: string) {
@@ -145,6 +147,7 @@ export class ProcessFiltersComponent implements OnInit, OnChanges {
/**
* Pass the selected filter as next
*
* @param filter
*/
selectFilter(filter: ProcessInstanceFilterRepresentation) {
@@ -174,6 +177,7 @@ export class ProcessFiltersComponent implements OnInit, OnChanges {
/**
* Select the Running filter
*
* @deprecated in 3.9.0, Use the filterParam Input() with a running filter instance instead
*/
selectRunningFilter() {
@@ -204,6 +208,13 @@ export class ProcessFiltersComponent implements OnInit, OnChanges {
return this.filters === undefined || (this.filters && this.filters.length === 0);
}
/**
* Return current filter icon
*/
getFilterIcon(icon: string): string {
return this.iconsMDL.mapGlyphiconToMaterialDesignIcons(icon);
}
/**
* Reset the filters properties
*/
@@ -211,11 +222,4 @@ export class ProcessFiltersComponent implements OnInit, OnChanges {
this.filters = [];
this.currentFilter = undefined;
}
/**
* Return current filter icon
*/
getFilterIcon(icon: string): string {
return this.iconsMDL.mapGlyphiconToMaterialDesignIcons(icon);
}
}

View File

@@ -77,7 +77,7 @@ describe('ProcessInstanceDetailsComponent', () => {
it('should display a header when the processInstanceId is provided', async () => {
fixture.detectChanges();
component.ngOnChanges({ 'processInstanceId': new SimpleChange(null, '123', true) });
component.ngOnChanges({ processInstanceId: new SimpleChange(null, '123', true) });
fixture.detectChanges();
await fixture.whenStable();
@@ -91,7 +91,7 @@ describe('ProcessInstanceDetailsComponent', () => {
fixture.detectChanges();
getProcessSpy.and.returnValue(of(exampleProcessNoName));
fixture.detectChanges();
component.ngOnChanges({ 'processInstanceId': new SimpleChange(null, '123', true) });
component.ngOnChanges({ processInstanceId: new SimpleChange(null, '123', true) });
fixture.detectChanges();
await fixture.whenStable();
@@ -105,7 +105,7 @@ describe('ProcessInstanceDetailsComponent', () => {
fixture.detectChanges();
getProcessSpy.and.returnValue(of(mockRunningProcess));
fixture.detectChanges();
component.ngOnChanges({ 'processInstanceId': new SimpleChange(null, '123', true) });
component.ngOnChanges({ processInstanceId: new SimpleChange(null, '123', true) });
fixture.detectChanges();
await fixture.whenStable();
@@ -119,7 +119,7 @@ describe('ProcessInstanceDetailsComponent', () => {
fixture.detectChanges();
getProcessSpy.and.returnValue(of(processEnded));
fixture.detectChanges();
component.ngOnChanges({ 'processInstanceId': new SimpleChange(null, '123', true) });
component.ngOnChanges({ processInstanceId: new SimpleChange(null, '123', true) });
fixture.detectChanges();
await fixture.whenStable();
@@ -142,7 +142,7 @@ describe('ProcessInstanceDetailsComponent', () => {
it('should fetch new process details when processInstanceId changed', async () => {
fixture.detectChanges();
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -162,7 +162,7 @@ describe('ProcessInstanceDetailsComponent', () => {
it('should NOT fetch new process details when processInstanceId changed to null', async () => {
fixture.detectChanges();
component.ngOnChanges({ 'processInstanceId': nullChange });
component.ngOnChanges({ processInstanceId: nullChange });
fixture.detectChanges();
await fixture.whenStable();
@@ -171,7 +171,7 @@ describe('ProcessInstanceDetailsComponent', () => {
});
it('should set a placeholder message when processInstanceId changed to null', async () => {
component.ngOnChanges({ 'processInstanceId': nullChange });
component.ngOnChanges({ processInstanceId: nullChange });
fixture.detectChanges();
await fixture.whenStable();
@@ -180,7 +180,7 @@ describe('ProcessInstanceDetailsComponent', () => {
});
it('should display cancel button if process is running', async () => {
component.ngOnChanges({ 'processInstanceId': change });
component.ngOnChanges({ processInstanceId: change });
fixture.detectChanges();
await fixture.whenStable();

View File

@@ -62,14 +62,15 @@ export class ProcessInstanceDetailsComponent implements OnChanges {
@Output()
taskClick = new EventEmitter<TaskDetailsEvent>();
processInstanceDetails: ProcessInstance;
/** Emitted when the "show diagram" button is clicked. */
@Output()
showProcessDiagram = new EventEmitter<any>();
processInstanceDetails: ProcessInstance;
/**
* Constructor
*
* @param translate Translation service
* @param activitiProcess Process service
*/

View File

@@ -170,8 +170,8 @@ describe('ProcessInstanceHeaderComponent', () => {
it('should show only the properties from the configuration file', () => {
appConfigService.config['adf-process-instance-header'] = {
'presets': {
'properties': ['status', 'ended']
presets: {
properties: ['status', 'ended']
}
};
component.ngOnChanges();

View File

@@ -52,6 +52,27 @@ export class ProcessInstanceHeaderComponent implements OnChanges {
}
}
getProcessStatus(): string {
if (this.processInstance) {
return this.isRunning() ? 'Running' : 'Completed';
}
return 'Unknown';
}
getStartedByFullName(): string {
let fullName = '';
if (this.processInstance && this.processInstance.startedBy) {
fullName += this.processInstance.startedBy.firstName || '';
fullName += fullName ? ' ' : '';
fullName += this.processInstance.startedBy.lastName || '';
}
return fullName;
}
isRunning(): boolean {
return this.processInstance && !this.processInstance.ended;
}
private initDefaultProperties(): any[] {
return [
new CardViewTextItemModel(
@@ -115,25 +136,4 @@ export class ProcessInstanceHeaderComponent implements OnChanges {
private isValidSelection(filteredProperties: string[], cardItem: CardViewBaseItemModel): boolean {
return filteredProperties ? filteredProperties.indexOf(cardItem.key) >= 0 : true;
}
getProcessStatus(): string {
if (this.processInstance) {
return this.isRunning() ? 'Running' : 'Completed';
}
return 'Unknown';
}
getStartedByFullName(): string {
let fullName = '';
if (this.processInstance && this.processInstance.startedBy) {
fullName += this.processInstance.startedBy.firstName || '';
fullName += fullName ? ' ' : '';
fullName += this.processInstance.startedBy.lastName || '';
}
return fullName;
}
isRunning(): boolean {
return this.processInstance && !this.processInstance.ended;
}
}

View File

@@ -95,12 +95,12 @@ describe('ProcessInstanceTasksComponent', () => {
it('should display active tasks', async () => {
const change = new SimpleChange(null, exampleProcessInstance, true);
fixture.detectChanges();
component.ngOnChanges({ 'processInstanceDetails': change });
component.ngOnChanges({ processInstanceDetails: change });
fixture.detectChanges();
await fixture.whenStable();
component.ngOnChanges({ 'processInstanceDetails': change });
component.ngOnChanges({ processInstanceDetails: change });
const listEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks"]'));
expect(listEl).not.toBeNull();
expect(listEl.queryAll(By.css('mat-list-item')).length).toBe(1);
@@ -109,7 +109,7 @@ describe('ProcessInstanceTasksComponent', () => {
it('should display completed tasks', async () => {
const change = new SimpleChange(null, exampleProcessInstance, true);
fixture.detectChanges();
component.ngOnChanges({ 'processInstanceDetails': change });
component.ngOnChanges({ processInstanceDetails: change });
fixture.detectChanges();
await fixture.whenStable();

View File

@@ -44,19 +44,7 @@ export class ProcessInstanceTasksComponent implements OnInit, OnChanges, OnDestr
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
activeTasks: TaskDetailsModel[] = [];
completedTasks: TaskDetailsModel[] = [];
private taskObserver: Observer<TaskDetailsModel>;
private completedTaskObserver: Observer<TaskDetailsModel>;
private onDestroy$ = new Subject<boolean>();
task$: Observable<TaskDetailsModel>;
completedTask$: Observable<TaskDetailsModel>;
message: string;
processId: string;
error = new EventEmitter<any>();
@ViewChild('startDialog')
startDialog: any;
@@ -66,7 +54,18 @@ export class ProcessInstanceTasksComponent implements OnInit, OnChanges, OnDestr
/** Emitted when a task is clicked. */
@Output()
taskClick: EventEmitter<TaskDetailsEvent> = new EventEmitter<TaskDetailsEvent>();
taskClick = new EventEmitter<TaskDetailsEvent>();
activeTasks: TaskDetailsModel[] = [];
completedTasks: TaskDetailsModel[] = [];
task$: Observable<TaskDetailsModel>;
completedTask$: Observable<TaskDetailsModel>;
message: string;
processId: string;
private taskObserver: Observer<TaskDetailsModel>;
private completedTaskObserver: Observer<TaskDetailsModel>;
private onDestroy$ = new Subject<boolean>();
constructor(private activitiProcess: ProcessService,
private logService: LogService,

View File

@@ -65,7 +65,7 @@ describe('ProcessInstanceListComponent', () => {
getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(of(fakeProcessInstance));
appConfig.config['adf-process-list'] = {
'presets': fakeProcessColumnSchema
presets: fakeProcessColumnSchema
};
});
@@ -283,12 +283,12 @@ describe('ProcessInstanceListComponent', () => {
it('should show custom resolved value in the column', async () => {
appConfig.config['adf-process-list'] = {
'presets': {
'fakeProcessCustomSchema': [
presets: {
fakeProcessCustomSchema: [
{
'key': 'variables',
'type': 'text',
'title': 'Variables'
key: 'variables',
type: 'text',
title: 'Variables'
}
]
}
@@ -335,7 +335,7 @@ describe('ProcessInstanceListComponent', () => {
done();
});
component.ngOnChanges({'appId': change});
component.ngOnChanges({appId: change});
});
it('should reload the list when the state parameter changes', (done) => {
@@ -351,7 +351,7 @@ describe('ProcessInstanceListComponent', () => {
done();
});
component.ngOnChanges({'state': change});
component.ngOnChanges({state: change});
});
it('should reload the list when the sort parameter changes', (done) => {
@@ -367,7 +367,7 @@ describe('ProcessInstanceListComponent', () => {
done();
});
component.ngOnChanges({'sort': change});
component.ngOnChanges({sort: change});
});
it('should reload the process list when the processDefinitionId parameter changes', (done) => {
@@ -383,7 +383,7 @@ describe('ProcessInstanceListComponent', () => {
done();
});
component.ngOnChanges({'processDefinitionId': change});
component.ngOnChanges({processDefinitionId: change});
});
it('should reload the process list when the processDefinitionId parameter changes to null', (done) => {
@@ -399,7 +399,7 @@ describe('ProcessInstanceListComponent', () => {
done();
});
component.ngOnChanges({'processDefinitionId': change});
component.ngOnChanges({processDefinitionId: change});
});
it('should reload the process list when the processInstanceId parameter changes', (done) => {
@@ -415,7 +415,7 @@ describe('ProcessInstanceListComponent', () => {
done();
});
component.ngOnChanges({'processInstanceId': change});
component.ngOnChanges({processInstanceId: change});
});
it('should reload the process list when the processInstanceId parameter changes to null', (done) => {
@@ -431,7 +431,7 @@ describe('ProcessInstanceListComponent', () => {
done();
});
component.ngOnChanges({'processInstanceId': change});
component.ngOnChanges({processInstanceId: change});
});
it('should update the columns when presetColumn schema changes', () => {
@@ -442,7 +442,7 @@ describe('ProcessInstanceListComponent', () => {
component.presetColumn = 'fakeRunningProcessSchema';
const presetColumnChange = new SimpleChange(null, 'fakeRunningProcessSchema', false);
component.ngOnChanges({ 'presetColumn': presetColumnChange });
component.ngOnChanges({ presetColumn: presetColumnChange });
const newColumnSchema = component.mergeJsonAndHtmlSchema();
const expectedColumn1 = new ObjectDataColumn(fakeProcessColumnSchema.fakeRunningProcessSchema[0]);
@@ -569,12 +569,12 @@ describe('Process List: Custom EmptyTemplateComponent', () => {
</data-columns>
</adf-process-instance-list>`
})
class ProcessListContextMenuComponent implements OnInit {
appId: number;
@Output()
contextAction = new EventEmitter<any>();
appId: number;
private performAction$ = new Subject<any>();
ngOnInit() {

View File

@@ -47,6 +47,8 @@ import { BehaviorSubject } from 'rxjs';
import { ProcessListModel } from '../models/process-list.model';
import { finalize } from 'rxjs/operators';
const PRESET_KEY = 'adf-process-list.presets';
@Component({
selector: 'adf-process-instance-list',
styleUrls: ['./process-list.component.css'],
@@ -54,8 +56,6 @@ import { finalize } from 'rxjs/operators';
})
export class ProcessInstanceListComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent {
static PRESET_KEY = 'adf-process-list.presets';
@ContentChild(CustomEmptyContentTemplateDirective)
customEmptyContent: CustomEmptyContentTemplateDirective;
@@ -154,10 +154,10 @@ export class ProcessInstanceListComponent extends DataTableSchema implements OnC
constructor(private processService: ProcessService,
private userPreferences: UserPreferencesService,
appConfig: AppConfigService) {
super(appConfig, ProcessInstanceListComponent.PRESET_KEY, processPresetsDefaultModel);
super(appConfig, PRESET_KEY, processPresetsDefaultModel);
this.size = this.userPreferences.paginationSize;
this.pagination = new BehaviorSubject<PaginationModel>(<PaginationModel> {
this.pagination = new BehaviorSubject<PaginationModel>({
maxItems: this.size,
skipCount: 0,
totalItems: 0
@@ -190,6 +190,98 @@ export class ProcessInstanceListComponent extends DataTableSchema implements OnC
}
}
reload() {
this.requestNode = this.createRequestNode();
this.load(this.requestNode);
}
/**
* Select the first instance of a list if present
*/
selectFirst() {
if (this.selectFirstRow) {
if (!this.isListEmpty()) {
const dataRow = this.rows[0];
dataRow.isSelected = true;
this.currentInstanceId = dataRow['id'];
} else {
this.currentInstanceId = null;
}
}
}
/**
* Return the current id
*/
getCurrentId(): string {
return this.currentInstanceId;
}
/**
* Check if the list is empty
*/
isListEmpty(): boolean {
return !this.rows || this.rows.length === 0;
}
/**
* Emit the event rowClick passing the current task id when the row is clicked
*
* @param event
*/
onRowClick(event: DataRowEvent) {
const item = event;
this.currentInstanceId = item.value.getValue('id');
this.rowClick.emit(this.currentInstanceId);
}
/**
* Emit the event rowClick passing the current task id when pressed the Enter key on the selected row
*
* @param event
*/
onRowKeyUp(event: CustomEvent<any>) {
if (event.detail.keyboardEvent.key === 'Enter') {
event.preventDefault();
this.currentInstanceId = event.detail.row.getValue('id');
this.rowClick.emit(this.currentInstanceId);
}
}
onShowRowContextMenu(event: DataCellEvent) {
this.showRowContextMenu.emit(event);
}
updatePagination(params: PaginationModel) {
const needsReload = params.maxItems || params.skipCount;
this.size = params.maxItems;
this.page = this.currentPage(params.skipCount, params.maxItems);
if (needsReload) {
this.reload();
}
}
currentPage(skipCount: number, maxItems: number): number {
return (skipCount && maxItems) ? Math.floor(skipCount / maxItems) : 0;
}
private createRequestNode(): ProcessFilterParamRepresentationModel {
return new ProcessFilterParamRepresentationModel({
appDefinitionId: this.appId,
processDefinitionId: this.processDefinitionId,
processInstanceId: this.processInstanceId,
state: this.state,
sort: this.sort,
page: this.page,
size: this.size,
start: 0
});
}
private isSortChanged(changes: SimpleChanges): boolean {
const actualSort = changes['sort'];
return actualSort && actualSort.currentValue && actualSort.currentValue !== actualSort.previousValue;
@@ -224,11 +316,6 @@ export class ProcessInstanceListComponent extends DataTableSchema implements OnC
return changed;
}
public reload() {
this.requestNode = this.createRequestNode();
this.load(this.requestNode);
}
private load(requestNode: ProcessFilterParamRepresentationModel) {
this.isLoading = true;
this.processService.getProcesses(requestNode)
@@ -250,89 +337,4 @@ export class ProcessInstanceListComponent extends DataTableSchema implements OnC
}
);
}
/**
* Select the first instance of a list if present
*/
selectFirst() {
if (this.selectFirstRow) {
if (!this.isListEmpty()) {
const dataRow = this.rows[0];
dataRow.isSelected = true;
this.currentInstanceId = dataRow['id'];
} else {
this.currentInstanceId = null;
}
}
}
/**
* Return the current id
*/
getCurrentId(): string {
return this.currentInstanceId;
}
/**
* Check if the list is empty
*/
isListEmpty(): boolean {
return !this.rows || this.rows.length === 0;
}
/**
* Emit the event rowClick passing the current task id when the row is clicked
* @param event
*/
onRowClick(event: DataRowEvent) {
const item = event;
this.currentInstanceId = item.value.getValue('id');
this.rowClick.emit(this.currentInstanceId);
}
/**
* Emit the event rowClick passing the current task id when pressed the Enter key on the selected row
* @param event
*/
onRowKeyUp(event: CustomEvent<any>) {
if (event.detail.keyboardEvent.key === 'Enter') {
event.preventDefault();
this.currentInstanceId = event.detail.row.getValue('id');
this.rowClick.emit(this.currentInstanceId);
}
}
onShowRowContextMenu(event: DataCellEvent) {
this.showRowContextMenu.emit(event);
}
private createRequestNode(): ProcessFilterParamRepresentationModel {
return new ProcessFilterParamRepresentationModel({
appDefinitionId: this.appId,
processDefinitionId: this.processDefinitionId,
processInstanceId: this.processInstanceId,
state: this.state,
sort: this.sort,
page: this.page,
size: this.size,
start: 0
});
}
updatePagination(params: PaginationModel) {
const needsReload = params.maxItems || params.skipCount;
this.size = params.maxItems;
this.page = this.currentPage(params.skipCount, params.maxItems);
if (needsReload) {
this.reload();
}
}
currentPage(skipCount: number, maxItems: number): number {
return (skipCount && maxItems) ? Math.floor(skipCount / maxItems) : 0;
}
}

View File

@@ -101,7 +101,7 @@ describe('StartFormComponent', () => {
fixture.detectChanges();
component.name = 'My new process';
const change = new SimpleChange(null, 123, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
});
@@ -163,7 +163,7 @@ describe('StartFormComponent', () => {
fixture.detectChanges();
getDefinitionsSpy.and.returnValue(of(testProcessDefWithForm));
const change = new SimpleChange(null, 123, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
});
it('should initialize start form', async () => {
@@ -242,7 +242,7 @@ describe('StartFormComponent', () => {
it('Should get the alfrescoRepositoryName from the config json', async () => {
appConfig.config = Object.assign(appConfig.config, {
'alfrescoRepositoryName': 'alfresco-123'
alfrescoRepositoryName: 'alfresco-123'
});
expect(component.getAlfrescoRepositoryName()).toBe('alfresco-123Alfresco');
@@ -341,7 +341,7 @@ describe('StartFormComponent', () => {
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of([]));
component.appId = 123;
const change = new SimpleChange(null, 123, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -367,7 +367,7 @@ describe('StartFormComponent', () => {
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(testProcessDefinitions));
component.appId = 123;
const change = new SimpleChange(null, 123, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -379,7 +379,7 @@ describe('StartFormComponent', () => {
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
component.appId = 123;
const change = new SimpleChange(null, 123, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -562,7 +562,7 @@ describe('StartFormComponent', () => {
component.appId = 123;
const appIdChange = new SimpleChange(null, 123, true);
component.ngOnChanges({ 'appId': appIdChange });
component.ngOnChanges({ appId: appIdChange });
fixture.detectChanges();
selectOptionByName(testProcessDef.name);
@@ -626,7 +626,7 @@ describe('StartFormComponent', () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
const change = new SimpleChange(null, 3, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
const appsSelector = fixture.nativeElement.querySelector('[data-automation-id="adf-start-process-apps-drop-down"]');
const lableElement = fixture.nativeElement.querySelector('.adf-start-process-app-list .mat-form-field-label');
@@ -653,7 +653,7 @@ describe('StartFormComponent', () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
const change = new SimpleChange(null, 3, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
expect(component.appId).toBe(component.selectedApplication.id);
@@ -668,7 +668,7 @@ describe('StartFormComponent', () => {
getDefinitionsSpy.and.returnValue(of([ { id: 'my:process 3', name: 'My Process 3', hasStartForm: true } ]));
fixture.detectChanges();
const newApplication = <MatSelectChange> { value: deployedApps[1] };
const newApplication = { value: deployedApps[1] } as MatSelectChange;
component.onAppSelectionChange(newApplication);
fixture.detectChanges();
@@ -685,20 +685,20 @@ describe('StartFormComponent', () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
const change = new SimpleChange(null, 123, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(1);
expect(component.selectedApplication.name).toEqual('App1');
});
it('[C333511] Should be able to preselect single app deployed with single process and start event Form', async() => {
it('[C333511] Should be able to preselect single app deployed with single process and start event Form', async () => {
getDeployedApplicationsSpy.and.returnValues(of([deployedApps[0]]));
getDefinitionsSpy.and.returnValues(of(testProcessDefWithForm));
const change = new SimpleChange(null, 123, true);
component.appId = 123;
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -725,13 +725,13 @@ describe('StartFormComponent', () => {
expect(cancelButton).not.toBeNull();
});
it('[C333511] Should be able to preselect single app deployed with single process and no form', async() => {
it('[C333511] Should be able to preselect single app deployed with single process and no form', async () => {
getDeployedApplicationsSpy.and.returnValues(of([deployedApps[0]]));
getDefinitionsSpy.and.returnValues(of(testProcessDefinitions));
const change = new SimpleChange(null, 123, true);
component.appId = 123;
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -762,7 +762,7 @@ describe('StartFormComponent', () => {
it('Should be able to pre-select an application from the apps based given appId', () => {
component.appId = 2;
const change = new SimpleChange(null, 2, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(6);
@@ -774,7 +774,7 @@ describe('StartFormComponent', () => {
it('Should be able to disable process name and definitions inputs if there is no application selected by default', () => {
component.appId = 12345;
const change = new SimpleChange(null, 12345, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(6);
@@ -790,7 +790,7 @@ describe('StartFormComponent', () => {
it('Should be able to enable process name and definitions inputs if the application selected by given appId', () => {
component.appId = 2;
const change = new SimpleChange(null, 2, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(6);
@@ -806,7 +806,7 @@ describe('StartFormComponent', () => {
it('Should be able to enable process name and definitions inputs when the application selected from the apps drop-down', () => {
component.appId = 12345;
const change = new SimpleChange(null, 12345, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(6);
@@ -837,7 +837,7 @@ describe('StartFormComponent', () => {
getDeployedApplicationsSpy.and.returnValues(of([singleDeployedApp]));
const change = new SimpleChange(null, mockAppid, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
@@ -864,10 +864,10 @@ describe('StartFormComponent', () => {
expect(component.selectedProcessDef.hasStartForm).toEqual(processDefWithNoStartForm.hasStartForm);
});
it('[C333522] Should be able to list multiple deployed apps with multiple process', async() => {
it('[C333522] Should be able to list multiple deployed apps with multiple process', async () => {
const change = new SimpleChange(null, 123, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
const application1 = deployedApps[0];
@@ -878,7 +878,7 @@ describe('StartFormComponent', () => {
const processDefWithStartForm = testProcessDefWithForm[0];
getDefinitionsSpy.and.returnValues(of([processDefWithStartForm]));
component.onAppSelectionChange(<MatSelectChange> { value: application1 });
component.onAppSelectionChange({ value: application1 } as MatSelectChange);
fixture.detectChanges();
await fixture.whenStable();
@@ -892,7 +892,7 @@ describe('StartFormComponent', () => {
expect(component.selectedProcessDef.hasStartForm).toEqual(processDefWithStartForm.hasStartForm);
getDefinitionsSpy.and.returnValues(of(testMultipleProcessDefs));
component.onAppSelectionChange(<MatSelectChange> { value: application2 });
component.onAppSelectionChange({ value: application2 } as MatSelectChange);
fixture.detectChanges();
await fixture.whenStable();
@@ -902,7 +902,7 @@ describe('StartFormComponent', () => {
const processDefWithNoStartForm = testMultipleProcessDefs[0];
getDefinitionsSpy.and.returnValues(of([processDefWithNoStartForm]));
component.onAppSelectionChange(<MatSelectChange> { value: application3 });
component.onAppSelectionChange({ value: application3 } as MatSelectChange);
fixture.detectChanges();
await fixture.whenStable();
@@ -920,7 +920,7 @@ describe('StartFormComponent', () => {
describe('Empty Template', () => {
it('[333510] Should be able to show empty template when no applications deployed', async() => {
it('[333510] Should be able to show empty template when no applications deployed', async () => {
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of([]));
component.showSelectApplicationDropdown = true;
@@ -944,7 +944,7 @@ describe('StartFormComponent', () => {
expect(noProcessElement.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.NO_PROCESS_DEFINITIONS');
});
it('Should be able to show empty template if processDefinitions are empty', async() => {
it('Should be able to show empty template if processDefinitions are empty', async () => {
getDefinitionsSpy.and.returnValue(of([]));
component.appId = 1;
@@ -965,7 +965,7 @@ describe('StartFormComponent', () => {
expect(noProcessElement.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.NO_PROCESS_DEFINITIONS');
});
it('should show no process definition selected template if there is no process definition selected', async() => {
it('should show no process definition selected template if there is no process definition selected', async () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of(deployedApps));
@@ -980,7 +980,7 @@ describe('StartFormComponent', () => {
expect(noProcessElement.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.NO_PROCESS_DEF_SELECTED');
});
it('should show no start form template if selected process definition does not have start form', async() => {
it('should show no start form template if selected process definition does not have start form', async () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of(deployedApps));
@@ -1007,7 +1007,7 @@ describe('StartFormComponent', () => {
fixture.detectChanges();
});
it('should emit error event in case loading process definitions failed', async() => {
it('should emit error event in case loading process definitions failed', async () => {
const errorSpy = spyOn(component.error, 'emit');
getDefinitionsSpy.and.returnValue(throwError(processDefError));
@@ -1019,7 +1019,7 @@ describe('StartFormComponent', () => {
expect(errorSpy).toHaveBeenCalledWith(processDefError);
});
it('should emit error event in case loading applications failed', async() => {
it('should emit error event in case loading applications failed', async () => {
const errorSpy = spyOn(component.error, 'emit');
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(throwError(applicationsError));
@@ -1032,7 +1032,7 @@ describe('StartFormComponent', () => {
expect(errorSpy).toHaveBeenCalledWith(applicationsError);
});
it('should emit error event in case start process failed', async() => {
it('should emit error event in case start process failed', async () => {
const errorSpy = spyOn(component.error, 'emit');
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of(deployedApps));

View File

@@ -40,6 +40,7 @@ import { MinimalNode, RelatedContentRepresentation } from '@alfresco/js-api';
import { AppDefinitionRepresentationModel } from '../../task-list';
import { ProcessNamePipe } from '../../pipes/process-name.pipe';
const MAX_LENGTH = 255;
@Component({
selector: 'adf-start-process',
templateUrl: './start-process.component.html',
@@ -48,8 +49,6 @@ import { ProcessNamePipe } from '../../pipes/process-name.pipe';
})
export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestroy {
MAX_LENGTH: number = 255;
/** (optional) Limit the list of processes that can be started to those
* contained in the specified app.
*/
@@ -92,7 +91,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
/** Emitted when the process starts. */
@Output()
start: EventEmitter<ProcessInstance> = new EventEmitter<ProcessInstance>();
start = new EventEmitter<ProcessInstance>();
/** Emitted when the process is canceled. */
@Output()
@@ -100,15 +99,15 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
error = new EventEmitter<any>();
/** Emitted when process definition selection changes. */
@Output()
processDefinitionSelection: EventEmitter<ProcessDefinitionRepresentation> = new EventEmitter<ProcessDefinitionRepresentation>();
processDefinitionSelection = new EventEmitter<ProcessDefinitionRepresentation>();
/** Emitted when application selection changes. */
@Output()
applicationSelection: EventEmitter<AppDefinitionRepresentationModel> = new EventEmitter<AppDefinitionRepresentationModel>();
applicationSelection = new EventEmitter<AppDefinitionRepresentationModel>();
@ViewChild('startForm')
startForm: StartFormComponent;
@@ -121,7 +120,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
processNameInput: FormControl;
processDefinitionInput: FormControl;
filteredProcessesDefinitions$: Observable<ProcessDefinitionRepresentation[]>;
maxProcessNameLength: number = this.MAX_LENGTH;
maxProcessNameLength: number = MAX_LENGTH;
alfrescoRepositoryName: string;
applications: AppDefinitionRepresentationModel[] = [];
selectedApplication: AppDefinitionRepresentationModel;
@@ -179,29 +178,6 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
}
}
private isAppIdChanged(changes: SimpleChanges) {
return changes['appId'] && changes['appId'].currentValue && changes['appId'].currentValue !== changes['appId'].previousValue;
}
private isProcessDefinitionChanged(changes: SimpleChanges) {
return changes['processDefinitionName'] && changes['processDefinitionName'].currentValue &&
changes['processDefinitionName'].currentValue !== changes['processDefinitionName'].previousValue;
}
private _filter(value: string): ProcessDefinitionRepresentation[] {
if (value !== null && value !== undefined) {
const filterValue = value.toLowerCase();
const filteredProcess = this.processDefinitions.filter((option) => option.name.toLowerCase().includes(filterValue));
if (this.processFilterSelector) {
this.selectedProcessDef = this.getSelectedProcess(filterValue);
}
return filteredProcess;
}
return [];
}
getSelectedProcess(selectedProcess: string): ProcessDefinitionRepresentation {
let processSelected = this.processDefinitions.find((process) => process.name.toLowerCase() === selectedProcess);
@@ -232,9 +208,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
}
if (this.processDefinitionName) {
const filteredProcessDefinition = processDefinitionRepresentations.find((processDefinition) => {
return processDefinition.name === this.processDefinitionName;
});
const filteredProcessDefinition = processDefinitionRepresentations.find((processDefinition) => processDefinition.name === this.processDefinitionName);
if (filteredProcessDefinition) {
currentProcessDef = filteredProcessDefinition;
}
@@ -257,9 +231,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
filterProcessDefinitionByName() {
if (this.processDefinitionName) {
const filteredProcessDef = this.processDefinitions.find((processDefinition) => {
return processDefinition.name === this.processDefinitionName;
});
const filteredProcessDef = this.processDefinitions.find((processDefinition) => processDefinition.name === this.processDefinitionName);
if (filteredProcessDef) {
this.processDefinitionSelectionChanged(filteredProcessDef);
@@ -322,14 +294,6 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
this.loadProcessDefinitionsBasedOnSelectedApp();
}
private isAppSelected(): boolean {
return !!(this.selectedApplication && this.selectedApplication.id);
}
private removeDefaultApps(apps: AppDefinitionRepresentationModel []): AppDefinitionRepresentationModel[] {
return apps.filter((app) => app.id);
}
hasApplications(): boolean {
return this.applications && this.applications.length > 0;
}
@@ -408,19 +372,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
return this.selectedProcessDef && this.selectedProcessDef.id && this.processNameInput.valid && this.isStartFormMissingOrValid();
}
private resetSelectedProcessDefinition() {
this.selectedProcessDef = undefined;
if (this.processDefinitionInput) {
this.processDefinitionInput.setValue('');
}
}
private resetProcessDefinitions() {
this.processDefinitions = [];
this.resetSelectedProcessDefinition();
}
public onOutcomeClick(outcome: string) {
onOutcomeClick(outcome: string) {
this.startProcess(outcome);
}
@@ -461,16 +413,6 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
return this.processDefinitionInput;
}
private toggleProcessNameAndDefinitionsDropdown() {
if (!this.isAppSelected()) {
this.processDefinitionController.disable();
this.nameController.disable();
} else {
this.processDefinitionController.enable();
this.nameController.enable();
}
}
processDefinitionSelectionChanged(processDefinition: ProcessDefinitionRepresentation) {
if (processDefinition) {
const processInstanceDetails = new ProcessInstance({ processDefinitionName: processDefinition.name });
@@ -488,4 +430,57 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit, OnDestr
isLoading(): boolean {
return this.showSelectApplicationDropdown ? this.isAppsLoading : false;
}
private isAppSelected(): boolean {
return !!(this.selectedApplication && this.selectedApplication.id);
}
private removeDefaultApps(apps: AppDefinitionRepresentationModel []): AppDefinitionRepresentationModel[] {
return apps.filter((app) => app.id);
}
private resetSelectedProcessDefinition() {
this.selectedProcessDef = undefined;
if (this.processDefinitionInput) {
this.processDefinitionInput.setValue('');
}
}
private resetProcessDefinitions() {
this.processDefinitions = [];
this.resetSelectedProcessDefinition();
}
private toggleProcessNameAndDefinitionsDropdown() {
if (!this.isAppSelected()) {
this.processDefinitionController.disable();
this.nameController.disable();
} else {
this.processDefinitionController.enable();
this.nameController.enable();
}
}
private isAppIdChanged(changes: SimpleChanges) {
return changes['appId'] && changes['appId'].currentValue && changes['appId'].currentValue !== changes['appId'].previousValue;
}
private isProcessDefinitionChanged(changes: SimpleChanges) {
return changes['processDefinitionName'] && changes['processDefinitionName'].currentValue &&
changes['processDefinitionName'].currentValue !== changes['processDefinitionName'].previousValue;
}
private _filter(value: string): ProcessDefinitionRepresentation[] {
if (value !== null && value !== undefined) {
const filterValue = value.toLowerCase();
const filteredProcess = this.processDefinitions.filter((option) => option.name.toLowerCase().includes(filterValue));
if (this.processFilterSelector) {
this.selectedProcessDef = this.getSelectedProcess(filterValue);
}
return filteredProcess;
}
return [];
}
}

View File

@@ -15,20 +15,20 @@
* limitations under the License.
*/
export let processPresetsDefaultModel = {
'default': [
export const processPresetsDefaultModel = {
default: [
{
'key': 'name',
'type': 'text',
'title': 'ADF_PROCESS_LIST.PROPERTIES.NAME',
'sortable': true
key: 'name',
type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.NAME',
sortable: true
},
{
'key': 'created',
'type': 'text',
'title': 'ADF_PROCESS_LIST.PROPERTIES.CREATED',
'cssClass': 'hidden',
'sortable': true
key: 'created',
type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.CREATED',
cssClass: 'hidden',
sortable: true
}
]
};

View File

@@ -106,7 +106,7 @@ describe('Process filter', () => {
});
jasmine.Ajax.requests.at(0).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 111, name: 'Running', icon: 'fake-icon', recent: false
@@ -114,7 +114,7 @@ describe('Process filter', () => {
});
jasmine.Ajax.requests.at(1).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 222, name: 'Completed', icon: 'fake-icon', recent: false
@@ -122,7 +122,7 @@ describe('Process filter', () => {
});
jasmine.Ajax.requests.at(2).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 333, name: 'All', icon: 'fake-icon', recent: false
@@ -149,7 +149,7 @@ describe('Process filter', () => {
});
jasmine.Ajax.requests.at(0).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 111, name: 'Running', icon: 'fake-icon', recent: false
@@ -157,7 +157,7 @@ describe('Process filter', () => {
});
jasmine.Ajax.requests.at(1).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 222, name: 'Completed', icon: 'fake-icon', recent: false
@@ -165,7 +165,7 @@ describe('Process filter', () => {
});
jasmine.Ajax.requests.at(2).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 333, name: 'All', icon: 'fake-icon', recent: false

View File

@@ -30,7 +30,7 @@ import {
})
export class ProcessFilterService {
private _userFiltersApi;
private _userFiltersApi: UserFiltersApi;
get userFiltersApi(): UserFiltersApi {
this._userFiltersApi = this._userFiltersApi ?? new UserFiltersApi(this.alfrescoApiService.getInstance());
return this._userFiltersApi;
@@ -41,6 +41,7 @@ export class ProcessFilterService {
/**
* Gets all filters defined for a Process App.
*
* @param appId ID of the target app
* @returns Array of filter details
*/
@@ -61,6 +62,7 @@ export class ProcessFilterService {
/**
* Retrieves the process filter by ID.
*
* @param filterId ID of the filter
* @param appId ID of the target app
* @returns Details of the filter
@@ -68,15 +70,14 @@ export class ProcessFilterService {
getProcessFilterById(filterId: number, appId?: number): Observable<FilterProcessRepresentationModel> {
return from(this.callApiProcessFilters(appId))
.pipe(
map((response: any) => {
return response.data.find((filter) => filter.id === filterId);
}),
map((response: any) => response.data.find((filter) => filter.id === filterId)),
catchError((err) => this.handleProcessError(err))
);
}
/**
* Retrieves the process filter by name.
*
* @param filterName Name of the filter
* @param appId ID of the target app
* @returns Details of the filter
@@ -84,19 +85,18 @@ export class ProcessFilterService {
getProcessFilterByName(filterName: string, appId?: number): Observable<FilterProcessRepresentationModel> {
return from(this.callApiProcessFilters(appId))
.pipe(
map((response: any) => {
return response.data.find((filter) => filter.name === filterName);
}),
map((response: any) => response.data.find((filter) => filter.name === filterName)),
catchError((err) => this.handleProcessError(err))
);
}
/**
* Creates and returns the default filters for an app.
*
* @param appId ID of the target app
* @returns Default filters just created
*/
public createDefaultFilters(appId: number): Observable<FilterProcessRepresentationModel[]> {
createDefaultFilters(appId: number): Observable<FilterProcessRepresentationModel[]> {
const runningFilter = this.getRunningFilterInstance(appId, 0);
const runningObservable = this.addProcessFilter(runningFilter);
@@ -135,83 +135,72 @@ export class ProcessFilterService {
/**
* Creates and returns a filter that matches "running" process instances.
*
* @param appId ID of the target app
* @param index of the filter (optional)
* @returns Filter just created
*/
public getRunningFilterInstance(appId: number, index?: number): FilterProcessRepresentationModel {
return new FilterProcessRepresentationModel({
'name': 'Running',
'appId': appId,
'recent': true,
'icon': 'glyphicon-random',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'running' },
index
});
}
/**
* Returns a static Completed filter instance.
* @param appId ID of the target app
* @param index of the filter (optional)
* @returns Details of the filter
*/
private getCompletedFilterInstance(appId: number, index?: number): FilterProcessRepresentationModel {
getRunningFilterInstance(appId: number, index?: number): FilterProcessRepresentationModel {
return new FilterProcessRepresentationModel({
'name': 'Completed',
'appId': appId,
'recent': false,
'icon': 'glyphicon-ok-sign',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'completed' },
index
});
}
/**
* Returns a static All filter instance.
* @param appId ID of the target app
* @param index of the filter (optional)
* @returns Details of the filter
*/
private getAllFilterInstance(appId: number, index?: number): FilterProcessRepresentationModel {
return new FilterProcessRepresentationModel({
'name': 'All',
'appId': appId,
'recent': true,
'icon': 'glyphicon-th',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'all' },
name: 'Running',
appId,
recent: true,
icon: 'glyphicon-random',
filter: { sort: 'created-desc', name: '', state: 'running' },
index
});
}
/**
* Adds a filter.
*
* @param filter The filter to add
* @returns The filter just added
*/
addProcessFilter(filter: FilterProcessRepresentationModel): Observable<FilterProcessRepresentationModel> {
return from(this.userFiltersApi.createUserProcessInstanceFilter(filter))
.pipe(
map((response: FilterProcessRepresentationModel) => {
return response;
}),
map((response: FilterProcessRepresentationModel) => response),
catchError((err) => this.handleProcessError(err))
);
}
/**
* Calls `getUserProcessInstanceFilters` from the Alfresco JS API.
*
* @param appId ID of the target app
* @returns List of filter details
*/
callApiProcessFilters(appId?: number): Promise<ResultListDataRepresentationUserProcessInstanceFilterRepresentation> {
if (appId) {
return this.userFiltersApi.getUserProcessInstanceFilters({ appId: appId });
return this.userFiltersApi.getUserProcessInstanceFilters({ appId });
} else {
return this.userFiltersApi.getUserProcessInstanceFilters();
}
}
private getCompletedFilterInstance(appId: number, index?: number): FilterProcessRepresentationModel {
return new FilterProcessRepresentationModel({
name: 'Completed',
appId,
recent: false,
icon: 'glyphicon-ok-sign',
filter: { sort: 'created-desc', name: '', state: 'completed' },
index
});
}
private getAllFilterInstance(appId: number, index?: number): FilterProcessRepresentationModel {
return new FilterProcessRepresentationModel({
name: 'All',
appId,
recent: true,
icon: 'glyphicon-th',
filter: { sort: 'created-desc', name: '', state: 'all' },
index
});
}
private handleProcessError(error: any) {
return throwError(error || 'Server error');
}

View File

@@ -42,25 +42,25 @@ declare let moment: any;
})
export class ProcessService {
private _tasksApi;
private _tasksApi: TasksApi;
get tasksApi(): TasksApi {
this._tasksApi = this._tasksApi ?? new TasksApi(this.alfrescoApiService.getInstance());
return this._tasksApi;
}
private _processDefinitionsApi;
private _processDefinitionsApi: ProcessDefinitionsApi;
get processDefinitionsApi(): ProcessDefinitionsApi {
this._processDefinitionsApi = this._processDefinitionsApi ?? new ProcessDefinitionsApi(this.alfrescoApiService.getInstance());
return this._processDefinitionsApi;
}
private _processInstancesApi;
private _processInstancesApi: ProcessInstancesApi;
get processInstancesApi(): ProcessInstancesApi {
this._processInstancesApi = this._processInstancesApi ?? new ProcessInstancesApi(this.alfrescoApiService.getInstance());
return this._processInstancesApi;
}
private _processInstanceVariablesApi;
private _processInstanceVariablesApi: ProcessInstanceVariablesApi;
get processInstanceVariablesApi(): ProcessInstanceVariablesApi {
this._processInstanceVariablesApi = this._processInstanceVariablesApi ?? new ProcessInstanceVariablesApi(this.alfrescoApiService.getInstance());
return this._processInstanceVariablesApi;
@@ -71,6 +71,7 @@ export class ProcessService {
/**
* Gets process instances for a filter and optionally a process definition.
*
* @param requestNode Filter for instances
* @param processDefinitionKey Limits returned instances to a process definition
* @returns List of process instances
@@ -93,6 +94,7 @@ export class ProcessService {
/**
* Gets processes for a filter and optionally a process definition.
*
* @param requestNode Filter for instances
* @param processDefinitionKey Limits returned instances to a process definition
* @returns List of processes
@@ -100,42 +102,20 @@ export class ProcessService {
getProcesses(requestNode: ProcessFilterParamRepresentationModel, processDefinitionKey?: string): Observable<ProcessListModel> {
return this.getProcessInstances(requestNode, processDefinitionKey)
.pipe(
map(response => {
return {
map(response => ({
...response,
data: (response.data || []).map(instance => {
instance.name = this.getProcessNameOrDescription(instance, 'medium');
return instance;
})
};
}),
})),
catchError(() => of(new ProcessListModel({})))
);
}
private getProcessNameOrDescription(processInstance: ProcessInstanceRepresentation, dateFormat: string): string {
let name = '';
if (processInstance) {
name = processInstance.name ||
processInstance.processDefinitionName + ' - ' + this.getFormatDate(processInstance.started, dateFormat);
}
return name;
}
private getFormatDate(value: Date, format: string) {
const datePipe = new DatePipe('en-US');
try {
return datePipe.transform(value, format);
} catch (err) {
return '';
}
}
/**
* Fetches the Process Audit information as a PDF.
*
* @param processId ID of the target process
* @returns Binary PDF data
*/
@@ -148,6 +128,7 @@ export class ProcessService {
/**
* Fetches the Process Audit information in a JSON format.
*
* @param processId ID of the target process
* @returns JSON data
*/
@@ -160,6 +141,7 @@ export class ProcessService {
/**
* Gets Process Instance metadata.
*
* @param processInstanceId ID of the target process
* @returns Metadata for the instance
*/
@@ -172,16 +154,17 @@ export class ProcessService {
/**
* Gets task instances for a process instance.
*
* @param processInstanceId ID of the process instance
* @param state Task state filter (can be "active" or "completed")
* @returns Array of task instance details
*/
getProcessTasks(processInstanceId: string, state?: string): Observable<TaskDetailsModel[]> {
const taskOpts = state ? {
processInstanceId: processInstanceId,
state: state
processInstanceId,
state
} : {
processInstanceId: processInstanceId
processInstanceId
};
return from(this.tasksApi.listTasks(taskOpts))
.pipe(
@@ -196,6 +179,7 @@ export class ProcessService {
/**
* Gets process definitions associated with an app.
*
* @param appId ID of a target app
* @returns Array of process definitions
*/
@@ -218,6 +202,7 @@ export class ProcessService {
/**
* Starts a process based on a process definition, name, form values or variables.
*
* @param processDefinitionId Process definition ID
* @param name Process name
* @param outcome Process outcome
@@ -227,8 +212,8 @@ export class ProcessService {
*/
startProcess(processDefinitionId: string, name: string, outcome?: string, startFormValues?: FormValues, variables?: ProcessInstanceVariable[]): Observable<ProcessInstance> {
const startRequest: any = {
name: name,
processDefinitionId: processDefinitionId
name,
processDefinitionId
};
if (outcome) {
startRequest.outcome = outcome;
@@ -250,6 +235,7 @@ export class ProcessService {
/**
* Cancels a process instance.
*
* @param processInstanceId ID of process to cancel
* @returns Null response notifying when the operation is complete
*/
@@ -264,6 +250,7 @@ export class ProcessService {
/**
* Gets the variables for a process instance.
*
* @param processInstanceId ID of the target process
* @returns Array of instance variable info
*/
@@ -279,6 +266,7 @@ export class ProcessService {
/**
* Creates or updates variables for a process instance.
*
* @param processInstanceId ID of the target process
* @param variables Variables to update
* @returns Array of instance variable info
@@ -293,6 +281,7 @@ export class ProcessService {
/**
* Deletes a variable for a process instance.
*
* @param processInstanceId ID of the target process
* @param variableName Name of the variable to delete
* @returns Null response notifying when the operation is complete
@@ -313,4 +302,25 @@ export class ProcessService {
private handleProcessError(error: any) {
return throwError(error || 'Server error');
}
private getProcessNameOrDescription(processInstance: ProcessInstanceRepresentation, dateFormat: string): string {
let name = '';
if (processInstance) {
name = processInstance.name ||
processInstance.processDefinitionName + ' - ' + this.getFormatDate(processInstance.started, dateFormat);
}
return name;
}
private getFormatDate(value: Date, format: string) {
const datePipe = new DatePipe('en-US');
try {
return datePipe.transform(value, format);
} catch (err) {
return '';
}
}
}

View File

@@ -28,29 +28,26 @@ import { FormControl, Validators } from '@angular/forms';
})
export class AttachFormComponent implements OnInit, OnChanges {
constructor(private taskService: TaskListService,
private logService: LogService,
private formService: FormService) { }
/** Id of the task. */
@Input()
taskId;
taskId: any;
/** Identifier of the form to attach. */
@Input()
formKey;
formKey: any;
/** Emitted when the "Cancel" button is clicked. */
@Output()
cancelAttachForm: EventEmitter<void> = new EventEmitter<void>();
cancelAttachForm = new EventEmitter<void>();
/** Emitted when the form is attached successfully. */
@Output()
success: EventEmitter<void> = new EventEmitter<void>();
success = new EventEmitter<void>();
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
error = new EventEmitter<any>();
forms: Form[];
@@ -60,6 +57,10 @@ export class AttachFormComponent implements OnInit, OnChanges {
attachFormControl: FormControl;
constructor(private taskService: TaskListService,
private logService: LogService,
private formService: FormService) { }
ngOnInit() {
this.attachFormControl = new FormControl('', Validators.required);
this.attachFormControl.valueChanges.subscribe( (currentValue) => {

View File

@@ -75,7 +75,7 @@ describe('ChecklistComponent', () => {
checklistComponent.readOnly = true;
fixture.detectChanges();
showChecklistDialog = <HTMLElement> element.querySelector('#add-checklist');
showChecklistDialog = element.querySelector<HTMLElement>('#add-checklist');
});
it('should NOT show add checklist button', () => {
@@ -98,7 +98,7 @@ describe('ChecklistComponent', () => {
}));
fixture.detectChanges();
showChecklistDialog = <HTMLElement> element.querySelector('#add-checklist');
showChecklistDialog = element.querySelector<HTMLElement>('#add-checklist');
});
it('should show add checklist button', () => {
@@ -117,7 +117,7 @@ describe('ChecklistComponent', () => {
checklistComponent.checklist = [];
fixture.detectChanges();
showChecklistDialog = <HTMLElement> element.querySelector('#add-checklist');
showChecklistDialog = element.querySelector<HTMLElement>('#add-checklist');
});
it('should show dialog when clicked on add', (done) => {
@@ -139,11 +139,11 @@ describe('ChecklistComponent', () => {
checklistComponent.taskId = 'fake-task-id';
checklistComponent.checklist = [];
fixture.detectChanges();
showChecklistDialog = <HTMLElement> element.querySelector('#add-checklist');
showChecklistDialog = element.querySelector<HTMLElement>('#add-checklist');
});
afterEach(() => {
const overlayContainers = <any> window.document.querySelectorAll('.cdk-overlay-container');
const overlayContainers = window.document.querySelectorAll('.cdk-overlay-container');
overlayContainers.forEach((overlayContainer) => {
overlayContainer.innerHTML = '';
});
@@ -182,7 +182,7 @@ describe('ChecklistComponent', () => {
})));
showChecklistDialog.click();
const addButtonDialog = <HTMLElement> window.document.querySelector('#add-check');
const addButtonDialog = window.document.querySelector<HTMLElement>('#add-check');
addButtonDialog.click();
fixture.detectChanges();
@@ -204,7 +204,7 @@ describe('ChecklistComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const checklistElementRemove = <HTMLElement> element.querySelector('#remove-fake-check-id');
const checklistElementRemove = element.querySelector<HTMLElement>('#remove-fake-check-id');
expect(checklistElementRemove).toBeDefined();
expect(checklistElementRemove).not.toBeNull();
checklistElementRemove.click();
@@ -227,7 +227,7 @@ describe('ChecklistComponent', () => {
await fixture.whenStable();
expect(checklistComponent.checklist.length).toBe(1);
const checklistElementRemove = <HTMLElement> element.querySelector('#remove-fake-check-id');
const checklistElementRemove = element.querySelector<HTMLElement>('#remove-fake-check-id');
expect(checklistElementRemove).toBeDefined();
expect(checklistElementRemove).not.toBeNull();
checklistElementRemove.click();
@@ -290,7 +290,7 @@ describe('ChecklistComponent', () => {
done();
});
showChecklistDialog.click();
const addButtonDialog = <HTMLElement> window.document.querySelector('#add-check');
const addButtonDialog = window.document.querySelector<HTMLElement>('#add-check');
addButtonDialog.click();
});
});

View File

@@ -45,7 +45,7 @@ export class ChecklistComponent implements OnChanges {
/** Emitted when a new checklist task is created. */
@Output()
checklistTaskCreated: EventEmitter<TaskDetailsModel> = new EventEmitter<TaskDetailsModel>();
checklistTaskCreated = new EventEmitter<TaskDetailsModel>();
/** Emitted when a checklist task is deleted. */
@Output()
@@ -53,7 +53,7 @@ export class ChecklistComponent implements OnChanges {
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
error = new EventEmitter<any>();
@ViewChild('dialog', { static: true })
addNewDialog: any;
@@ -62,11 +62,6 @@ export class ChecklistComponent implements OnChanges {
checklist: TaskDetailsModel [] = [];
/**
* Constructor
* @param auth
* @param translate
*/
constructor(private activitiTaskList: TaskListService,
private dialog: MatDialog) {
}

View File

@@ -98,7 +98,7 @@ describe('StartTaskComponent', () => {
const successSpy = spyOn(component.success, 'emit');
component.taskForm.controls['name'].setValue('task');
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(successSpy).toHaveBeenCalled();
});
@@ -108,7 +108,7 @@ describe('StartTaskComponent', () => {
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
component.taskForm.controls['name'].setValue('fakeName');
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(successSpy).toHaveBeenCalledWith({
id: 91,
@@ -123,7 +123,7 @@ describe('StartTaskComponent', () => {
component.appId = 42;
component.taskForm.controls['name'].setValue('fakeName');
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(successSpy).toHaveBeenCalled();
});
@@ -132,7 +132,7 @@ describe('StartTaskComponent', () => {
const successSpy = spyOn(component.success, 'emit');
component.taskDetailsModel = new TaskDetailsModel(null);
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(createNewTaskSpy).not.toHaveBeenCalled();
expect(successSpy).not.toHaveBeenCalled();
@@ -166,7 +166,7 @@ describe('StartTaskComponent', () => {
component.appId = 42;
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(successSpy).toHaveBeenCalledWith({
id: 91,
@@ -191,7 +191,7 @@ describe('StartTaskComponent', () => {
component.appId = 42;
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(successSpy).toHaveBeenCalledWith({
id: 91,
@@ -237,7 +237,7 @@ describe('StartTaskComponent', () => {
component.appId = 42;
component.assigneeId = testUser.id;
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(successSpy).toHaveBeenCalledWith({
id: 91,
@@ -255,7 +255,7 @@ describe('StartTaskComponent', () => {
component.appId = 42;
component.getAssigneeId(testUser.id);
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(successSpy).toHaveBeenCalledWith({
id: 91,
@@ -273,7 +273,7 @@ describe('StartTaskComponent', () => {
component.assigneeId = null;
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
createTaskButton.click();
expect(successSpy).toHaveBeenCalledWith({
id: 91,
@@ -289,7 +289,7 @@ describe('StartTaskComponent', () => {
spyOn(service, 'createNewTask').and.returnValue(of(new TaskDetailsModel({ id: 'task-id'})));
component.taskForm.controls['name'].setValue('fakeName');
fixture.detectChanges();
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
fixture.detectChanges();
createTaskButton.click();
expect(attachFormToATask).not.toHaveBeenCalled();
@@ -333,7 +333,7 @@ describe('StartTaskComponent', () => {
it('should cancel start task on cancel button click', () => {
const emitSpy = spyOn(component.cancel, 'emit');
const cancelTaskButton = <HTMLElement> element.querySelector('#button-cancel');
const cancelTaskButton = element.querySelector<HTMLElement>('#button-cancel');
fixture.detectChanges();
cancelTaskButton.click();
expect(emitSpy).not.toBeNull();
@@ -355,10 +355,10 @@ describe('StartTaskComponent', () => {
});
it('should get formatted fullname', () => {
const testUser1 = { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' };
const testUser2 = { 'id': 1002, 'firstName': '', 'lastName': 'Adams', 'email': 'adams@app.activiti.com' };
const testUser3 = { 'id': 1003, 'firstName': 'Wilbur', 'lastName': '', 'email': 'wilbur@app.activiti.com' };
const testUser4 = { 'id': 1004, 'firstName': '', 'lastName': '', 'email': 'test@app.activiti.com' };
const testUser1 = { id: 1001, firstName: 'Wilbur', lastName: 'Adams', email: 'wilbur@app.activiti.com' };
const testUser2 = { id: 1002, firstName: '', lastName: 'Adams', email: 'adams@app.activiti.com' };
const testUser3 = { id: 1003, firstName: 'Wilbur', lastName: '', email: 'wilbur@app.activiti.com' };
const testUser4 = { id: 1004, firstName: '', lastName: '', email: 'test@app.activiti.com' };
const testFullName1 = component.getDisplayUser(testUser1.firstName, testUser1.lastName, ' ');
const testFullName2 = component.getDisplayUser(testUser2.firstName, testUser2.lastName, ' ');
@@ -375,7 +375,7 @@ describe('StartTaskComponent', () => {
component.taskForm.controls['name'].setValue('fakeName');
const errorSpy = spyOn(component.error, 'emit');
spyOn(service, 'createNewTask').and.returnValue(throwError({}));
const createTaskButton = <HTMLElement> element.querySelector('#button-start');
const createTaskButton = element.querySelector<HTMLElement>('#button-start');
fixture.detectChanges();
createTaskButton.click();
expect(errorSpy).toHaveBeenCalled();

View File

@@ -30,6 +30,9 @@ import { TaskListService } from './../services/tasklist.service';
import { switchMap, defaultIfEmpty, takeUntil } from 'rxjs/operators';
import { FormBuilder, AbstractControl, Validators, FormGroup, FormControl } from '@angular/forms';
const FORMAT_DATE = 'DD/MM/YYYY';
const MAX_LENGTH = 255;
@Component({
selector: 'adf-start-task',
templateUrl: './start-task.component.html',
@@ -40,10 +43,6 @@ import { FormBuilder, AbstractControl, Validators, FormGroup, FormControl } from
encapsulation: ViewEncapsulation.None
})
export class StartTaskComponent implements OnInit, OnDestroy {
public FORMAT_DATE: string = 'DD/MM/YYYY';
MAX_LENGTH: number = 255;
/** (required) The id of the app. */
@Input()
appId: number;
@@ -54,15 +53,15 @@ export class StartTaskComponent implements OnInit, OnDestroy {
/** Emitted when the task is successfully created. */
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
success = new EventEmitter<any>();
/** Emitted when the cancel button is clicked by the user. */
@Output()
cancel: EventEmitter<void> = new EventEmitter<void>();
cancel = new EventEmitter<void>();
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
error = new EventEmitter<any>();
taskDetailsModel: TaskDetailsModel = new TaskDetailsModel();
forms$: Observable<Form[]>;
@@ -70,17 +69,11 @@ export class StartTaskComponent implements OnInit, OnDestroy {
field: FormFieldModel;
taskForm: FormGroup;
dateError: boolean = false;
maxTaskNameLength: number = this.MAX_LENGTH;
maxTaskNameLength: number = MAX_LENGTH;
loading = false;
private onDestroy$ = new Subject<boolean>();
/**
* Constructor
* @param auth
* @param translate
* @param taskService
*/
constructor(private taskService: TaskListService,
private dateAdapter: DateAdapter<Moment>,
private userPreferencesService: UserPreferencesService,
@@ -127,7 +120,7 @@ export class StartTaskComponent implements OnInit, OnDestroy {
if (control.value) {
const isWhitespace = (control.value || '').trim().length === 0;
const isValid = control.value.length === 0 || !isWhitespace;
return isValid ? null : { 'whitespace': true };
return isValid ? null : { whitespace: true };
}
return null;
}
@@ -176,38 +169,14 @@ export class StartTaskComponent implements OnInit, OnDestroy {
this.assigneeId = userId;
}
private attachForm(taskId: string, formKey: string): Observable<any> {
let response = of();
if (taskId && formKey) {
response = this.taskService.attachFormToATask(taskId, parseInt(formKey, 10));
}
return response;
}
private assignTaskByUserId(taskId: string, userId: any): Observable<any> {
let response = of();
if (taskId && userId) {
response = this.taskService.assignTaskByUserId(taskId, userId);
}
return response;
}
onCancel(): void {
this.cancel.emit();
}
private loadFormsTask(): void {
this.forms$ = this.taskService.getFormList();
}
isUserNameEmpty(user: UserProcessModel): boolean {
return !user || (this.isEmpty(user.firstName) && this.isEmpty(user.lastName));
}
private isEmpty(data: string): boolean {
return data === undefined || data === null || data.trim().length === 0;
}
getDisplayUser(firstName: string, lastName: string, delimiter: string = '-'): string {
firstName = (firstName !== null ? firstName : '');
lastName = (lastName !== null ? lastName : '');
@@ -221,7 +190,7 @@ export class StartTaskComponent implements OnInit, OnDestroy {
let momentDate: moment.Moment;
if (typeof newDateValue === 'string') {
momentDate = moment(newDateValue, this.FORMAT_DATE, true);
momentDate = moment(newDateValue, FORMAT_DATE, true);
} else {
momentDate = newDateValue;
}
@@ -238,9 +207,9 @@ export class StartTaskComponent implements OnInit, OnDestroy {
}
private validateMaxTaskNameLength() {
if (this.maxTaskNameLength > this.MAX_LENGTH) {
this.maxTaskNameLength = this.MAX_LENGTH;
this.logService.log(`the task name length cannot be greater than ${this.MAX_LENGTH}`);
if (this.maxTaskNameLength > MAX_LENGTH) {
this.maxTaskNameLength = MAX_LENGTH;
this.logService.log(`the task name length cannot be greater than ${MAX_LENGTH}`);
}
}
@@ -255,4 +224,28 @@ export class StartTaskComponent implements OnInit, OnDestroy {
get formKeyController(): AbstractControl {
return this.taskForm.get('formKey');
}
private attachForm(taskId: string, formKey: string): Observable<any> {
let response = of();
if (taskId && formKey) {
response = this.taskService.attachFormToATask(taskId, parseInt(formKey, 10));
}
return response;
}
private assignTaskByUserId(taskId: string, userId: any): Observable<any> {
let response = of();
if (taskId && userId) {
response = this.taskService.assignTaskByUserId(taskId, userId);
}
return response;
}
private loadFormsTask(): void {
this.forms$ = this.taskService.getFormList();
}
private isEmpty(data: string): boolean {
return data === undefined || data === null || data.trim().length === 0;
}
}

View File

@@ -52,7 +52,7 @@ describe('TaskAuditDirective', () => {
let component: BasicButtonComponent;
let service: TaskListService;
function createFakePdfBlob(): Blob {
const createFakePdfBlob = (): Blob => {
const pdfData = atob(
'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' +
'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' +
@@ -68,7 +68,7 @@ describe('TaskAuditDirective', () => {
'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G');
return new Blob([pdfData], {type: 'application/pdf'});
}
};
setupTestBed({
imports: [

View File

@@ -28,7 +28,7 @@ const PDF_FORMAT: string = 'pdf';
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'button[adf-task-audit]',
host: {
'role': 'button',
role: 'button',
'(click)': 'onClickAudit()'
}
})

View File

@@ -208,7 +208,7 @@ describe('TaskDetailsComponent', () => {
});
it('should fetch new task details when taskId changed', () => {
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
expect(getTaskDetailsSpy).toHaveBeenCalledWith('456');
});
@@ -223,13 +223,13 @@ describe('TaskDetailsComponent', () => {
it('should NOT fetch new task details when taskId changed to null', fakeAsync(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
component.ngOnChanges({ 'taskId': nullChange });
component.ngOnChanges({ taskId: nullChange });
expect(getTaskDetailsSpy).not.toHaveBeenCalled();
});
}));
it('should set a placeholder message when taskId changed to null', () => {
component.ngOnChanges({ 'taskId': nullChange });
component.ngOnChanges({ taskId: nullChange });
fixture.detectChanges();
expect(fixture.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.MESSAGES.NONE');
});
@@ -243,7 +243,7 @@ describe('TaskDetailsComponent', () => {
});
afterEach(() => {
const overlayContainers = <any> window.document.querySelectorAll('.cdk-overlay-container');
const overlayContainers = window.document.querySelectorAll('.cdk-overlay-container');
overlayContainers.forEach((overlayContainer) => {
overlayContainer.innerHTML = '';
@@ -340,7 +340,7 @@ describe('TaskDetailsComponent', () => {
it('should comments be readonly if the task is complete and no user are involved', () => {
component.showComments = true;
component.showHeaderContent = true;
component.ngOnChanges({ 'taskId': new SimpleChange('123', '456', true) });
component.ngOnChanges({ taskId: new SimpleChange('123', '456', true) });
component.taskPeople = [];
component.taskDetails = new TaskDetailsModel(taskDetailsMock);
component.taskDetails.endDate = new Date('2017-10-03T17:03:57.311+0000');
@@ -352,7 +352,7 @@ describe('TaskDetailsComponent', () => {
it('should comments be readonly if the task is complete and user are NOT involved', () => {
component.showComments = true;
component.showHeaderContent = true;
component.ngOnChanges({ 'taskId': new SimpleChange('123', '456', true) });
component.ngOnChanges({ taskId: new SimpleChange('123', '456', true) });
component.taskPeople = [];
component.taskDetails = new TaskDetailsModel(taskDetailsMock);
component.taskDetails.endDate = new Date('2017-10-03T17:03:57.311+0000');
@@ -364,7 +364,7 @@ describe('TaskDetailsComponent', () => {
it('should comments NOT be readonly if the task is NOT complete and user are NOT involved', () => {
component.showComments = true;
component.showHeaderContent = true;
component.ngOnChanges({ 'taskId': new SimpleChange('123', '456', true) });
component.ngOnChanges({ taskId: new SimpleChange('123', '456', true) });
component.taskPeople = [fakeUser];
component.taskDetails = new TaskDetailsModel(taskDetailsMock);
component.taskDetails.endDate = null;
@@ -376,7 +376,7 @@ describe('TaskDetailsComponent', () => {
it('should comments NOT be readonly if the task is complete and user are involved', () => {
component.showComments = true;
component.showHeaderContent = true;
component.ngOnChanges({ 'taskId': new SimpleChange('123', '456', true) });
component.ngOnChanges({ taskId: new SimpleChange('123', '456', true) });
component.taskPeople = [fakeUser];
component.taskDetails = new TaskDetailsModel(taskDetailsMock);
component.taskDetails.endDate = new Date('2017-10-03T17:03:57.311+0000');
@@ -388,7 +388,7 @@ describe('TaskDetailsComponent', () => {
it('should comments be present if showComments is true', () => {
component.showComments = true;
component.showHeaderContent = true;
component.ngOnChanges({ 'taskId': new SimpleChange('123', '456', true) });
component.ngOnChanges({ taskId: new SimpleChange('123', '456', true) });
component.taskPeople = [];
component.taskDetails = new TaskDetailsModel(taskDetailsMock);
@@ -398,7 +398,7 @@ describe('TaskDetailsComponent', () => {
it('should comments NOT be present if showComments is false', () => {
component.showComments = false;
component.ngOnChanges({ 'taskId': new SimpleChange('123', '456', true) });
component.ngOnChanges({ taskId: new SimpleChange('123', '456', true) });
component.taskPeople = [];
component.taskDetails = new TaskDetailsModel(taskDetailsMock);

View File

@@ -123,23 +123,23 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
/** Emitted when the form is submitted with the `Save` or custom outcomes. */
@Output()
formSaved: EventEmitter<FormModel> = new EventEmitter<FormModel>();
formSaved = new EventEmitter<FormModel>();
/** Emitted when the form is submitted with the `Complete` outcome. */
@Output()
formCompleted: EventEmitter<FormModel> = new EventEmitter<FormModel>();
formCompleted = new EventEmitter<FormModel>();
/** Emitted when the form field content is clicked. */
@Output()
formContentClicked: EventEmitter<ContentLinkModel> = new EventEmitter<ContentLinkModel>();
formContentClicked = new EventEmitter<ContentLinkModel>();
/** Emitted when the form is loaded or reloaded. */
@Output()
formLoaded: EventEmitter<FormModel> = new EventEmitter<FormModel>();
formLoaded = new EventEmitter<FormModel>();
/** Emitted when a checklist task is created. */
@Output()
taskCreated: EventEmitter<TaskDetailsModel> = new EventEmitter<TaskDetailsModel>();
taskCreated = new EventEmitter<TaskDetailsModel>();
/** Emitted when a checklist task is deleted. */
@Output()
@@ -147,13 +147,13 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
error = new EventEmitter<any>();
/** Emitted when any outcome is executed. Default behaviour can be prevented
* via `event.preventDefault()`.
*/
@Output()
executeOutcome: EventEmitter<FormOutcomeEvent> = new EventEmitter<FormOutcomeEvent>();
executeOutcome = new EventEmitter<FormOutcomeEvent>();
/** Emitted when a task is assigned. */
@Output()
@@ -161,11 +161,11 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
/** Emitted when a task is claimed. */
@Output()
claimedTask: EventEmitter<string> = new EventEmitter<string>();
claimedTask = new EventEmitter<string>();
/** Emitted when a task is unclaimed. */
@Output()
unClaimedTask: EventEmitter<string> = new EventEmitter<string>();
unClaimedTask = new EventEmitter<string>();
taskDetails: TaskDetailsModel;
taskFormName: string = null;
@@ -174,15 +174,13 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
showAssignee: boolean = false;
showAttachForm: boolean = false;
internalReadOnlyForm: boolean = false;
errorDialogRef: MatDialogRef<TemplateRef<any>>;
peopleSearch: Observable<UserProcessModel[]>;
data: any;
private peopleSearchObserver: Observer<UserProcessModel[]>;
public errorDialogRef: MatDialogRef<TemplateRef<any>>;
private onDestroy$ = new Subject<boolean>();
peopleSearch: Observable<UserProcessModel[]>;
data: any;
constructor(private taskListService: TaskListService,
private peopleProcessService: PeopleProcessService,
private logService: LogService,
@@ -226,102 +224,14 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
return this.showAttachForm;
}
/**
* Reset the task details
*/
private reset() {
this.taskDetails = null;
}
isTaskActive() {
return this.taskDetails && this.taskDetails.duration === null;
}
/**
* Save a task detail and update it after a successful response
*
* @param updateNotification
*/
private updateTaskDetails(updateNotification: UpdateNotification) {
this.taskListService
.updateTask(this.taskId, updateNotification.changed)
.pipe(catchError(() => {
this.cardViewUpdateService.updateElement(updateNotification.target);
return of(null);
}))
.subscribe(() => this.loadDetails(this.taskId));
}
private clickTaskDetails(clickNotification: ClickNotification) {
if (clickNotification.target.key === 'assignee') {
this.showAssignee = true;
}
if (clickNotification.target.key === 'formName') {
this.showAttachForm = true;
}
}
/**
* Load the activiti task details
* @param taskId
*/
private loadDetails(taskId: string) {
this.taskPeople = [];
if (taskId) {
this.taskListService.getTaskDetails(taskId).subscribe(
(res: TaskDetailsModel) => {
this.showAttachForm = false;
this.taskDetails = res;
if (this.taskDetails.name === 'null') {
this.taskDetails.name = 'No name';
}
const endDate: any = res.endDate;
if (endDate && !isNaN(endDate.getTime())) {
this.internalReadOnlyForm = true;
} else {
this.internalReadOnlyForm = this.readOnlyForm;
}
if (this.taskDetails && this.taskDetails.involvedPeople) {
this.taskDetails.involvedPeople.forEach((user) => {
this.taskPeople.push(new UserProcessModel(user));
});
}
});
}
}
isAssigned(): boolean {
return !!this.taskDetails.assignee;
}
/**
* Retrieve the next open task
* @param processInstanceId
* @param processDefinitionId
*/
private loadNextTask(processInstanceId: string, processDefinitionId: string): void {
const requestNode = new TaskQueryRequestRepresentationModel(
{
processInstanceId: processInstanceId,
processDefinitionId: processDefinitionId
}
);
this.taskListService.getTasks(requestNode).subscribe(
(response) => {
if (response && response.length > 0) {
this.taskDetails = new TaskDetailsModel(response[0]);
} else {
this.reset();
}
}, (error) => {
this.error.emit(error);
});
}
/**
* Complete button clicked
*/
@@ -431,4 +341,75 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
isReadOnlyComment(): boolean {
return (this.taskDetails && this.taskDetails.isCompleted()) && (this.taskPeople && this.taskPeople.length === 0);
}
private reset() {
this.taskDetails = null;
}
private updateTaskDetails(updateNotification: UpdateNotification) {
this.taskListService
.updateTask(this.taskId, updateNotification.changed)
.pipe(catchError(() => {
this.cardViewUpdateService.updateElement(updateNotification.target);
return of(null);
}))
.subscribe(() => this.loadDetails(this.taskId));
}
private clickTaskDetails(clickNotification: ClickNotification) {
if (clickNotification.target.key === 'assignee') {
this.showAssignee = true;
}
if (clickNotification.target.key === 'formName') {
this.showAttachForm = true;
}
}
private loadDetails(taskId: string) {
this.taskPeople = [];
if (taskId) {
this.taskListService.getTaskDetails(taskId).subscribe(
(res: TaskDetailsModel) => {
this.showAttachForm = false;
this.taskDetails = res;
if (this.taskDetails.name === 'null') {
this.taskDetails.name = 'No name';
}
const endDate: any = res.endDate;
if (endDate && !isNaN(endDate.getTime())) {
this.internalReadOnlyForm = true;
} else {
this.internalReadOnlyForm = this.readOnlyForm;
}
if (this.taskDetails && this.taskDetails.involvedPeople) {
this.taskDetails.involvedPeople.forEach((user) => {
this.taskPeople.push(new UserProcessModel(user));
});
}
});
}
}
private loadNextTask(processInstanceId: string, processDefinitionId: string): void {
const requestNode = new TaskQueryRequestRepresentationModel(
{
processInstanceId,
processDefinitionId
}
);
this.taskListService.getTasks(requestNode).subscribe(
(response) => {
if (response && response.length > 0) {
this.taskDetails = new TaskDetailsModel(response[0]);
} else {
this.reset();
}
}, (error) => {
this.error.emit(error);
});
}
}

View File

@@ -64,7 +64,7 @@ describe('TaskFiltersComponent', () => {
const appId = '1';
const change = new SimpleChange(null, appId, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
component.error.subscribe((err) => {
expect(err).toBeDefined();
@@ -88,7 +88,7 @@ describe('TaskFiltersComponent', () => {
});
component.ngOnInit();
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -100,7 +100,7 @@ describe('TaskFiltersComponent', () => {
const createDefaultFiltersSpy = spyOn(taskFilterService, 'createDefaultFilters').and.returnValue(of(filtersMock));
const appId = '2';
const change = new SimpleChange(null, appId, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
expect(createDefaultFiltersSpy).toHaveBeenCalledWith(appId);
@@ -120,7 +120,7 @@ describe('TaskFiltersComponent', () => {
});
component.ngOnInit();
component.ngOnChanges({ 'appName': change });
component.ngOnChanges({ appName: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -142,7 +142,7 @@ describe('TaskFiltersComponent', () => {
done();
});
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
});
@@ -161,7 +161,7 @@ describe('TaskFiltersComponent', () => {
done();
});
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
});
@@ -181,7 +181,7 @@ describe('TaskFiltersComponent', () => {
done();
});
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
});
@@ -201,7 +201,7 @@ describe('TaskFiltersComponent', () => {
done();
});
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
});
@@ -214,7 +214,7 @@ describe('TaskFiltersComponent', () => {
const change = new SimpleChange(null, filterParam, true);
component.filterParam = filterParam;
component.ngOnChanges({ 'filterParam': change });
component.ngOnChanges({ filterParam: change });
fixture.detectChanges();
expect(component.filterSelected.emit).toHaveBeenCalledWith(fakeTaskFilters[0]);
@@ -238,7 +238,7 @@ describe('TaskFiltersComponent', () => {
const appId = '1';
const change = new SimpleChange(null, appId, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
expect(component.getFiltersByAppId).toHaveBeenCalledWith(appId);
});
@@ -248,7 +248,7 @@ describe('TaskFiltersComponent', () => {
const appId = null;
const change = new SimpleChange(undefined, appId, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
expect(component.getFiltersByAppId).toHaveBeenCalledWith(appId);
});
@@ -261,7 +261,7 @@ describe('TaskFiltersComponent', () => {
expect(component.currentFilter.id).toEqual(fakeTaskFilters[2].id);
});
const change = new SimpleChange(null, { id: fakeTaskFilters[2].id }, true);
component.ngOnChanges({ 'filterParam': change });
component.ngOnChanges({ filterParam: change });
});
it('should change current filter when filterParam (name) changes', async () => {
@@ -273,7 +273,7 @@ describe('TaskFiltersComponent', () => {
});
const change = new SimpleChange(null, { name: fakeTaskFilters[2].name }, true);
component.ngOnChanges({ 'filterParam': change });
component.ngOnChanges({ filterParam: change });
});
it('should reload filters by app name on binding changes', () => {
@@ -281,7 +281,7 @@ describe('TaskFiltersComponent', () => {
const appName = 'fake-app-name';
const change = new SimpleChange(null, appName, true);
component.ngOnChanges({ 'appName': change });
component.ngOnChanges({ appName: change });
expect(component.getFiltersByAppName).toHaveBeenCalledWith(appName);
});
@@ -298,7 +298,7 @@ describe('TaskFiltersComponent', () => {
spyOn(component, 'getFiltersByAppId').and.stub();
const change = new SimpleChange(undefined, null, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
expect(component.getFiltersByAppId).toHaveBeenCalled();
});
@@ -320,7 +320,7 @@ describe('TaskFiltersComponent', () => {
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(of(fakeTaskFilters));
component.showIcon = true;
const change = new SimpleChange(undefined, 1, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -338,7 +338,7 @@ describe('TaskFiltersComponent', () => {
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(of(fakeTaskFilters));
component.showIcon = false;
const change = new SimpleChange(undefined, 1, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -354,7 +354,7 @@ describe('TaskFiltersComponent', () => {
component.filterParam = new FilterRepresentationModel( {name: 'non-existing-filter'});
const appId = '1';
const change = new SimpleChange(null, appId, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
expect(component.currentFilter).toBe(undefined);
@@ -372,7 +372,7 @@ describe('TaskFiltersComponent', () => {
spyOn(taskFilterService, 'createDefaultFilters').and.returnValue(of(defaultTaskFiltersMock));
const appId = '2';
const change = new SimpleChange(null, appId, true);
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
fixture.detectChanges();

View File

@@ -240,6 +240,13 @@ export class TaskFiltersComponent implements OnInit, OnChanges {
return this.filters === undefined || (this.filters && this.filters.length === 0);
}
/**
* Return current filter icon
*/
getFilterIcon(icon): string {
return this.iconsMDL.mapGlyphiconToMaterialDesignIcons(icon);
}
/**
* Reset the filters properties
*/
@@ -247,11 +254,4 @@ export class TaskFiltersComponent implements OnInit, OnChanges {
this.filters = [];
this.currentFilter = undefined;
}
/**
* Return current filter icon
*/
getFilterIcon(icon): string {
return this.iconsMDL.mapGlyphiconToMaterialDesignIcons(icon);
}
}

View File

@@ -29,9 +29,10 @@ describe('ClaimTaskDirective', () => {
template: '<button adf-claim-task [taskId]="taskId" (success)="onClaim($event)">Claim</button>'
})
class TestComponent {
taskId = 'test1234';
@Output()
claim: EventEmitter<any> = new EventEmitter<any>();
claim = new EventEmitter<any>();
taskId = 'test1234';
onClaim(event) {
this.claim.emit(event);
@@ -65,7 +66,7 @@ describe('ClaimTaskDirective', () => {
expect(claimTaskSpy).toHaveBeenCalledWith(fixture.componentInstance.taskId);
});
it('Should be able to catch success event on click of claim button', async() => {
it('Should be able to catch success event on click of claim button', async () => {
spyOn(taskListService, 'claimTask').and.returnValue(of(null));
const unclaimSpy = spyOn(fixture.componentInstance.claim, 'emit');

View File

@@ -49,6 +49,15 @@ export class ClaimTaskDirective implements OnInit {
private taskListService: TaskListService,
private logService: LogService) {}
@HostListener('click')
onClick() {
try {
this.claimTask();
} catch (error) {
this.error.emit(error);
}
}
ngOnInit() {
this.validateInputs();
}
@@ -69,15 +78,6 @@ export class ClaimTaskDirective implements OnInit {
return this.taskId && this.taskId.length > 0;
}
@HostListener('click')
onClick() {
try {
this.claimTask();
} catch (error) {
this.error.emit(error);
}
}
private claimTask() {
this.taskListService.claimTask(this.taskId).subscribe(
() => {

View File

@@ -89,7 +89,7 @@ describe('TaskFormComponent', () => {
getBpmLoggedUserSpy = spyOn(authService, 'getBpmLoggedUser').and.returnValue(of(fakeUser));
});
afterEach(async() => {
afterEach(async () => {
await fixture.whenStable();
getTaskDetailsSpy.calls.reset();
fixture.destroy();
@@ -97,7 +97,7 @@ describe('TaskFormComponent', () => {
describe('Task with form', () => {
beforeEach(async() => {
beforeEach(async () => {
await fixture.whenStable();
getTaskDetailsSpy.calls.reset();
});
@@ -154,7 +154,7 @@ describe('TaskFormComponent', () => {
describe('change detection', () => {
beforeEach(async() => {
beforeEach(async () => {
component.taskId = '123';
fixture.detectChanges();
await fixture.whenStable();
@@ -163,14 +163,14 @@ describe('TaskFormComponent', () => {
it('should fetch new task details when taskId changed', () => {
const change = new SimpleChange('123', '456', true);
component.ngOnChanges({ 'taskId': change });
component.ngOnChanges({ taskId: change });
fixture.detectChanges();
expect(getTaskDetailsSpy).toHaveBeenCalledWith('123');
});
it('should NOT fetch new task details when taskId changed to null', async () => {
const nullChange = new SimpleChange('123', null, true);
component.ngOnChanges({ 'taskId': nullChange });
component.ngOnChanges({ taskId: nullChange });
fixture.detectChanges();
await fixture.whenStable();
expect(getTaskDetailsSpy).not.toHaveBeenCalled();
@@ -179,14 +179,14 @@ describe('TaskFormComponent', () => {
describe('Task assigned to candidates', () => {
beforeEach(async() => {
beforeEach(async () => {
component.taskId = '123';
fixture.detectChanges();
await fixture.whenStable();
getTaskDetailsSpy.calls.reset();
});
it('Should be able to display form in readonly mode if the task assigned to candidates', async() => {
it('Should be able to display form in readonly mode if the task assigned to candidates', async () => {
getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsMock));
fixture.detectChanges();
await fixture.whenStable();
@@ -258,14 +258,14 @@ describe('TaskFormComponent', () => {
describe('Completed Process Task', () => {
beforeEach(async() => {
beforeEach(async () => {
component.taskId = '123';
fixture.detectChanges();
await fixture.whenStable();
getTaskDetailsSpy.calls.reset();
});
it('Should be able to display form in readonly mode if the task completed', async() => {
it('Should be able to display form in readonly mode if the task completed', async () => {
getTaskDetailsSpy.and.returnValue(of(completedTaskDetailsMock));
fixture.detectChanges();
await fixture.whenStable();
@@ -417,7 +417,7 @@ describe('TaskFormComponent', () => {
expect(noFormMessage.innerText).toContain('ADF_TASK_LIST.STANDALONE_TASK.NO_FORM_MESSAGE');
});
it('Should be able display attach form button for a standalone task without form', async() => {
it('Should be able display attach form button for a standalone task without form', async () => {
const showAttachFormSpy = spyOn(component.showAttachForm, 'emit');
component.taskDetails = new TaskDetailsModel(standaloneTaskWithoutForm);
fixture.detectChanges();
@@ -428,7 +428,7 @@ describe('TaskFormComponent', () => {
expect(showAttachFormSpy).toHaveBeenCalled();
});
it('Should display completed template if standalone task completed', async() => {
it('Should display completed template if standalone task completed', async () => {
component.taskDetails = completedStandaloneTaskWithoutForm;
fixture.detectChanges();
await fixture.whenStable();
@@ -638,7 +638,7 @@ describe('TaskFormComponent', () => {
describe('Claim/Unclaim buttons', () => {
it('should display the claim button if no assignee', async() => {
it('should display the claim button if no assignee', async () => {
getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsMock));
component.taskId = 'mock-task-id';
@@ -649,7 +649,7 @@ describe('TaskFormComponent', () => {
expect(claimButton.nativeElement.innerText).toBe('ADF_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM');
});
it('should not display the claim/requeue button if the task is not claimable ', async() => {
it('should not display the claim/requeue button if the task is not claimable ', async () => {
getTaskDetailsSpy.and.returnValue(of(taskDetailsWithOutCandidateGroup));
component.taskId = 'mock-task-id';
@@ -665,7 +665,7 @@ describe('TaskFormComponent', () => {
expect(claimButton).toBeNull();
});
it('should display the claim button if the task is claimable', async() => {
it('should display the claim button if the task is claimable', async () => {
getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsMock));
component.taskId = 'mock-task-id';
@@ -678,7 +678,7 @@ describe('TaskFormComponent', () => {
expect(claimButton.nativeElement.innerText).toBe('ADF_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM');
});
it('should display the release button if task is claimed by the current logged-in user', async() => {
it('should display the release button if task is claimed by the current logged-in user', async () => {
getBpmLoggedUserSpy.and.returnValue(of(claimedTaskDetailsMock.assignee));
getTaskDetailsSpy.and.returnValue(of(claimedTaskDetailsMock));
@@ -692,7 +692,7 @@ describe('TaskFormComponent', () => {
expect(unclaimButton.nativeElement.innerText).toBe('ADF_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM');
});
it('should not display the release button to logged in user if task is claimed by other candidate member', async() => {
it('should not display the release button to logged in user if task is claimed by other candidate member', async () => {
getTaskDetailsSpy.and.returnValue(of(claimedByGroupMemberMock));
component.taskId = 'mock-task-id';
@@ -705,7 +705,7 @@ describe('TaskFormComponent', () => {
expect(unclaimButton).toBeNull();
});
it('should not display the release button if the task is completed', async() => {
it('should not display the release button if the task is completed', async () => {
getTaskDetailsSpy.and.returnValue(of(completedTaskDetailsMock));
component.taskId = 'mock-task-id';
@@ -815,7 +815,7 @@ describe('TaskFormComponent', () => {
expect(completeButton.disabled).toEqual(true);
});
it('Should be able to save a form for a involved user', async() => {
it('Should be able to save a form for a involved user', async () => {
getTaskDetailsSpy.and.returnValue(of(involvedUserTaskForm));
fixture.detectChanges();
await fixture.whenStable();
@@ -824,7 +824,7 @@ describe('TaskFormComponent', () => {
expect(formService.saveTaskForm).toHaveBeenCalled();
});
it('Should be able to save a form for a involved group user', async() => {
it('Should be able to save a form for a involved group user', async () => {
getTaskDetailsSpy.and.returnValue(of(involvedGroupTaskForm));
fixture.detectChanges();
await fixture.whenStable();
@@ -902,7 +902,7 @@ describe('TaskFormComponent', () => {
expect(inputFieldThree['disabled']).toEqual(true);
});
it('Should task form fields be enabled when the task is claimed', async() => {
it('Should task form fields be enabled when the task is claimed', async () => {
fixture.detectChanges();
getBpmLoggedUserSpy.and.returnValue(of(claimedTaskDetailsMock.assignee));
getTaskDetailsSpy.and.returnValue(of(claimedTaskDetailsMock));
@@ -926,7 +926,7 @@ describe('TaskFormComponent', () => {
describe('Task form action buttons', () => {
it('Should disable Complete button when candidate user is not have a access to the task claimed by another candidate user', async() => {
it('Should disable Complete button when candidate user is not have a access to the task claimed by another candidate user', async () => {
getTaskDetailsSpy.and.returnValue(of(involvedUserTaskForm));
component.taskId = 'mock-task-id';
fixture.detectChanges();
@@ -945,7 +945,7 @@ describe('TaskFormComponent', () => {
expect(releaseButton).toBeNull();
});
it('Should show only the Claim button as enabled before claiming a task with form', async() => {
it('Should show only the Claim button as enabled before claiming a task with form', async () => {
getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsMock));
component.taskId = 'mock-task-id';
fixture.detectChanges();
@@ -965,7 +965,7 @@ describe('TaskFormComponent', () => {
expect(releaseButton).toBeNull();
});
it('Should show only Save/Complete/Release buttons as enabled after claiming a task with form', async() => {
it('Should show only Save/Complete/Release buttons as enabled after claiming a task with form', async () => {
getBpmLoggedUserSpy.and.returnValue(of(claimedTaskDetailsMock.assignee));
getTaskDetailsSpy.and.returnValue(of(claimedTaskDetailsMock));
component.taskId = 'mock-task-id';
@@ -986,7 +986,7 @@ describe('TaskFormComponent', () => {
expect(claimButton).toBeNull();
});
it('Should show only the Claim button as enabled before claiming a task without form', async() => {
it('Should show only the Claim button as enabled before claiming a task without form', async () => {
const claimableTaskDetailsWithoutFormMock = { ...claimableTaskDetailsMock, formKey: null };
getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsWithoutFormMock));
component.taskId = 'mock-task-id';
@@ -1006,7 +1006,7 @@ describe('TaskFormComponent', () => {
expect(releaseButton).toBeNull();
});
it('Should show only Complete/Release buttons as enabled after claiming a task without form', async() => {
it('Should show only Complete/Release buttons as enabled after claiming a task without form', async () => {
const claimedTaskDetailsWithoutFormMock = { ...claimedTaskDetailsMock, formKey: null };
getBpmLoggedUserSpy.and.returnValue(of(claimedTaskDetailsWithoutFormMock.assignee));
getTaskDetailsSpy.and.returnValue(of(claimedTaskDetailsWithoutFormMock));

View File

@@ -94,7 +94,7 @@ export class TaskFormComponent implements OnInit, OnChanges {
/** Emitted when the form associated with the form task is attached. */
@Output()
showAttachForm: EventEmitter<void> = new EventEmitter<void>();
showAttachForm = new EventEmitter<void>();
/** Emitted when any outcome is executed. Default behaviour can be prevented
* via `event.preventDefault()`.
@@ -108,7 +108,7 @@ export class TaskFormComponent implements OnInit, OnChanges {
/** Emitted when the supplied form values have a validation error. */
@Output()
formError: EventEmitter<FormFieldModel[]> = new EventEmitter<FormFieldModel[]>();
formError = new EventEmitter<FormFieldModel[]>();
/** Emitted when an error occurs. */
@Output()
@@ -246,24 +246,12 @@ export class TaskFormComponent implements OnInit, OnChanges {
return !!this.taskDetails.assignee;
}
private hasEmailAddress(): boolean {
return this.taskDetails.assignee.email ? true : false;
}
isAssignedToMe(): boolean {
return this.isAssigned() && this.hasEmailAddress() ?
this.isEmailEqual() :
this.isExternalIdEqual();
}
private isEmailEqual(): boolean {
return (this.taskDetails.assignee && this.currentLoggedUser) && ( this.taskDetails.assignee.email.toLocaleLowerCase() === this.currentLoggedUser.email.toLocaleLowerCase());
}
private isExternalIdEqual(): boolean {
return (this.taskDetails.assignee && this.currentLoggedUser) && (this.taskDetails.assignee.externalId === this.currentLoggedUser.externalId);
}
isCompleteButtonEnabled(): boolean {
return this.isAssignedToMe() || this.canInitiatorComplete();
}
@@ -357,4 +345,16 @@ export class TaskFormComponent implements OnInit, OnChanges {
onUnclaimTaskError(error: any) {
this.error.emit(error);
}
private hasEmailAddress(): boolean {
return this.taskDetails.assignee.email ? true : false;
}
private isEmailEqual(): boolean {
return (this.taskDetails.assignee && this.currentLoggedUser) && ( this.taskDetails.assignee.email.toLocaleLowerCase() === this.currentLoggedUser.email.toLocaleLowerCase());
}
private isExternalIdEqual(): boolean {
return (this.taskDetails.assignee && this.currentLoggedUser) && (this.taskDetails.assignee.externalId === this.currentLoggedUser.externalId);
}
}

View File

@@ -29,9 +29,10 @@ describe('UnclaimTaskDirective', () => {
template: '<button adf-unclaim-task [taskId]="taskId" (success)="onUnclaim($event)">Unclaim</button>'
})
class TestComponent {
taskId = 'test1234';
@Output()
unclaim: EventEmitter<any> = new EventEmitter<any>();
unclaim = new EventEmitter<any>();
taskId = 'test1234';
onUnclaim(event) {
this.unclaim.emit(event);
@@ -65,7 +66,7 @@ describe('UnclaimTaskDirective', () => {
expect(claimTaskSpy).toHaveBeenCalledWith(fixture.componentInstance.taskId);
});
it('Should be able to catch success event on click of unclaim button', async() => {
it('Should be able to catch success event on click of unclaim button', async () => {
spyOn(taskListService, 'unclaimTask').and.returnValue(of(null));
const unclaimSpy = spyOn(fixture.componentInstance.unclaim, 'emit');

View File

@@ -37,11 +37,11 @@ export class UnclaimTaskDirective implements OnInit {
/** Emitted when the task is released. */
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
success = new EventEmitter<any>();
/** Emitted when the task cannot be released. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
error = new EventEmitter<any>();
invalidParams: string[] = [];
@@ -49,6 +49,15 @@ export class UnclaimTaskDirective implements OnInit {
private taskListService: TaskListService,
private logService: LogService) {}
@HostListener('click')
onClick() {
try {
this.unclaimTask();
} catch (error) {
this.error.emit(error);
}
}
ngOnInit() {
this.validateInputs();
}
@@ -68,15 +77,6 @@ export class UnclaimTaskDirective implements OnInit {
return this.taskId && this.taskId.length > 0;
}
@HostListener('click')
onClick() {
try {
this.unclaimTask();
} catch (error) {
this.error.emit(error);
}
}
private unclaimTask() {
this.taskListService.unclaimTask(this.taskId).subscribe(
() => {

View File

@@ -58,14 +58,14 @@ export class TaskHeaderComponent implements OnChanges, OnInit {
@Output()
unclaim: EventEmitter<any> = new EventEmitter<any>();
private currentUserId: number;
properties: any [] = [];
inEdit: boolean = false;
displayDateClearAction = false;
dateFormat: string;
dateLocale: string;
private currentUserId: number;
constructor(private bpmUserService: BpmUserService,
private translationService: TranslationService,
private appConfig: AppConfigService) {
@@ -87,6 +87,120 @@ export class TaskHeaderComponent implements OnChanges, OnInit {
}
}
/**
* Refresh the card data
*/
initData() {
if (this.taskDetails) {
const parentInfoMap = this.getParentInfo();
const defaultProperties = this.initDefaultProperties(parentInfoMap);
const filteredProperties: string[] = this.appConfig.get('adf-task-header.presets.properties');
this.properties = defaultProperties.filter((cardItem) => this.isValidSelection(filteredProperties, cardItem));
}
}
/**
* Refresh the card data
*/
refreshData() {
this.properties = this.properties.map((cardItem) => {
if (cardItem.key === 'formName' && cardItem.value !== this.formName) {
return new CardViewTextItemModel({
label: 'ADF_TASK_LIST.PROPERTIES.FORM_NAME',
value: this.formName,
key: 'formName',
default: this.translationService.instant('ADF_TASK_LIST.PROPERTIES.FORM_NAME_DEFAULT'),
clickable: this.isFormClickable(),
icon: 'create'
});
} else {
return cardItem;
}
});
}
/**
* Return the process parent information
*/
getParentInfo(): Map<string, string> {
if (this.taskDetails.processInstanceId && this.taskDetails.processDefinitionName) {
return new Map([[this.taskDetails.processInstanceId, this.taskDetails.processDefinitionName]]);
}
return new Map();
}
/**
* Does the task have an assignee
*/
hasAssignee(): boolean {
return !!this.taskDetails.assignee;
}
/**
* Returns true if the task is assigned to logged in user
*/
isAssignedTo(userId: number): boolean {
return this.hasAssignee() ? this.taskDetails.assignee.id === userId : false;
}
/**
* Return true if the task assigned
*/
isAssignedToCurrentUser(): boolean {
return this.hasAssignee() && this.isAssignedTo(this.currentUserId);
}
/**
* Return true if the user is a candidate member
*/
isCandidateMember(): boolean {
return this.taskDetails.managerOfCandidateGroup || this.taskDetails.memberOfCandidateGroup || this.taskDetails.memberOfCandidateUsers;
}
/**
* Return true if the task claimable
*/
isTaskClaimable(): boolean {
return !this.hasAssignee() && this.isCandidateMember();
}
/**
* Return true if the task claimed by candidate member.
*/
isTaskClaimedByCandidateMember(): boolean {
return this.isCandidateMember() && this.isAssignedToCurrentUser() && !this.isCompleted();
}
/**
* Returns task's status
*/
getTaskStatus(): string {
return (this.taskDetails && this.taskDetails.isCompleted()) ? 'Completed' : 'Running';
}
onClaimTask(taskId: string) {
this.claim.emit(taskId);
}
onUnclaimTask(taskId: string) {
this.unclaim.emit(taskId);
}
/**
* Returns true if the task is completed
*/
isCompleted(): boolean {
return this.taskDetails && !!this.taskDetails.endDate;
}
isFormClickable(): boolean {
return !!this.formName && !this.isCompleted();
}
getTaskDuration(): string {
return this.taskDetails.duration ? `${this.taskDetails.duration} ms` : '';
}
private initDefaultProperties(parentInfoMap): any[] {
return [
new CardViewTextItemModel(
@@ -206,38 +320,6 @@ export class TaskHeaderComponent implements OnChanges, OnInit {
];
}
/**
* Refresh the card data
*/
initData() {
if (this.taskDetails) {
const parentInfoMap = this.getParentInfo();
const defaultProperties = this.initDefaultProperties(parentInfoMap);
const filteredProperties: string[] = this.appConfig.get('adf-task-header.presets.properties');
this.properties = defaultProperties.filter((cardItem) => this.isValidSelection(filteredProperties, cardItem));
}
}
/**
* Refresh the card data
*/
refreshData() {
this.properties = this.properties.map((cardItem) => {
if (cardItem.key === 'formName' && cardItem.value !== this.formName) {
return new CardViewTextItemModel({
label: 'ADF_TASK_LIST.PROPERTIES.FORM_NAME',
value: this.formName,
key: 'formName',
default: this.translationService.instant('ADF_TASK_LIST.PROPERTIES.FORM_NAME_DEFAULT'),
clickable: this.isFormClickable(),
icon: 'create'
});
} else {
return cardItem;
}
});
}
private isValidSelection(filteredProperties: string[], cardItem: CardViewBaseItemModel): boolean {
return filteredProperties ? filteredProperties.indexOf(cardItem.key) >= 0 : true;
}
@@ -250,86 +332,4 @@ export class TaskHeaderComponent implements OnChanges, OnInit {
this.currentUserId = res ? +res.id : null;
});
}
/**
* Return the process parent information
*/
getParentInfo(): Map<string, string> {
if (this.taskDetails.processInstanceId && this.taskDetails.processDefinitionName) {
return new Map([[this.taskDetails.processInstanceId, this.taskDetails.processDefinitionName]]);
}
return new Map();
}
/**
* Does the task have an assignee
*/
public hasAssignee(): boolean {
return !!this.taskDetails.assignee;
}
/**
* Returns true if the task is assigned to logged in user
*/
public isAssignedTo(userId: number): boolean {
return this.hasAssignee() ? this.taskDetails.assignee.id === userId : false;
}
/**
* Return true if the task assigned
*/
public isAssignedToCurrentUser(): boolean {
return this.hasAssignee() && this.isAssignedTo(this.currentUserId);
}
/**
* Return true if the user is a candidate member
*/
isCandidateMember(): boolean {
return this.taskDetails.managerOfCandidateGroup || this.taskDetails.memberOfCandidateGroup || this.taskDetails.memberOfCandidateUsers;
}
/**
* Return true if the task claimable
*/
public isTaskClaimable(): boolean {
return !this.hasAssignee() && this.isCandidateMember();
}
/**
* Return true if the task claimed by candidate member.
*/
public isTaskClaimedByCandidateMember(): boolean {
return this.isCandidateMember() && this.isAssignedToCurrentUser() && !this.isCompleted();
}
/**
* Returns task's status
*/
getTaskStatus(): string {
return (this.taskDetails && this.taskDetails.isCompleted()) ? 'Completed' : 'Running';
}
onClaimTask(taskId: string) {
this.claim.emit(taskId);
}
onUnclaimTask(taskId: string) {
this.unclaim.emit(taskId);
}
/**
* Returns true if the task is completed
*/
isCompleted(): boolean {
return this.taskDetails && !!this.taskDetails.endDate;
}
isFormClickable(): boolean {
return !!this.formName && !this.isCompleted();
}
getTaskDuration(): string {
return this.taskDetails.duration ? `${this.taskDetails.duration} ms` : '';
}
}

View File

@@ -56,7 +56,7 @@ describe('TaskListComponent', () => {
appConfig.config = Object.assign(appConfig.config, {
'adf-task-list': {
'presets': {
presets: {
fakeCustomSchema
}
}
@@ -158,11 +158,11 @@ describe('TaskListComponent', () => {
done();
});
component.ngAfterContentInit();
component.ngOnChanges({ 'state': state, 'processDefinitionKey': processDefinitionKey, 'assignment': assignment });
component.ngOnChanges({ state, processDefinitionKey, assignment });
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -184,11 +184,11 @@ describe('TaskListComponent', () => {
});
component.ngAfterContentInit();
component.ngOnChanges({ 'state': state, 'processDefinitionKey': processDefinitionKey, 'assignment': assignment });
component.ngOnChanges({ state, processDefinitionKey, assignment });
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -210,11 +210,11 @@ describe('TaskListComponent', () => {
});
component.ngAfterContentInit();
component.ngOnChanges({ 'state': state, 'processInstanceId': processInstanceId, 'assignment': assignment });
component.ngOnChanges({ state, processInstanceId, assignment });
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -236,11 +236,11 @@ describe('TaskListComponent', () => {
});
component.ngAfterContentInit();
component.ngOnChanges({ 'state': state, 'processDefinitionId': processDefinitionId, 'assignment': assignment });
component.ngOnChanges({ state, processDefinitionId, assignment });
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -259,10 +259,10 @@ describe('TaskListComponent', () => {
done();
});
component.ngAfterContentInit();
component.ngOnChanges({ 'state': state, 'afterDate': afterDate });
component.ngOnChanges({ state, afterDate });
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -287,11 +287,11 @@ describe('TaskListComponent', () => {
});
component.ngAfterContentInit();
component.ngOnChanges({ 'state': state, 'processInstanceId': processInstanceId });
component.ngOnChanges({ state, processInstanceId });
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -328,7 +328,7 @@ describe('TaskListComponent', () => {
component.reload();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -363,7 +363,7 @@ describe('TaskListComponent', () => {
component.rows = [{ id: '999', name: 'Fake-name' }];
const landingTaskId = '999';
const change = new SimpleChange(null, landingTaskId, true);
component.ngOnChanges({ 'landingTaskId': change });
component.ngOnChanges({ landingTaskId: change });
expect(component.reload).not.toHaveBeenCalled();
expect(component.rows.length).toEqual(1);
});
@@ -381,10 +381,10 @@ describe('TaskListComponent', () => {
done();
});
component.ngOnChanges({ 'landingTaskId': change });
component.ngOnChanges({ landingTaskId: change });
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -409,10 +409,10 @@ describe('TaskListComponent', () => {
expect(component.rows[1]['name']).toEqual('No name');
done();
});
component.ngOnChanges({ 'appId': change });
component.ngOnChanges({ appId: change });
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -431,10 +431,10 @@ describe('TaskListComponent', () => {
done();
});
component.ngOnChanges({ 'processDefinitionKey': change });
component.ngOnChanges({ processDefinitionKey: change });
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -453,10 +453,10 @@ describe('TaskListComponent', () => {
done();
});
component.ngOnChanges({ 'state': change });
component.ngOnChanges({ state: change });
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -475,10 +475,10 @@ describe('TaskListComponent', () => {
done();
});
component.ngOnChanges({ 'sort': change });
component.ngOnChanges({ sort: change });
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -497,10 +497,10 @@ describe('TaskListComponent', () => {
done();
});
component.ngOnChanges({ 'name': change });
component.ngOnChanges({ name: change });
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -519,10 +519,10 @@ describe('TaskListComponent', () => {
done();
});
component.ngOnChanges({ 'assignment': change });
component.ngOnChanges({ assignment: change });
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeGlobalTask)
});
@@ -532,7 +532,7 @@ describe('TaskListComponent', () => {
it('should update the columns when presetColumn schema changes', () => {
appConfig.config = Object.assign(appConfig.config, {
'adf-task-list': {
'presets': fakeColumnSchema
presets: fakeColumnSchema
}
});
@@ -543,7 +543,7 @@ describe('TaskListComponent', () => {
component.presetColumn = 'fakeMyTasksSchema';
const presetColumnChange = new SimpleChange(null, 'fakeMyTasksSchema', false);
component.ngOnChanges({ 'presetColumn': presetColumnChange });
component.ngOnChanges({ presetColumn: presetColumnChange });
const newColumnSchema = component.mergeJsonAndHtmlSchema();
const expectedColumn1 = new ObjectDataColumn(fakeColumnSchema.fakeMyTasksSchema[0]);
@@ -562,7 +562,7 @@ describe('TaskListComponent', () => {
const processDefinitionKey = new SimpleChange(null, null, true);
const assignment = new SimpleChange(null, 'fake-assignee', true);
component.ngAfterContentInit();
component.ngOnChanges({ 'state': state, 'processDefinitionKey': processDefinitionKey, 'assignment': assignment });
component.ngOnChanges({ state, processDefinitionKey, assignment });
fixture.detectChanges();
await fixture.whenStable();
@@ -584,7 +584,7 @@ describe('TaskListComponent', () => {
const state = new SimpleChange(null, 'open', true);
component.multiselect = true;
component.ngOnChanges({ 'sort': state });
component.ngOnChanges({ sort: state });
fixture.detectChanges();
await fixture.whenStable();
@@ -612,7 +612,7 @@ describe('TaskListComponent', () => {
const state = new SimpleChange(null, 'open', true);
component.multiselect = true;
component.ngOnChanges({ 'sort': state });
component.ngOnChanges({ sort: state });
fixture.detectChanges();
await fixture.whenStable();
@@ -650,7 +650,7 @@ describe('TaskListComponent', () => {
component.multiselect = true;
component.selectionMode = 'none';
component.ngOnChanges({ 'sort': state });
component.ngOnChanges({ sort: state });
fixture.detectChanges();
await fixture.whenStable();
@@ -695,7 +695,7 @@ describe('TaskListComponent', () => {
component.multiselect = true;
component.selectionMode = 'single';
component.ngOnChanges({ 'sort': state });
component.ngOnChanges({ sort: state });
fixture.detectChanges();
const selectTask1 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-0"] .mat-checkbox-inner-container');
@@ -726,7 +726,7 @@ describe('TaskListComponent', () => {
spyOn(taskListService, 'findTasksByState').and.returnValues(of(fakeGlobalTask));
const state = new SimpleChange(null, 'open', true);
component.ngOnChanges({ 'sort': state });
component.ngOnChanges({ sort: state });
fixture.detectChanges();
await fixture.whenStable();
@@ -827,9 +827,7 @@ describe('Task List: Custom EmptyTemplateComponent', () => {
beforeEach(() => {
translateService = TestBed.inject(TranslateService);
taskListService = TestBed.inject(TaskListService);
spyOn(translateService, 'get').and.callFake((key) => {
return of(key);
});
spyOn(translateService, 'get').and.callFake((key: string) => of(key));
spyOn(taskListService, 'findTasksByState').and.returnValue(of(fakeEmptyTask));
fixture = TestBed.createComponent(EmptyTemplateComponent);
fixture.detectChanges();

View File

@@ -32,6 +32,8 @@ import moment from 'moment-es6';
import { takeUntil, finalize } from 'rxjs/operators';
import { TaskDetailsModel } from '../models/task-details.model';
export const PRESET_KEY = 'adf-task-list.presets';
@Component({
selector: 'adf-tasklist',
templateUrl: './task-list.component.html',
@@ -39,16 +41,12 @@ import { TaskDetailsModel } from '../models/task-details.model';
})
export class TaskListComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit {
static PRESET_KEY = 'adf-task-list.presets';
@ContentChild(CustomEmptyContentTemplateDirective)
customEmptyContent: CustomEmptyContentTemplateDirective;
@ContentChild(CustomLoadingContentTemplateDirective)
customLoadingContent: CustomLoadingContentTemplateDirective;
requestNode: TaskQueryRequestRepresentationModel;
/** The id of the app. */
@Input()
appId: number;
@@ -151,10 +149,6 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
@Output()
error = new EventEmitter<any>();
currentInstanceId: string;
selectedInstances: any[];
pagination: BehaviorSubject<PaginationModel>;
/** The page number of the tasks to fetch. */
@Input()
page: number = 0;
@@ -171,6 +165,10 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
@Input()
dueBefore: string;
requestNode: TaskQueryRequestRepresentationModel;
currentInstanceId: string;
selectedInstances: any[];
pagination: BehaviorSubject<PaginationModel>;
rows: any[] = [];
isLoading: boolean = true;
sorting: any[] = ['created', 'desc'];
@@ -189,9 +187,9 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
constructor(private taskListService: TaskListService,
appConfigService: AppConfigService,
private userPreferences: UserPreferencesService) {
super(appConfigService, TaskListComponent.PRESET_KEY, taskPresetsDefaultModel);
super(appConfigService, PRESET_KEY, taskPresetsDefaultModel);
this.pagination = new BehaviorSubject<PaginationModel>(<PaginationModel> {
this.pagination = new BehaviorSubject<PaginationModel>({
maxItems: this.size,
skipCount: 0,
totalItems: 0
@@ -242,28 +240,6 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
}
}
private isSortChanged(changes: SimpleChanges): boolean {
const actualSort = changes['sort'];
return actualSort && actualSort.currentValue && actualSort.currentValue !== actualSort.previousValue;
}
private isPropertyChanged(changes: SimpleChanges): boolean {
let changed: boolean = true;
const landingTaskId = changes['landingTaskId'];
const page = changes['page'];
const size = changes['size'];
if (landingTaskId && landingTaskId.currentValue && this.isEqualToCurrentId(landingTaskId.currentValue)) {
changed = false;
} else if (page && page.currentValue !== page.previousValue) {
changed = true;
} else if (size && size.currentValue !== size.previousValue) {
changed = true;
}
return changed;
}
reload(): void {
if (!this.hasCustomDataSource) {
this.requestNode = this.createRequestNode();
@@ -273,34 +249,6 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
}
}
private load() {
this.isLoading = true;
this.loadTasksByState()
.pipe(finalize(() => this.isLoading = false))
.subscribe(
tasks => {
this.rows = this.optimizeTaskDetails(tasks.data);
this.selectTask(this.landingTaskId);
this.success.emit(tasks);
this.pagination.next({
count: tasks.data.length,
maxItems: this.size,
skipCount: this.page * this.size,
totalItems: tasks.total
});
},
error => {
this.error.emit(error);
});
}
private loadTasksByState(): Observable<TaskListModel> {
return this.requestNode.state === 'all'
? this.taskListService.findAllTasksWithoutState(this.requestNode)
: this.taskListService.findTasksByState(this.requestNode);
}
/**
* Select the task given in input if present
*/
@@ -309,9 +257,7 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
let dataRow = null;
if (taskIdSelected) {
dataRow = this.rows.find((currentRow: any) => {
return currentRow['id'] === taskIdSelected;
});
dataRow = this.rows.find((currentRow: any) => currentRow['id'] === taskIdSelected);
}
if (!dataRow && this.selectFirstRow) {
@@ -336,6 +282,7 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
/**
* Check if the taskId is the same of the selected task
*
* @param taskId
*/
isEqualToCurrentId(taskId: string): boolean {
@@ -377,8 +324,74 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
this.showRowContextMenu.emit(event);
}
updatePagination(params: PaginationModel) {
const needsReload = params.maxItems || params.skipCount;
this.size = params.maxItems;
this.page = this.currentPage(params.skipCount, params.maxItems);
if (needsReload) {
this.reload();
}
}
currentPage(skipCount: number, maxItems: number): number {
return (skipCount && maxItems) ? Math.floor(skipCount / maxItems) : 0;
}
private isSortChanged(changes: SimpleChanges): boolean {
const actualSort = changes['sort'];
return actualSort && actualSort.currentValue && actualSort.currentValue !== actualSort.previousValue;
}
private isPropertyChanged(changes: SimpleChanges): boolean {
let changed: boolean = true;
const landingTaskId = changes['landingTaskId'];
const page = changes['page'];
const size = changes['size'];
if (landingTaskId && landingTaskId.currentValue && this.isEqualToCurrentId(landingTaskId.currentValue)) {
changed = false;
} else if (page && page.currentValue !== page.previousValue) {
changed = true;
} else if (size && size.currentValue !== size.previousValue) {
changed = true;
}
return changed;
}
private load() {
this.isLoading = true;
this.loadTasksByState()
.pipe(finalize(() => this.isLoading = false))
.subscribe(
tasks => {
this.rows = this.optimizeTaskDetails(tasks.data);
this.selectTask(this.landingTaskId);
this.success.emit(tasks);
this.pagination.next({
count: tasks.data.length,
maxItems: this.size,
skipCount: this.page * this.size,
totalItems: tasks.total
});
},
error => {
this.error.emit(error);
});
}
private loadTasksByState(): Observable<TaskListModel> {
return this.requestNode.state === 'all'
? this.taskListService.findAllTasksWithoutState(this.requestNode)
: this.taskListService.findTasksByState(this.requestNode);
}
/**
* Optimize name field
*
* @param instances
*/
private optimizeTaskDetails(instances: TaskDetailsModel[]): TaskDetailsModel[] {
@@ -410,19 +423,4 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
};
return new TaskQueryRequestRepresentationModel(requestNode);
}
updatePagination(params: PaginationModel) {
const needsReload = params.maxItems || params.skipCount;
this.size = params.maxItems;
this.page = this.currentPage(params.skipCount, params.maxItems);
if (needsReload) {
this.reload();
}
}
currentPage(skipCount: number, maxItems: number): number {
return (skipCount && maxItems) ? Math.floor(skipCount / maxItems) : 0;
}
}

View File

@@ -49,15 +49,15 @@ export class TaskStandaloneComponent {
/** Emitted when the "Cancel" button is clicked. */
@Output()
cancel: EventEmitter<void> = new EventEmitter<void>();
cancel = new EventEmitter<void>();
/** Emitted when the form associated with the task is completed. */
@Output()
complete: EventEmitter<void> = new EventEmitter<void>();
complete = new EventEmitter<void>();
/** Emitted when the form associated with the form task is attached. */
@Output()
showAttachForm: EventEmitter<void> = new EventEmitter<void>();
showAttachForm = new EventEmitter<void>();
constructor() { }

View File

@@ -27,10 +27,9 @@ export class TaskListModel {
constructor(input?: any) {
if (input) {
Object.assign(this, input);
if (input.data) {
this.data = input.data.map((item: any) => {
return new TaskDetailsModel(item);
});
this.data = input.data.map((item: any) => new TaskDetailsModel(item));
}
}
}

View File

@@ -15,27 +15,27 @@
* limitations under the License.
*/
export let taskPresetsDefaultModel = {
'default': [
export const taskPresetsDefaultModel = {
default: [
{
'key': 'name',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.NAME',
'sortable': true
key: 'name',
type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.NAME',
sortable: true
},
{
'key': 'created',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.CREATED',
'cssClass': 'hidden',
'sortable': true
key: 'created',
type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.CREATED',
cssClass: 'hidden',
sortable: true
},
{
'key': 'assignee',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.ASSIGNEE',
'cssClass': 'hidden',
'sortable': true
key: 'assignee',
type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.ASSIGNEE',
cssClass: 'hidden',
sortable: true
}
]
};

View File

@@ -57,7 +57,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeFiltersResponse)
});
@@ -75,7 +75,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeFiltersResponse)
});
@@ -94,7 +94,7 @@ describe('Activiti Task filter Service', () => {
);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeFiltersResponse)
});
@@ -120,7 +120,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeAppFilter)
});
@@ -142,7 +142,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.at(0).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 111, name: 'My Tasks', icon: 'fake-icon', recent: false
@@ -150,7 +150,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.at(1).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 222, name: 'Involved Tasks', icon: 'fake-icon', recent: false
@@ -158,7 +158,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.at(2).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 333, name: 'Queued Tasks', icon: 'fake-icon', recent: false
@@ -166,7 +166,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.at(3).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 444, name: 'Completed Tasks', icon: 'fake-icon', recent: false
@@ -197,7 +197,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.at(0).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 111, name: 'My Tasks', icon: 'fake-icon', recent: false
@@ -205,7 +205,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.at(1).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 222, name: 'Involved Tasks', icon: 'fake-icon', recent: false
@@ -213,7 +213,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.at(2).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 333, name: 'Queued Tasks', icon: 'fake-icon', recent: false
@@ -221,7 +221,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.at(3).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
appId: 1001, id: 444, name: 'Completed Tasks', icon: 'fake-icon', recent: false
@@ -244,7 +244,7 @@ describe('Activiti Task filter Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: '2233', name: 'FakeNameFilter', filter: { assignment: 'fake-assignment' }

View File

@@ -27,7 +27,7 @@ import { UserFiltersApi } from '@alfresco/js-api';
})
export class TaskFilterService {
private _userFiltersApi;
private _userFiltersApi: UserFiltersApi;
get userFiltersApi(): UserFiltersApi {
this._userFiltersApi = this._userFiltersApi ?? new UserFiltersApi(this.apiService.getInstance());
return this._userFiltersApi;
@@ -39,6 +39,7 @@ export class TaskFilterService {
/**
* Creates and returns the default filters for a process app.
*
* @param appId ID of the target app
* @returns Array of default filters just created
*/
@@ -103,6 +104,7 @@ export class TaskFilterService {
/**
* Gets all task filters for a process app.
*
* @param appId Optional ID for a specific app
* @returns Array of task filter details
*/
@@ -123,6 +125,7 @@ export class TaskFilterService {
/**
* Gets a task filter by ID.
*
* @param filterId ID of the filter
* @param appId ID of the app for the filter
* @returns Details of task filter
@@ -136,6 +139,7 @@ export class TaskFilterService {
/**
* Gets a task filter by name.
*
* @param taskName Name of the filter
* @param appId ID of the app for the filter
* @returns Details of task filter
@@ -149,27 +153,27 @@ export class TaskFilterService {
/**
* Adds a new task filter
*
* @param filter The new filter to add
* @returns Details of task filter just added
*/
addFilter(filter: FilterRepresentationModel): Observable<FilterRepresentationModel> {
return from(this.userFiltersApi.createUserTaskFilter(filter))
.pipe(
map((response: FilterRepresentationModel) => {
return response;
}),
map((response: FilterRepresentationModel) => response),
catchError((err) => this.handleError(err))
);
}
/**
* Calls `getUserTaskFilters` from the Alfresco JS API.
*
* @param appId ID of the target app
* @returns List of task filters
*/
callApiTaskFilters(appId?: number): Promise<any> {
if (appId) {
return this.userFiltersApi.getUserTaskFilters({ appId: appId });
return this.userFiltersApi.getUserTaskFilters({ appId });
} else {
return this.userFiltersApi.getUserTaskFilters();
}
@@ -177,68 +181,77 @@ export class TaskFilterService {
/**
* Creates and returns a filter for "My Tasks" task instances.
*
* @param appId ID of the target app
* @param index of the filter (optional)
* @returns The newly created filter
*/
getMyTasksFilterInstance(appId: number, index?: number): FilterRepresentationModel {
return new FilterRepresentationModel({
'name': 'My Tasks',
'appId': appId,
'recent': false,
'icon': 'glyphicon-inbox',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'assignee' },
name: 'My Tasks',
appId,
recent: false,
icon: 'glyphicon-inbox',
filter: {
sort: 'created-desc',
name: '',
state: 'open',
assignment: 'assignee'
},
index
});
}
/**
* Creates and returns a filter for "Involved" task instances.
*
* @param appId ID of the target app
* @param index of the filter (optional)
* @returns The newly created filter
*/
getInvolvedTasksFilterInstance(appId: number, index?: number): FilterRepresentationModel {
return new FilterRepresentationModel({
'name': 'Involved Tasks',
'appId': appId,
'recent': false,
'icon': 'glyphicon-align-left',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'involved' },
name: 'Involved Tasks',
appId,
recent: false,
icon: 'glyphicon-align-left',
filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'involved' },
index
});
}
/**
* Creates and returns a filter for "Queued Tasks" task instances.
*
* @param appId ID of the target app
* @param index of the filter (optional)
* @returns The newly created filter
*/
getQueuedTasksFilterInstance(appId: number, index?: number): FilterRepresentationModel {
return new FilterRepresentationModel({
'name': 'Queued Tasks',
'appId': appId,
'recent': false,
'icon': 'glyphicon-record',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'candidate' },
name: 'Queued Tasks',
appId,
recent: false,
icon: 'glyphicon-record',
filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'candidate' },
index
});
}
/**
* Creates and returns a filter for "Completed" task instances.
*
* @param appId ID of the target app
* @param index of the filter (optional)
* @returns The newly created filter
*/
getCompletedTasksFilterInstance(appId: number, index?: number): FilterRepresentationModel {
return new FilterRepresentationModel({
'name': 'Completed Tasks',
'appId': appId,
'recent': true,
'icon': 'glyphicon-ok-sign',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'completed', 'assignment': 'involved' },
name: 'Completed Tasks',
appId,
recent: true,
icon: 'glyphicon-ok-sign',
filter: { sort: 'created-desc', name: '', state: 'completed', assignment: 'involved' },
index
});
}
@@ -247,5 +260,4 @@ export class TaskFilterService {
this.logService.error(error);
return throwError(error || 'Server error');
}
}

View File

@@ -29,8 +29,8 @@ import {
fakeUser2,
secondFakeTaskList
} from '../../mock';
import { fakeRepresentationFilter1, fakeRepresentationFilter2, fakeFilter } from '../../mock/task/task-filters.mock';
import { FilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model';
import { fakeFilter, fakeRepresentationFilter1, fakeRepresentationFilter2 } from '../../mock/task/task-filters.mock';
import { FilterRepresentationModel } from '../models/filter.model';
import { TaskDetailsModel } from '../models/task-details.model';
import { TaskListService } from './tasklist.service';
import { TaskUpdateRepresentation } from '@alfresco/js-api';
@@ -61,7 +61,7 @@ describe('Activiti TaskList Service', () => {
describe('Content tests', () => {
it('should return the task list filtered', (done) => {
service.getTasks(<TaskQueryRequestRepresentationModel> fakeFilter).subscribe((res) => {
service.getTasks(fakeFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
expect(res.start).toEqual(0);
@@ -75,7 +75,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
@@ -85,7 +85,7 @@ describe('Activiti TaskList Service', () => {
spyOn(service, 'getTasks').and.returnValue(of(fakeTaskList));
spyOn(service, 'getTotalTasks').and.returnValue(of(fakeTaskList));
service.findAllTaskByState(<TaskQueryRequestRepresentationModel> fakeFilter, 'open').subscribe((res) => {
service.findAllTaskByState(fakeFilter, 'open').subscribe((res) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
@@ -104,7 +104,7 @@ describe('Activiti TaskList Service', () => {
spyOn(service, 'getTasks').and.returnValue(of(fakeTaskList));
spyOn(service, 'getTotalTasks').and.returnValue(of(fakeTaskList));
service.findAllTaskByState(<TaskQueryRequestRepresentationModel> fakeFilter).subscribe((res) => {
service.findAllTaskByState(fakeFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
expect(res.start).toEqual(0);
@@ -119,7 +119,7 @@ describe('Activiti TaskList Service', () => {
});
it('should return the task list filtered by state', (done) => {
service.findTasksByState(<TaskQueryRequestRepresentationModel> fakeFilter, 'open').subscribe((res) => {
service.findTasksByState(fakeFilter, 'open').subscribe((res) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
expect(res.start).toEqual(0);
@@ -133,14 +133,14 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
});
it('should return the task list filtered', (done) => {
service.findTasksByState(<TaskQueryRequestRepresentationModel> fakeFilter).subscribe((res) => {
service.findTasksByState(fakeFilter).subscribe((res) => {
expect(res.size).toEqual(1);
expect(res.start).toEqual(0);
expect(res.data).toBeDefined();
@@ -153,7 +153,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
@@ -163,7 +163,7 @@ describe('Activiti TaskList Service', () => {
spyOn(service, 'getTasks').and.returnValue(of(fakeTaskList));
spyOn(service, 'getTotalTasks').and.returnValue(of(fakeTaskList));
service.findAllTasksWithoutState(<TaskQueryRequestRepresentationModel> fakeFilter).subscribe((res) => {
service.findAllTasksWithoutState(fakeFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res.data).toBeDefined();
expect(res.data.length).toEqual(2);
@@ -183,7 +183,7 @@ describe('Activiti TaskList Service', () => {
it('Should return both open and completed task', (done) => {
spyOn(service, 'findTasksByState').and.returnValue(of(fakeOpenTaskList));
spyOn(service, 'findAllTaskByState').and.returnValue(of(fakeCompletedTaskList));
service.findAllTasksWithoutState(<TaskQueryRequestRepresentationModel> fakeFilter).subscribe((res) => {
service.findAllTasksWithoutState(fakeFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res.data).toBeDefined();
expect(res.data.length).toEqual(4);
@@ -200,7 +200,7 @@ describe('Activiti TaskList Service', () => {
spyOn(service, 'getTasks').and.returnValue(of(fakeTaskList));
spyOn(service, 'getTotalTasks').and.returnValue(of(fakeTaskList));
service.findAllTasksWithoutState(<TaskQueryRequestRepresentationModel> fakeFilter).subscribe((res) => {
service.findAllTasksWithoutState(fakeFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res.data).toBeDefined();
expect(res.data.length).toEqual(2);
@@ -226,7 +226,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskDetails)
});
@@ -248,7 +248,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTasksChecklist)
});
@@ -274,7 +274,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: '777', name: 'FakeNameTask', description: null, category: null,
@@ -290,7 +290,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json'
});
});
@@ -302,14 +302,14 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
});
it('should return the total number of tasks', (done) => {
service.getTotalTasks(<TaskQueryRequestRepresentationModel> fakeFilter).subscribe((res: any) => {
service.getTotalTasks(fakeFilter).subscribe((res: any) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
expect(res.total).toEqual(1);
@@ -317,7 +317,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
@@ -341,7 +341,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: '777',
@@ -373,7 +373,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: testTaskId,
@@ -405,7 +405,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: testTaskId,
@@ -428,7 +428,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
@@ -442,7 +442,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
@@ -459,7 +459,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
@@ -485,7 +485,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
@@ -508,13 +508,13 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.at(0).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
jasmine.Ajax.requests.at(1).respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(secondFakeTaskList)
});
@@ -532,7 +532,7 @@ describe('Activiti TaskList Service', () => {
});
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeFormList)
});

View File

@@ -33,26 +33,25 @@ import {
providedIn: 'root'
})
export class TaskListService {
private _modelsApi;
private _modelsApi: ModelsApi;
get modelsApi(): ModelsApi {
this._modelsApi = this._modelsApi ?? new ModelsApi(this.apiService.getInstance());
return this._modelsApi;
}
private _tasksApi;
private _tasksApi: TasksApi;
get tasksApi(): TasksApi {
this._tasksApi = this._tasksApi ?? new TasksApi(this.apiService.getInstance());
return this._tasksApi;
}
private _taskActionsApi;
private _taskActionsApi: TaskActionsApi;
get taskActionsApi(): TaskActionsApi {
this._taskActionsApi = this._taskActionsApi ?? new TaskActionsApi(this.apiService.getInstance());
return this._taskActionsApi;
}
private _checklistsApi;
private _checklistsApi: ChecklistsApi;
get checklistsApi(): ChecklistsApi {
this._checklistsApi = this._checklistsApi ?? new ChecklistsApi(this.apiService.getInstance());
return this._checklistsApi;
@@ -64,6 +63,7 @@ export class TaskListService {
/**
* Gets all the filters in the list that belong to a task.
*
* @param taskId ID of the target task
* @param filterList List of filters to search through
* @returns Filters belonging to the task
@@ -76,23 +76,9 @@ export class TaskListService {
);
}
/**
* Gets the search query for a task based on the supplied filter.
* @param filter The filter to use
* @returns The search query
*/
private generateTaskRequestNodeFromFilter(filterModel: FilterRepresentationModel): TaskQueryRequestRepresentationModel {
const requestNode = {
appDefinitionId: filterModel.appId,
assignment: filterModel.filter.assignment,
state: filterModel.filter.state,
sort: filterModel.filter.sort
};
return new TaskQueryRequestRepresentationModel(requestNode);
}
/**
* Checks if a taskId is filtered with the given filter.
*
* @param taskId ID of the target task
* @param filterModel The filter you want to check
* @returns The filter if it is related or null otherwise
@@ -101,15 +87,14 @@ export class TaskListService {
const requestNodeForFilter = this.generateTaskRequestNodeFromFilter(filterModel);
return from(this.callApiTasksFiltered(requestNodeForFilter))
.pipe(
map(res => {
return res.data.find((element) => element.id === taskId) ? filterModel : null;
}),
map(res => res.data.find((element) => element.id === taskId) ? filterModel : null),
catchError((err) => this.handleError(err))
);
}
/**
* Gets all the tasks matching the supplied query.
*
* @param requestNode Query to search for tasks
* @returns List of tasks
*/
@@ -122,6 +107,7 @@ export class TaskListService {
/**
* Gets tasks matching a query and state value.
*
* @param requestNode Query to search for tasks
* @param state Task state. Can be "open" or "completed".
* @returns List of tasks
@@ -136,6 +122,7 @@ export class TaskListService {
/**
* Gets all tasks matching a query and state value.
*
* @param requestNode Query to search for tasks.
* @param state Task state. Can be "open" or "completed".
* @returns List of tasks
@@ -155,6 +142,7 @@ export class TaskListService {
/**
* Gets all tasks matching the supplied query but ignoring the task state.
*
* @param requestNode Query to search for tasks
* @returns List of tasks
*/
@@ -173,21 +161,21 @@ export class TaskListService {
/**
* Gets details for a task.
*
* @param taskId ID of the target task.
* @returns Task details
*/
getTaskDetails(taskId: string): Observable<TaskDetailsModel> {
return from(this.callApiTaskDetails(taskId))
.pipe(
map(details => {
return new TaskDetailsModel(details);
}),
map(details => new TaskDetailsModel(details)),
catchError((err) => this.handleError(err))
);
}
/**
* Gets the checklist for a task.
*
* @param id ID of the target task
* @returns Array of checklist task details
*/
@@ -207,13 +195,14 @@ export class TaskListService {
/**
* Gets all available reusable forms.
*
* @returns Array of form details
*/
getFormList(): Observable<Form[]> {
const opts = {
'filter': 'myReusableForms', // String | filter
'sort': 'modifiedDesc', // String | sort
'modelType': 2 // Integer | modelType
filter: 'myReusableForms', // String | filter
sort: 'modifiedDesc', // String | sort
modelType: 2 // Integer | modelType
};
return from(this.modelsApi.getModels(opts))
@@ -231,12 +220,13 @@ export class TaskListService {
/**
* Attaches a form to a task.
*
* @param taskId ID of the target task
* @param formId ID of the form to add
* @returns Null response notifying when the operation is complete
*/
attachFormToATask(taskId: string, formId: number): Observable<any> {
return from(this.taskActionsApi.attachForm(taskId, { 'formId': formId }))
return from(this.taskActionsApi.attachForm(taskId, { formId }))
.pipe(
catchError((err) => this.handleError(err))
);
@@ -244,21 +234,21 @@ export class TaskListService {
/**
* Adds a subtask (ie, a checklist task) to a parent task.
*
* @param task The task to add
* @returns The subtask that was added
*/
addTask(task: TaskDetailsModel): Observable<TaskDetailsModel> {
return from(this.callApiAddTask(task))
.pipe(
map((response: TaskDetailsModel) => {
return new TaskDetailsModel(response);
}),
map((response) => new TaskDetailsModel(response)),
catchError((err) => this.handleError(err))
);
}
/**
* Deletes a subtask (ie, a checklist task) from a parent task.
*
* @param taskId The task to delete
* @returns Null response notifying when the operation is complete
*/
@@ -271,6 +261,7 @@ export class TaskListService {
/**
* Deletes a form from a task.
*
* @param taskId Task id related to form
* @returns Null response notifying when the operation is complete
*/
@@ -283,6 +274,7 @@ export class TaskListService {
/**
* Gives completed status to a task.
*
* @param taskId ID of the target task
* @returns Null response notifying when the operation is complete
*/
@@ -295,6 +287,7 @@ export class TaskListService {
/**
* Gets the total number of the tasks found by a query.
*
* @param requestNode Query to search for tasks
* @returns Number of tasks
*/
@@ -308,21 +301,21 @@ export class TaskListService {
/**
* Creates a new standalone task.
*
* @param task Details of the new task
* @returns Details of the newly created task
*/
createNewTask(task: TaskDetailsModel): Observable<TaskDetailsModel> {
return from(this.callApiCreateTask(task))
.pipe(
map((response: TaskDetailsModel) => {
return new TaskDetailsModel(response);
}),
map((response) => new TaskDetailsModel(response)),
catchError((err) => this.handleError(err))
);
}
/**
* Assigns a task to a user or group.
*
* @param taskId The task to assign
* @param requestNode User or group to assign the task to
* @returns Details of the assigned task
@@ -331,32 +324,31 @@ export class TaskListService {
const assignee = { assignee: requestNode.id };
return from(this.callApiAssignTask(taskId, assignee))
.pipe(
map((response: TaskDetailsModel) => {
return new TaskDetailsModel(response);
}),
map((response) => new TaskDetailsModel(response)),
catchError((err) => this.handleError(err))
);
}
/**
* Assigns a task to a user.
*
* @param taskId ID of the task to assign
* @param userId ID of the user to assign the task to
* @returns Details of the assigned task
*/
assignTaskByUserId(taskId: string, userId: string): Observable<TaskDetailsModel> {
const assignee = <AssigneeIdentifierRepresentation> { assignee: userId };
const assignee = { assignee: userId };
return from(this.callApiAssignTask(taskId, assignee))
.pipe(
map((response: TaskDetailsModel) => {
return new TaskDetailsModel(response);
}),
map((response) => new TaskDetailsModel(response)),
catchError((err) => this.handleError(err))
);
}
/**
* Claims a task for the current user.
*
* @param taskId ID of the task to claim
* @returns Details of the claimed task
*/
@@ -369,6 +361,7 @@ export class TaskListService {
/**
* Un-claims a task for the current user.
*
* @param taskId ID of the task to unclaim
* @returns Null response notifying when the operation is complete
*/
@@ -381,6 +374,7 @@ export class TaskListService {
/**
* Updates the details (name, description, due date) for a task.
*
* @param taskId ID of the task to update
* @param updated Data to update the task (as a `TaskUpdateRepresentation` instance).
* @returns Updated task details
@@ -388,26 +382,28 @@ export class TaskListService {
updateTask(taskId: string, updated: TaskUpdateRepresentation): Observable<TaskDetailsModel> {
return from(this.tasksApi.updateTask(taskId, updated))
.pipe(
map((result) => <TaskDetailsModel> result),
map((result) => result as TaskDetailsModel),
catchError((err) => this.handleError(err))
);
}
/**
* Fetches the Task Audit information in PDF format.
*
* @param taskId ID of the target task
* @returns Binary PDF data
*/
fetchTaskAuditPdfById(taskId: string): Observable<Blob> {
return from(this.tasksApi.getTaskAuditPdf(taskId))
.pipe(
map((data) => <Blob> data),
map((data) => data as Blob),
catchError((err) => this.handleError(err))
);
}
/**
* Fetch the Task Audit information in JSON format
*
* @param taskId ID of the target task
* @returns JSON data
*/
@@ -418,6 +414,22 @@ export class TaskListService {
);
}
/**
* Gets the search query for a task based on the supplied filter.
*
* @param filter The filter to use
* @returns The search query
*/
private generateTaskRequestNodeFromFilter(filterModel: FilterRepresentationModel): TaskQueryRequestRepresentationModel {
const requestNode = {
appDefinitionId: filterModel.appId,
assignment: filterModel.filter.assignment,
state: filterModel.filter.state,
sort: filterModel.filter.sort
};
return new TaskQueryRequestRepresentationModel(requestNode);
}
private callApiTasksFiltered(requestNode: TaskQueryRepresentation): Promise<TaskListModel> {
return this.tasksApi.listTasks(requestNode);
}