New packages org (#2639)

New packages org
This commit is contained in:
Eugenio Romano
2017-11-16 14:12:52 +00:00
committed by GitHub
parent 6a24c6ef75
commit a52bb5600a
1984 changed files with 17179 additions and 40423 deletions

38
lib/insights/README.md Normal file
View File

@@ -0,0 +1,38 @@
# Alfresco insights
Contains a variety of components, directives and services used throughout ADF
<!-- markdown-toc start - Don't edit this section. npm run toc to generate it-->
<!-- toc -->
- [Documentation](#documentation)
- [Prerequisites](#prerequisites)
- [Install](#install)
- [License](#license)
<!-- tocstop -->
<!-- markdown-toc end -->
## Documentation
See the [ADF Core](../../docs/README.md#process-services) section of the [docs index](../../docs/README.md)
for all available documentation on this library.
## Prerequisites
Before you start using this development framework, make sure you have installed all required software and done all the
necessary configuration, see this [page](https://github.com/Alfresco/alfresco-ng2-components/blob/master/PREREQUISITES.md).
> If you plan using this component with projects generated by Angular CLI, please refer to the following article: [Using ADF with Angular CLI](https://github.com/Alfresco/alfresco-ng2-components/wiki/Angular-CLI)
## Install
```sh
npm install @alfresco/insights
```
## License
[Apache Version 2.0](https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE)

View File

@@ -0,0 +1,71 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { DiagramsModule } from '../diagram';
import { MaterialModule } from '../material.module';
import { ChartsModule } from 'ng2-charts';
import { ToolbarModule } from '@alfresco/core';
import { AnalyticsGeneratorComponent } from './components/analytics-generator.component';
import { AnalyticsReportHeatMapComponent } from './components/analytics-report-heat-map.component';
import { AnalyticsReportListComponent } from './components/analytics-report-list.component';
import { AnalyticsReportParametersComponent } from './components/analytics-report-parameters.component';
import { AnalyticsComponent } from './components/analytics.component';
import { WIDGET_ANALYTICS_DIRECTIVES } from './components/widgets/index';
import { AnalyticsService } from './services/analytics.service';
export const ANALYTICS_DIRECTIVES: any[] = [
AnalyticsComponent,
AnalyticsReportListComponent,
AnalyticsReportParametersComponent,
AnalyticsGeneratorComponent,
AnalyticsReportHeatMapComponent,
WIDGET_ANALYTICS_DIRECTIVES
];
export const ANALYTICS_PROVIDERS: any[] = [
AnalyticsService
];
@NgModule({
imports: [
FormsModule,
ReactiveFormsModule,
CommonModule,
ChartsModule,
DiagramsModule,
MaterialModule,
TranslateModule,
ToolbarModule
],
declarations: [
...ANALYTICS_DIRECTIVES
],
providers: [
...ANALYTICS_PROVIDERS
],
exports: [
...ANALYTICS_DIRECTIVES,
MaterialModule
]
})
export class AnalyticsProcessModule {}

View File

@@ -0,0 +1,116 @@
<div *ngIf="reports">
<div class="report-icons">
<button mat-icon-button
*ngFor="let report of reports; let idx = index"
[matTooltip]="report.title"
[color]="isCurrent(idx) ? 'primary' : null"
(click)="selectCurrent(idx)">
<mat-icon>{{report.icon}}</mat-icon>
</button>
</div>
<div class="clear-both"> </div>
<div *ngFor="let report of reports; let idx = index">
<div [ngSwitch]="report.type">
<div *ngSwitchCase="'pie'">
<div *ngIf="isCurrent(idx)">
<h4>{{report.title}}</h4>
<div *ngIf="!report.hasData()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
<div *ngIf="report.hasData()">
<div *ngIf="report.hasZeroValues()">{{'ANALYTICS.MESSAGES.ZERO-DATA-FOUND' | translate}}</div>
<canvas baseChart *ngIf="!report.hasZeroValues()" class="chart"
[data]="report.data"
[labels]="report.labels"
[chartType]="report.type">
</canvas>
</div>
</div>
</div>
<div *ngSwitchCase="'table'" >
<div *ngIf="isCurrent(idx)">
<h4>{{report.title}}</h4>
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
<div [attr.id]="'chart-table-' + report.id" *ngIf="report.hasDatasets()">
<table class="table table-responsive table-condensed" class="partial-width">
<tr>
<th *ngFor="let label of report.labels">{{label | translate}}</th>
</tr>
<tr *ngFor="let rows of report.datasets">
<td *ngFor="let row of rows">{{row | translate }}</td>
</tr>
</table>
</div>
</div>
</div>
<div *ngSwitchCase="'masterDetailTable'" >
<div *ngIf="isCurrent(idx)">
<h4>{{report.title}}</h4>
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
<div [attr.id]="'chart-master-detail-table-' + report.id" *ngIf="report.hasDatasets()">
<table class="table table-responsive table-condensed" class="full-width">
<tr>
<th *ngFor="let label of report.labels">{{label | translate}}</th>
</tr>
<tr *ngFor="let rows of report.datasets" class="analytics-row__entry">
<td *ngFor="let row of rows" (click)="toggleDetailsTable()">{{row | translate }}</td>
</tr>
</table>
</div>
<div [attr.id]="'chart-master-detail-' + report.id" *ngIf="isShowDetails()">
<table class="table table-responsive table-condensed" class="full-width">
<tr>
<th *ngFor="let label of report.detailsTable.labels">{{label | translate}}</th>
</tr>
<tr *ngFor="let rows of report.detailsTable.datasets">
<td *ngFor="let row of rows">{{row | translate }}</td>
</tr>
</table>
</div>
</div>
</div>
<div *ngSwitchCase="'bar'">
<div *ngIf="isCurrent(idx)">
<h4>{{report.title}}</h4>
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
<canvas baseChart *ngIf="report.hasDatasets()" class="chart"
[datasets]="report.datasets"
[labels]="report.labels"
[options]="report.options"
[chartType]="report.type">
</canvas>
</div>
</div>
<div *ngSwitchCase="'multiBar'">
<div *ngIf="isCurrent(idx)">
<h4>{{report.title}}</h4>
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
<div *ngIf="report.hasDatasets()">
<mat-checkbox
color="primary"
[id]="'stacked-id'"
[checked]="report.options.scales.xAxes[0].stacked"
[(ngModel)]="report.options.scales.xAxes[0].stacked"
(change)="refresh(report)">Stacked</mat-checkbox>
<canvas baseChart class="chart"
[datasets]="report.datasets"
[labels]="report.labels"
[options]="report.options"
[chartType]="'bar'">
</canvas>
</div>
</div>
</div>
<div *ngSwitchCase="'HeatMap'">
<div *ngIf="isCurrent(idx)">
<h4>{{report.title}}</h4>
<analytics-report-heat-map [report]="report"></analytics-report-heat-map>
</div>
</div>
<div *ngSwitchDefault>
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{report.type}}</span>
</div>
</div>
</div>
</div>
<br><br><br>
<div *ngIf="!reports">{{'ANALYTICS.MESSAGES.FILL-PARAMETER' | translate}}</div>

View File

@@ -0,0 +1,26 @@
.chart {
display: block;
width: 100%;
}
.analytics-row__entry {
cursor: pointer;
}
.report-icons {
margin: 20px 0;
float: left;
}
.full-width {
width: 100%
}
.partial-width {
width: 80%;
margin-left: 20px
}
.clear-both {
clear: both;
}

View File

@@ -0,0 +1,274 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChartsModule } from 'ng2-charts';
import { MaterialModule } from '../../material.module';
import { DiagramsModule } from '../../diagram';
import { Chart } from '../../diagram';
import { ReportQuery } from '../../diagram';
import * as analyticMock from '../../mock';
import { AnalyticsGeneratorComponent } from '../components/analytics-generator.component';
import { AnalyticsReportHeatMapComponent } from '../components/analytics-report-heat-map.component';
import { AnalyticsReportListComponent } from '../components/analytics-report-list.component';
import { AnalyticsReportParametersComponent } from '../components/analytics-report-parameters.component';
import { WIDGET_ANALYTICS_DIRECTIVES } from '../components/widgets/index';
import { AnalyticsService } from '../services/analytics.service';
export const ANALYTICS_DIRECTIVES: any[] = [
AnalyticsGeneratorComponent,
AnalyticsReportParametersComponent,
AnalyticsReportListComponent,
AnalyticsReportHeatMapComponent,
WIDGET_ANALYTICS_DIRECTIVES
];
export const ANALYTICS_PROVIDERS: any[] = [
AnalyticsService
];
declare let jasmine: any;
describe('AnalyticsGeneratorComponent', () => {
let component: any;
let fixture: ComponentFixture<AnalyticsGeneratorComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
MaterialModule,
ChartsModule,
DiagramsModule
],
declarations: [
...ANALYTICS_DIRECTIVES
],
providers: [
...ANALYTICS_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AnalyticsGeneratorComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('Should render the Process definition overview report ', (done) => {
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(3);
expect(res[0]).toBeDefined();
expect(res[0].type).toEqual('table');
expect(res[0].datasets).toBeDefined();
expect(res[0].datasets.length).toEqual(4);
expect(res[0].datasets[0][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS');
expect(res[0].datasets[0][1]).toEqual('9');
expect(res[0].datasets[1][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-INSTANCES');
expect(res[0].datasets[1][1]).toEqual('41');
expect(res[0].datasets[2][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES');
expect(res[0].datasets[2][1]).toEqual('3');
expect(res[0].datasets[3][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES');
expect(res[0].datasets[3][1]).toEqual('38');
expect(res[1]).toBeDefined();
expect(res[1].type).toEqual('pie');
expect(res[2]).toBeDefined();
expect(res[2].type).toEqual('table');
done();
});
component.reportId = 1001;
component.reportParamQuery = new ReportQuery({status: 'All'});
component.ngOnChanges();
fixture.detectChanges();
fixture.whenStable().then(() => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticMock.chartProcessDefOverview
});
});
});
it('Should render the Process definition overview report when onchanges is called ', (done) => {
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(3);
expect(res[0]).toBeDefined();
expect(res[0].type).toEqual('table');
expect(res[0].datasets).toBeDefined();
expect(res[0].datasets.length).toEqual(4);
expect(res[0].datasets[0][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS');
expect(res[0].datasets[0][1]).toEqual('9');
expect(res[0].datasets[1][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-INSTANCES');
expect(res[0].datasets[1][1]).toEqual('41');
expect(res[0].datasets[2][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES');
expect(res[0].datasets[2][1]).toEqual('3');
expect(res[0].datasets[3][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES');
expect(res[0].datasets[3][1]).toEqual('38');
expect(res[1]).toBeDefined();
expect(res[1].type).toEqual('pie');
expect(res[2]).toBeDefined();
expect(res[2].type).toEqual('table');
done();
});
component.reportId = 1001;
component.reportParamQuery = new ReportQuery({status: 'All'});
component.ngOnChanges();
fixture.detectChanges();
fixture.whenStable().then(() => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticMock.chartProcessDefOverview
});
});
});
it('Should render the Task overview report ', (done) => {
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(3);
expect(res[0]).toBeDefined();
expect(res[0].type).toEqual('bar');
expect(res[0].labels).toBeDefined();
expect(res[0].labels.length).toEqual(2);
expect(res[0].labels[0]).toEqual('2016-09-30T00:00:00.000+0000');
expect(res[0].labels[1]).toEqual('2016-10-04T00:00:00.000+0000');
expect(res[0].datasets[0].label).toEqual('series1');
expect(res[0].datasets[0].data[0]).toEqual(3);
expect(res[0].datasets[0].data[1]).toEqual(1);
expect(res[1]).toBeDefined();
expect(res[1].type).toEqual('masterDetailTable');
expect(res[1].datasets).toBeDefined();
expect(res[1].datasets.length).toEqual(2);
expect(res[1].datasets[0][0]).toEqual('fake 1 user task');
expect(res[1].datasets[0][1]).toEqual('1');
expect(res[1].datasets[0][2]).toEqual('2.0');
expect(res[1].datasets[0][3]).toEqual('3.0');
expect(res[1].datasets[0][4]).toEqual('4.0');
expect(res[1].datasets[0][5]).toEqual('5.0');
expect(res[1].datasets[0][6]).toEqual('6.0');
expect(res[1].datasets[1][0]).toEqual('fake 2 user task');
expect(res[1].datasets[1][1]).toEqual('1');
expect(res[1].datasets[1][2]).toEqual('2.0');
expect(res[1].datasets[1][3]).toEqual('3.0');
expect(res[1].datasets[1][4]).toEqual('4.0');
expect(res[1].datasets[1][5]).toEqual('5.0');
expect(res[1].datasets[1][6]).toEqual('6.0');
expect(res[2]).toBeDefined();
expect(res[2].type).toEqual('multiBar');
expect(res[2].labels).toBeDefined();
expect(res[2].labels.length).toEqual(3);
expect(res[2].labels[0]).toEqual(1);
expect(res[2].labels[1]).toEqual(2);
expect(res[2].labels[2]).toEqual(3);
expect(res[2].datasets[0].label).toEqual('averages');
expect(res[2].datasets[0].data[0]).toEqual(0);
expect(res[2].datasets[0].data[1]).toEqual(5);
expect(res[2].datasets[0].data[2]).toEqual(2);
expect(res[2].datasets[1].label).toEqual('minima');
expect(res[2].datasets[1].data[0]).toEqual(0);
expect(res[2].datasets[1].data[1]).toEqual(0);
expect(res[2].datasets[1].data[2]).toEqual(0);
expect(res[2].datasets[2].label).toEqual('maxima');
expect(res[2].datasets[2].data[0]).toEqual(0);
expect(res[2].datasets[2].data[1]).toEqual(29);
expect(res[2].datasets[2].data[2]).toEqual(29);
done();
});
component.reportId = 1;
component.reportParamQuery = new ReportQuery({status: 'All'});
component.ngOnChanges();
fixture.detectChanges();
fixture.whenStable().then(() => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticMock.chartTaskOverview
});
});
});
it('Should reset the reports when the onChanged is call', () => {
component.reports = [new Chart({id: 'fake', type: 'fake-type'})];
component.reportId = 1;
component.ngOnChanges();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(component.reports).toBeUndefined();
});
});
it('Should emit onError event with a 404 response ', (done) => {
component.error.subscribe((err) => {
expect(err).toBeDefined();
done();
});
component.reportId = 1;
component.reportParamQuery = new ReportQuery({status: 'All'});
component.ngOnChanges();
fixture.detectChanges();
fixture.whenStable().then(() => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 404,
contentType: 'json',
responseText: []
});
});
});
});

View File

@@ -0,0 +1,130 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation } from '@angular/core';
import { ReportQuery } from '../../diagram';
import { Chart } from '../../diagram';
import { AnalyticsService } from '../services/analytics.service';
@Component({
selector: 'adf-analytics-generator',
templateUrl: './analytics-generator.component.html',
styleUrls: ['./analytics-generator.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class AnalyticsGeneratorComponent implements OnChanges {
@Input()
reportId: number;
@Input()
reportParamQuery: ReportQuery = undefined;
@Output()
success = new EventEmitter();
@Output()
error = new EventEmitter();
reports: Chart[];
showDetails: boolean = false;
currentChartPosition: number;
public barChartOptions: any = {
responsive: true,
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
}
}],
xAxes: [{
ticks: {
},
stacked: true
}]
}
};
constructor(private analyticsService: AnalyticsService) {
}
ngOnChanges() {
if (this.reportId && this.reportParamQuery) {
this.generateReport(this.reportId, this.reportParamQuery);
} else {
this.reset();
}
}
public generateReport(reportId, reportParamQuery) {
if (reportParamQuery === undefined || reportParamQuery === null) {
reportParamQuery = {};
}
this.analyticsService.getReportsByParams(reportId, reportParamQuery).subscribe(
(res: Chart[]) => {
this.reports = res;
if (this.reports) {
this.selectFirstReport();
}
this.success.emit(res);
},
(err: any) => {
this.error.emit(err);
}
);
}
public reset() {
if (this.reports) {
this.reports = undefined;
}
}
public refresh(report): void {
/**
* (My guess), for Angular to recognize the change in the dataset
* it has to change the dataset variable directly,
* so one way around it, is to clone the data, change it and then
* assign it;
*/
let clone = JSON.parse(JSON.stringify(report));
report.datasets = clone.datasets;
}
toggleDetailsTable() {
this.showDetails = !this.showDetails;
}
isShowDetails(): boolean {
return this.showDetails;
}
isCurrent(position: number) {
return position === this.currentChartPosition ? true : false;
}
selectCurrent(position: number) {
this.currentChartPosition = position;
}
selectFirstReport() {
this.selectCurrent(0);
}
}

View File

@@ -0,0 +1,9 @@
<h4>Process Heat map</h4>
<div *ngIf="hasMetric()">
<form [formGroup]="metricForm" novalidate>
<analytics-dropdown-widget [field]="field" [group]="metricForm.controls.metricGroup" [controllerName]="'metric'"
(fieldChanged)="onMetricChanges(field)" [showDefaultOption]="false"></analytics-dropdown-widget>
</form>
<adf-diagram *ngIf="currentMetric" [processDefinitionId]="report.processDefinitionId" [metricPercentages]="currentMetric" [metricColor]="currentMetricColors" [metricType]="metricType"></adf-diagram>
</div>
<div *ngIf="!hasMetric()">No metric found</div>

View File

@@ -0,0 +1,134 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DiagramsModule } from '../../diagram';
import { AnalyticsReportHeatMapComponent } from '../components/analytics-report-heat-map.component';
import { WIDGET_ANALYTICS_DIRECTIVES } from '../components/widgets/index';
import { MaterialModule } from '../../material.module';
import { AnalyticsService } from '../services/analytics.service';
declare let jasmine: any;
describe('AnalyticsReportHeatMapComponent', () => {
let component: AnalyticsReportHeatMapComponent;
let fixture: ComponentFixture<AnalyticsReportHeatMapComponent>;
let debug: DebugElement;
let element: HTMLElement;
let totalCountPerc: any = { 'sid-fake-id': 0, 'fake-start-event': 100 };
let totalTimePerc: any = { 'sid-fake-id': 10, 'fake-start-event': 30 };
let avgTimePercentages: any = { 'sid-fake-id': 5, 'fake-start-event': 50 };
let totalCountValues: any = { 'sid-fake-id': 2, 'fake-start-event': 3 };
let totalTimeValues: any = { 'sid-fake-id': 1, 'fake-start-event': 4 };
let avgTimeValues: any = { 'sid-fake-id': 4, 'fake-start-event': 5 };
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
DiagramsModule,
MaterialModule
],
declarations: [
AnalyticsReportHeatMapComponent,
...WIDGET_ANALYTICS_DIRECTIVES
],
providers: [
AnalyticsService
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AnalyticsReportHeatMapComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
component.report = {
totalCountsPercentages: totalCountPerc,
totalCountValues: totalCountValues,
totalTimePercentages: totalTimePerc,
totalTimeValues: totalTimeValues,
avgTimeValues: avgTimeValues,
avgTimePercentages: avgTimePercentages
};
});
describe('Rendering tests: Heat Map', () => {
beforeEach(() => {
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('should render the dropdown with the metric options', async(() => {
component.report = { totalCountsPercentages: { 'sid-fake-id': 10, 'fake-start-event': 30 } };
component.success.subscribe(() => {
fixture.whenStable().then(() => {
let dropDown: any = element.querySelector('#select-metrics');
expect(dropDown).toBeDefined();
expect(dropDown.length).toEqual(3);
expect(dropDown[0].innerHTML).toEqual('Number of times a step is executed');
expect(dropDown[1].innerHTML).toEqual('Total time spent in a process step');
expect(dropDown[2].innerHTML).toEqual('Average time spent in a process step');
});
});
fixture.detectChanges();
}));
it('should return false when no metrics are defined in the report', async(() => {
component.report = {};
expect(component.hasMetric()).toBeFalsy();
}));
it('should return true when the metrics are defined in the report', async(() => {
expect(component.hasMetric()).toBeTruthy();
}));
it('should change the currentmetric width totalCount', async(() => {
let field = { value: 'totalCount' };
component.onMetricChanges(field);
expect(component.currentMetric).toEqual(totalCountValues);
expect(component.currentMetricColors).toEqual(totalCountPerc);
}));
it('should change the currentmetric width totalTime', async(() => {
let field = { value: 'totalTime' };
component.onMetricChanges(field);
expect(component.currentMetric).toEqual(totalTimeValues);
expect(component.currentMetricColors).toEqual(totalTimePerc);
}));
it('should change the currentmetric width avgTime', async(() => {
let field = { value: 'avgTime' };
component.onMetricChanges(field);
expect(component.currentMetric).toEqual(avgTimeValues);
expect(component.currentMetricColors).toEqual(avgTimePercentages);
}));
});
});

View File

@@ -0,0 +1,91 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { AnalyticsService } from '../services/analytics.service';
@Component({
selector: 'adf-analytics-report-heat-map, analytics-report-heat-map',
templateUrl: './analytics-report-heat-map.component.html'
})
export class AnalyticsReportHeatMapComponent implements OnInit {
@Input()
report: any;
@Output()
success = new EventEmitter();
@Output()
error = new EventEmitter();
field: any = {};
metricForm: FormGroup;
currentMetric: string;
currentMetricColors: any;
metricType: string;
constructor(private analyticsService: AnalyticsService,
private formBuilder: FormBuilder) {
}
ngOnInit() {
this.initForm();
this.field.id = 'metrics';
this.field.value = 'totalCount';
this.analyticsService.getMetricValues().subscribe(
(opts: any[]) => {
this.field.options = opts;
this.success.emit(opts);
}
);
}
onMetricChanges(field: any) {
if (field.value === 'totalCount') {
this.currentMetric = this.report.totalCountValues;
this.currentMetricColors = this.report.totalCountsPercentages;
this.metricType = 'times';
} else if (field.value === 'totalTime') {
this.currentMetric = this.report.totalTimeValues;
this.currentMetricColors = this.report.totalTimePercentages;
this.metricType = 'hours';
} else if (field.value === 'avgTime') {
this.currentMetric = this.report.avgTimeValues;
this.currentMetricColors = this.report.avgTimePercentages;
this.metricType = 'hours';
}
}
initForm() {
this.metricForm = this.formBuilder.group({
metricGroup: new FormGroup({
metric: new FormControl()
})
});
}
hasMetric() {
return (this.report.totalCountsPercentages ||
this.report.totalTimePercentages ||
this.report.avgTimePercentages) ? true : false;
}
}

View File

@@ -0,0 +1,32 @@
<div class="adf-analytics-report-list menu-container">
<mat-nav-list *ngIf="isList()">
<mat-list-item
class="activiti-filters__entry"
(click)="selectReport(report)"
*ngFor="let report of reports; let idx = index"
[class.active]="currentReport === report">
<span [attr.id]="'report-list-' + idx" class="activiti-filters__label">
<mat-icon mat-list-icon
[attr.data-automation-id]="report.name + '_filter'"
class="activiti-filters__entry-icon">assignment</mat-icon>
<span class="text">{{report.name}}</span>
</span>
</mat-list-item>
</mat-nav-list>
<div class="adf-report-card-grids" *ngIf="isGrid()">
<mat-card (click)="selectReport(report)" class="adf-report-card" *ngFor="let report of reports;">
<div class="adf-report-card-logo logo">
<mat-icon class="adf-report-card-logo-icon">equalizer</mat-icon>
</div>
<div mat-card-title class="adf-report-card-title">
<h1 class="application-title">{{report.name}}</h1>
</div>
<div mat-card-content class="adf-report-card-content">
<p>{{report.description}}</p>
</div>
<div mat-card-actions class="adf-report-card-actions">
<mat-icon class="adf-report-card-actions-icon" *ngIf="isSelected(report)">done</mat-icon>
</div>
</mat-card>
</div>
</div>

View File

@@ -0,0 +1,98 @@
@mixin adf-analytics-report-list-theme($theme) {
$primary: map-get($theme, primary);
.adf-analytics-report-list {
.activiti-filters__entry {
cursor: pointer;
}
.activiti-filters__entry-icon {
position: relative;
top: 5px;
}
.activiti-filters__label {
white-space: nowrap;
overflow: hidden;
}
.mat-nav-list .mat-list-item .mat-list-item-content {
line-height: 48px;
}
.activiti-filters__entry.active {
color: mat-color($primary);
}
.activiti-filters__entry.active .activiti-filters__entry-icon {
color: mat-color($primary);
}
.adf-report-card-grids {
display: flex;
padding: 8px;
flex-flow: row wrap;
margin: 0 auto;
align-items: stretch;
}
.adf-report-card {
margin: 8px;
width: calc(33.3333333333% - 16px);
position: relative;
min-height: 200px;
overflow: hidden;
background-color: #269abc;
display: flex;
flex-direction: column;
cursor: pointer;
&-logo {
position: absolute;
right: 20px;
top: 35px;
z-index: 6;
&-icon {
font-size: 70px;
color: #168aac;
width: 1em;
height: 1em;
display: inline-block;
}
}
&-title {
padding: 16px;
z-index: 7;
.application-title {
font-size: 24px;
margin: 0;
}
}
&-content {
padding: 16px;
flex-grow: 1;
}
&-actions {
border-top: 1px solid rgba(0,0,0,.1);
padding: 8px;
box-sizing: border-box;
height: 40px;
&-icon {
color: #e9f1f3;
&:hover {
color: #b7dfea;
}
}
}
}
}
}

View File

@@ -0,0 +1,240 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReportParametersModel } from '../../diagram';
import { AnalyticsReportListComponent } from '../components/analytics-report-list.component';
import { MaterialModule } from '../../material.module';
import { AnalyticsService } from '../services/analytics.service';
declare let jasmine: any;
describe('AnalyticsReportListComponent', () => {
let reportList = [
{ 'id': 2002, 'name': 'Fake Test Process definition heat map' },
{ 'id': 2003, 'name': 'Fake Test Process definition overview' },
{ 'id': 2004, 'name': 'Fake Test Process instances overview' },
{ 'id': 2005, 'name': 'Fake Test Task overview' },
{ 'id': 2006, 'name': 'Fake Test Task service level agreement' }
];
let reportSelected = { 'id': 2003, 'name': 'Fake Test Process definition overview' };
let component: AnalyticsReportListComponent;
let fixture: ComponentFixture<AnalyticsReportListComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
MaterialModule
],
declarations: [
AnalyticsReportListComponent
],
providers: [
AnalyticsService
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AnalyticsReportListComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
});
describe('Rendering tests', () => {
beforeEach(() => {
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('Report return true with undefined reports', () => {
expect(component.isReportsEmpty()).toBeTruthy();
});
it('Report return true with an empty reports', () => {
component.reports = [];
expect(component.isReportsEmpty()).toBeTruthy();
});
it('should return the default reports when the report list is empty', (done) => {
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/reports').andReturn({
status: 200,
contentType: 'json',
responseText: []
});
fixture.detectChanges();
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/default-reports').andReturn({
status: 200,
contentType: 'json',
responseText: []
});
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/reports').andReturn({
status: 200,
contentType: 'json',
responseText: reportList
});
component.success.subscribe(() => {
fixture.detectChanges();
expect(element.querySelector('#report-list-0 .activiti-filters__entry-icon').innerHTML).toBe('assignment');
expect(element.querySelector('#report-list-0 > span').innerHTML).toBe('Fake Test Process definition heat map');
expect(element.querySelector('#report-list-1 > span').innerHTML).toBe('Fake Test Process definition overview');
expect(element.querySelector('#report-list-2 > span').innerHTML).toBe('Fake Test Process instances overview');
expect(element.querySelector('#report-list-3 > span').innerHTML).toBe('Fake Test Task overview');
expect(element.querySelector('#report-list-4 > span').innerHTML).toBe('Fake Test Task service level agreement');
expect(component.isReportsEmpty()).toBeFalsy();
done();
});
});
it('Report render the report list relative to a single app', (done) => {
fixture.detectChanges();
component.success.subscribe(() => {
fixture.detectChanges();
expect(element.querySelector('#report-list-0 .activiti-filters__entry-icon').innerHTML).toBe('assignment');
expect(element.querySelector('#report-list-0 > span').innerHTML).toBe('Fake Test Process definition heat map');
expect(element.querySelector('#report-list-1 > span').innerHTML).toBe('Fake Test Process definition overview');
expect(element.querySelector('#report-list-2 > span').innerHTML).toBe('Fake Test Process instances overview');
expect(element.querySelector('#report-list-3 > span').innerHTML).toBe('Fake Test Task overview');
expect(element.querySelector('#report-list-4 > span').innerHTML).toBe('Fake Test Task service level agreement');
expect(component.isReportsEmpty()).toBeFalsy();
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: reportList
});
});
it('Report emit an error with a empty response', (done) => {
fixture.detectChanges();
component.error.subscribe((err) => {
expect(err).toBeDefined();
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 404,
contentType: 'json',
responseText: []
});
});
it('Should return the current report when one report is selected', () => {
component.reportClick.subscribe(() => {
expect(component.currentReport).toEqual(reportSelected);
});
component.selectReport(reportSelected);
});
it('Should return true if the current report is selected', () => {
component.selectReport(reportSelected);
expect(component.isSelected(reportSelected)).toBe(true);
});
it('Should return false if the current report is different', () => {
component.selectReport(reportSelected);
let anotherReport = { 'id': 111, 'name': 'Another Fake Test Process definition overview' };
expect(component.isSelected(anotherReport)).toBe(false);
});
it('Should reload the report list', (done) => {
component.initObserver();
let report = new ReportParametersModel({ 'id': 2002, 'name': 'Fake Test Process definition heat map' });
component.reports = [report];
expect(component.reports.length).toEqual(1);
component.reload();
component.success.subscribe(() => {
expect(component.reports.length).toEqual(5);
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: reportList
});
});
it('Should reload the report list and select the report with the given id', (done) => {
component.initObserver();
expect(component.reports.length).toEqual(0);
component.reload(2002);
component.success.subscribe(() => {
expect(component.reports.length).toEqual(5);
expect(component.currentReport).toBeDefined();
expect(component.currentReport).not.toBeNull();
expect(component.currentReport.id).toEqual(2002);
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: reportList
});
});
});
describe('layout', () => {
it('should display a list by default', () => {
fixture.detectChanges();
expect(component.isGrid()).toBe(false);
expect(component.isList()).toBe(true);
});
it('should display a grid when configured to', () => {
component.layoutType = AnalyticsReportListComponent.LAYOUT_GRID;
fixture.detectChanges();
expect(component.isGrid()).toBe(true);
expect(component.isList()).toBe(false);
});
it('should display a list when configured to', () => {
component.layoutType = AnalyticsReportListComponent.LAYOUT_LIST;
fixture.detectChanges();
expect(component.isGrid()).toBe(false);
expect(component.isList()).toBe(true);
});
});
});

View File

@@ -0,0 +1,178 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { Observable, Observer } from 'rxjs/Rx';
import { ReportParametersModel } from '../../diagram';
import { AnalyticsService } from '../services/analytics.service';
@Component({
selector: 'adf-analytics-report-list, analytics-report-list',
templateUrl: './analytics-report-list.component.html',
styleUrls: ['./analytics-report-list.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class AnalyticsReportListComponent implements OnInit {
public static LAYOUT_LIST: string = 'LIST';
public static LAYOUT_GRID: string = 'GRID';
@Input()
layoutType: string = AnalyticsReportListComponent.LAYOUT_LIST;
@Input()
appId: number;
@Input()
selectFirst: boolean = false;
@Output()
reportClick: EventEmitter<ReportParametersModel> = new EventEmitter<ReportParametersModel>();
@Output()
success = new EventEmitter();
@Output()
error = new EventEmitter();
private reportObserver: Observer<any>;
report$: Observable<any>;
currentReport: any;
reports: ReportParametersModel[] = [];
constructor(private analyticsService: AnalyticsService) {
this.report$ = new Observable<ReportParametersModel>(observer => this.reportObserver = observer).share();
}
ngOnInit() {
this.initObserver();
this.getReportList(this.appId);
}
initObserver() {
this.report$.subscribe((report: ReportParametersModel) => {
this.reports.push(report);
});
}
/**
* Reload the component
*/
reload(reportId?) {
this.reset();
this.getReportList(this.appId, reportId);
}
/**
* Get the report list
*/
getReportList(appId: number, reportId?: string) {
this.analyticsService.getReportList(appId).subscribe(
(res: ReportParametersModel[]) => {
if (res && res.length === 0) {
this.createDefaultReports();
} else {
res.forEach((report) => {
this.reportObserver.next(report);
});
if (reportId) {
this.selectReportByReportId(reportId);
}
if (this.selectFirst) {
this.selectFirstReport();
}
this.success.emit(res);
}
},
(err: any) => {
this.error.emit(err);
}
);
}
/**
* Create the default reports and return the report list
*/
createDefaultReports() {
this.analyticsService.createDefaultReports().subscribe(
() => {
this.analyticsService.getReportList(this.appId).subscribe(
(response: ReportParametersModel[]) => {
response.forEach((report) => {
this.reportObserver.next(report);
});
this.success.emit(response);
}
);
}
);
}
/**
* Check if the report list is empty
* @returns {boolean|ReportParametersModel[]}
*/
isReportsEmpty(): boolean {
return this.reports === undefined || (this.reports && this.reports.length === 0);
}
/**
* Reset the list
*/
private reset() {
if (!this.isReportsEmpty()) {
this.reports = [];
}
}
/**
* Select the current report
* @param report
*/
public selectReport(report: any) {
this.currentReport = report;
this.reportClick.emit(report);
}
public selectReportByReportId(reportId) {
let reportFound = this.reports.find(report => report.id === reportId);
if (reportFound) {
this.currentReport = reportFound;
this.reportClick.emit(reportFound);
}
}
selectFirstReport() {
this.selectReport(this.reports[0]);
this.selectFirst = false;
}
isSelected(report: any) {
return this.currentReport === report ? true : false;
}
isList() {
return this.layoutType === AnalyticsReportListComponent.LAYOUT_LIST;
}
isGrid() {
return this.layoutType === AnalyticsReportListComponent.LAYOUT_GRID;
}
}

View File

@@ -0,0 +1,139 @@
<div [class.hide]="hideComponent">
<div class="adf-report-report-container">
<div *ngIf="reportParameters">
<form [formGroup]="reportForm" novalidate>
<adf-toolbar>
<adf-toolbar-title class="adf-report-title-container">
<div *ngIf="isEditable">
<mat-form-field class="adf-full-width-input">
<input
matInput
type="text"
class="adf-edit-report-title"
id="reportName"
autofocus
data-automation-id="reportName"
[value]="reportParameters.name"
(input)="reportParameters.name=$event.target.value"
(blur)="editTitle($event)"
(keyup.enter)="editTitle($event)"
/>
</mat-form-field>
</div>
<div class="adf-report-title" *ngIf="!isEditable" (click)="editEnable()">
<mat-icon class="adf-report-icon" >mode_edit</mat-icon>
<h4>{{reportParameters.name}}</h4>
</div>
</adf-toolbar-title>
<div *ngIf="!isEditable">
<button mat-button matTooltip="{{'ANALYTICS.MESSAGES.ICON-SETTING' | translate}}"
(click)="toggleParameters()">
<mat-icon>settings</mat-icon>
</button>
<button mat-button id="delete-button" (click)="deleteReport(reportId)"
matTooltip="{{'ANALYTICS.MESSAGES.ICON-DELETE' | translate}}">
<mat-icon>delete</mat-icon>
</button>
<span *ngIf="isFormValid()">
<button mat-button id="export-button" (click)="showDialog('Export')"
matTooltip="{{'ANALYTICS.MESSAGES.ICON-EXPORT-CSV' | translate}}">
<mat-icon>file_download</mat-icon>
</button>
<button mat-button id="save-button" (click)="showDialog('Save')"
matTooltip="{{'ANALYTICS.MESSAGES.ICON-SAVE' | translate}}">
<mat-icon>save</mat-icon>
</button>
</span>
</div>
</adf-toolbar>
<div *ngFor="let field of reportParameters.definition.parameters"
[class.is-hide]="isParametersHide()">
<div [ngSwitch]="field.type">
<div *ngSwitchCase="'integer'">
<br>
<analytics-number-widget [field]="field" [group]="reportForm.controls.processInstanceGroup"
[controllerName]="'slowProcessInstanceInteger'"
[required]="true"></analytics-number-widget>
</div>
<div *ngSwitchCase="'duration'">
<br>
<duration-widget [field]="field" [group]="reportForm.controls.durationGroup"
[controllerName]="'duration'"></duration-widget>
</div>
<div *ngSwitchCase="'boolean'">
<br>
<analytics-checkbox-widget [field]="field" [group]="reportForm.controls.typeFilteringGroup"
[controllerName]="'typeFiltering'"></analytics-checkbox-widget>
</div>
<div *ngSwitchCase="'status'">
<br>
<analytics-dropdown-widget [field]="field" [group]="reportForm.controls.statusGroup"
[controllerName]="'status'"
[required]="true"></analytics-dropdown-widget>
</div>
<div *ngSwitchCase="'processDefinition'">
<br>
<analytics-dropdown-widget [field]="field" [group]="reportForm.controls.processDefGroup"
[controllerName]="'processDefinitionId'"
[required]="true"
(fieldChanged)="onProcessDefinitionChanges(field)"></analytics-dropdown-widget>
</div>
<div *ngSwitchCase="'task'">
<br>
<analytics-dropdown-widget [field]="field" [group]="reportForm.controls.taskGroup"
[controllerName]="'taskName'"
[required]="true"></analytics-dropdown-widget>
</div>
<div *ngSwitchCase="'dateRange'">
<br>
<adf-date-range-widget [field]="field"
[group]="reportForm.controls.dateRange"></adf-date-range-widget>
</div>
<div *ngSwitchCase="'dateInterval'">
<br>
<analytics-dropdown-widget [field]="field" [group]="reportForm.controls.dateIntervalGroup"
[controllerName]="'dateRangeInterval'"
[required]="true" [showDefaultOption]="false"></analytics-dropdown-widget>
</div>
<div *ngSwitchDefault>
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{field.type}}</span>
</div>
</div>
</div>
<ng-template #reportNameDialog>
<div id="report-dialog" class="adf-report-dialog">
<h5 matDialogTitle id="report-dialog-title">{{action}} report</h5>
<div mat-dialog-content>
<div *ngIf="isSaveAction()" id="save-title-submessage" class="export-message">
{{'DIALOG.SAVE_MESSAGE' | translate}}
</div>
<div class="save-export-input">
<mat-form-field class="example-full-width" floatPlaceholder="always">
<input matInput
type="text"
id="repName"
placeholder="Report Name"
[value]="reportName"
[(ngModel)]="reportName"
[ngModelOptions]="{standalone: true}">
</mat-form-field>
</div>
</div>
<div mat-dialog-actions>
<button mat-button
color="accent"
type="button"
id="close-dialog-button"
(click)="closeDialog()">Close</button>
<button mat-button
color="primary"
type="button"
id="action-dialog-button"
(click)="performAction(action, reportParamQuery)">{{action}}</button>
</div>
</div>
</ng-template>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1,103 @@
.dropdown-widget {
width: 100%;
}
.dropdown-widget__select {
width: 100%;
}
.dropdown-widget__invalid .dropdown-widget__select {
border-color: #d50000;
}
.dropdown-widget__invalid .dropdown-widget__label {
color: #d50000;
}
.dropdown-widget__invalid .dropdown-widget__label:after {
background-color: #d50000;
}
.adf-edit-report-title {
float: left;
font-size: 20px!important;
padding-top: 19px;
}
.adf-report-icon {
float: left;
padding: 5px 5px 0 0;
visibility: hidden;
}
.adf-report-title-container {
cursor: pointer;
width: 100%;
margin-bottom: 12px;
:hover .adf-report-icon {
color: rgb(68, 138, 255);
visibility: visible;
}
}
.adf-report-title {
padding-top: 10px;
}
.adf-full-width-input {
width: 100%;
}
.is-hide {
height: 0;
overflow: hidden;
transition: height 0.5s;
}
.adf-report-report-container {
border-bottom: solid 1px rgb(212, 212, 212);
padding-top: 10px;
.mat-toolbar {
border: 0 !important;
padding: 0 !important;
}
}
.report-container-setting {
padding-left: 10px;
}
.option_button_details {
padding-top: 20px;
}
.export-message {
background-color: lightgray;
}
.save-export-input {
width: 100%;
}
.delete-parameter {
position: absolute;
margin-left: 60%;
padding-top: 5px;
}
.hide {
display: none;
}
.adf-report-dialog {
.mat-form-field {
width: 100%;
}
.mat-dialog-actions {
justify-content: flex-end;
}
}

View File

@@ -0,0 +1,636 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DebugElement, SimpleChange } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReportParametersModel } from '../../diagram';
import * as analyticParamsMock from '../../mock';
import { AnalyticsReportParametersComponent } from '../components/analytics-report-parameters.component';
import { WIDGET_ANALYTICS_DIRECTIVES } from '../components/widgets/index';
import { MaterialModule } from '../../material.module';
import { AnalyticsService } from '../services/analytics.service';
import { DateRangeWidgetComponent } from './widgets/date-range/date-range.widget';
declare let jasmine: any;
describe('AnalyticsReportParametersComponent', () => {
let component: AnalyticsReportParametersComponent;
let fixture: ComponentFixture<AnalyticsReportParametersComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
MaterialModule
],
declarations: [
DateRangeWidgetComponent,
AnalyticsReportParametersComponent,
...WIDGET_ANALYTICS_DIRECTIVES
],
providers: [
AnalyticsService
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AnalyticsReportParametersComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
describe('Rendering tests', () => {
beforeEach(() => {
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('Should initialize the Report form with a Form Group ', (done) => {
let fakeReportParam = new ReportParametersModel(analyticParamsMock.reportDefParamTask);
component.successReportParams.subscribe(() => {
fixture.detectChanges();
expect(component.reportForm.get('taskGroup')).toBeDefined();
expect(component.reportForm.get('taskGroup').get('taskName')).toBeDefined();
done();
});
component.successReportParams.emit(fakeReportParam);
});
it('Should render a dropdown with all the status when the definition parameter type is \'status\' ', (done) => {
component.successReportParams.subscribe(() => {
fixture.detectChanges();
let dropDown: any = element.querySelector('#select-status');
expect(element.querySelector('h4').textContent.trim()).toEqual('Fake Task overview status');
expect(dropDown).toBeDefined();
expect(dropDown.length).toEqual(4);
expect(dropDown[0].innerHTML).toEqual('Choose One');
expect(dropDown[1].innerHTML).toEqual('All');
expect(dropDown[2].innerHTML).toEqual('Active');
expect(dropDown[3].innerHTML).toEqual('Complete');
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamStatus
});
});
it('Should render a number with the default value when the definition parameter type is \'integer\' ', (done) => {
component.successReportParams.subscribe(() => {
fixture.detectChanges();
let numberElement: any = element.querySelector('#slowProcessInstanceInteger');
expect(numberElement.value).toEqual('10');
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamNumber
});
});
it('Should render a duration component when the definition parameter type is \'duration\' ', (done) => {
component.successReportParams.subscribe(() => {
fixture.detectChanges();
let numberElement: any = element.querySelector('#duration');
expect(numberElement.value).toEqual('0');
let dropDown: any = element.querySelector('#select-duration');
expect(dropDown).toBeDefined();
expect(dropDown.length).toEqual(4);
expect(dropDown[0].innerHTML).toEqual('Seconds');
expect(dropDown[1].innerHTML).toEqual('Minutes');
expect(dropDown[2].innerHTML).toEqual('Hours');
expect(dropDown[3].innerHTML).toEqual('Days');
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamDuration
});
});
it('Should save an Params object when the submit is performed', () => {
component.success.subscribe((res) => {
expect(res.dateRange.startDate).toEqual('2016-09-01T00:00:00.000Z');
expect(res.dateRange.endDate).toEqual('2016-10-05T00:00:00.000Z');
expect(res.status).toEqual('All');
expect(res.processDefinitionId).toEqual('FakeProcess:1:22');
expect(res.taskName).toEqual('FakeTaskName');
expect(res.duration).toEqual(22);
expect(res.dateRangeInterval).toEqual(120);
expect(res.slowProcessInstanceInteger).toEqual(2);
expect(res.typeFiltering).toEqual(true);
});
let values: any = {
dateRange: {
startDate: '2016-09-01', endDate: '2016-10-05'
},
statusGroup: {
status: 'All'
},
processDefGroup: {
processDefinitionId: 'FakeProcess:1:22'
},
taskGroup: {
taskName: 'FakeTaskName'
},
durationGroup: {
duration: 22
},
dateIntervalGroup: {
dateRangeInterval: 120
},
processInstanceGroup: {
slowProcessInstanceInteger: 2
},
typeFilteringGroup: {
typeFiltering: true
}
};
component.submit(values);
});
it('Should render a checkbox with the value true when the definition parameter type is \'boolean\' ', (done) => {
component.successReportParams.subscribe(() => {
fixture.detectChanges();
let checkElement: any = element.querySelector('#typeFiltering-input');
expect(checkElement.checked).toBeTruthy();
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamCheck
});
});
it('Should render a date range components when the definition parameter type is \'dateRange\' ', (done) => {
component.successReportParams.subscribe(() => {
let dateElement: any = element.querySelector('adf-date-range-widget');
expect(dateElement).toBeDefined();
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.toggleParameters();
component.ngOnChanges({'reportId': change});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamDateRange
});
});
it('Should render a dropdown with all the RangeInterval when the definition parameter type is \'dateRangeInterval\' ', (done) => {
component.successReportParams.subscribe(() => {
fixture.detectChanges();
let dropDown: any = element.querySelector('#select-dateRangeInterval');
expect(dropDown).toBeDefined();
expect(dropDown.length).toEqual(5);
expect(dropDown[0].innerHTML).toEqual('By hour');
expect(dropDown[1].innerHTML).toEqual('By day');
expect(dropDown[2].innerHTML).toEqual('By week');
expect(dropDown[3].innerHTML).toEqual('By month');
expect(dropDown[4].innerHTML).toEqual('By year');
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamRangeInterval
});
});
it('Should render a dropdown with all the process definition when the definition parameter type is \'processDefinition\' and the' +
' reportId change', (done) => {
component.successParamOpt.subscribe(() => {
fixture.detectChanges();
let dropDown: any = element.querySelector('#select-processDefinitionId');
expect(dropDown).toBeDefined();
expect(dropDown.length).toEqual(5);
expect(dropDown[0].innerHTML).toEqual('Choose One');
expect(dropDown[1].innerHTML).toEqual('Fake Process Test 1 Name (v 1) ');
expect(dropDown[2].innerHTML).toEqual('Fake Process Test 1 Name (v 2) ');
expect(dropDown[3].innerHTML).toEqual('Fake Process Test 2 Name (v 1) ');
expect(dropDown[4].innerHTML).toEqual('Fake Process Test 3 Name (v 1) ');
done();
});
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/report-params/1').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDef
});
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/process-definitions').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDefOptionsNoApp
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
});
it('Should render a dropdown with all the process definition when the definition parameter type is \'processDefinition\' and the' +
' appId change', (done) => {
component.successParamOpt.subscribe(() => {
fixture.detectChanges();
let dropDown: any = element.querySelector('#select-processDefinitionId');
expect(dropDown).toBeDefined();
expect(dropDown.length).toEqual(3);
expect(dropDown[0].innerHTML).toEqual('Choose One');
expect(dropDown[1].innerHTML).toEqual('Fake Process Test 1 Name (v 1) ');
expect(dropDown[2].innerHTML).toEqual('Fake Process Test 1 Name (v 2) ');
done();
});
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/report-params/1').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDef
});
let appId = 1;
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/api/enterprise/process-definitions?appDefinitionId=' + appId).andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDefOptionsApp
});
component.appId = appId;
component.reportId = '1';
let change = new SimpleChange(null, appId, true);
component.ngOnChanges({'appId': change});
});
it('Should create an empty valid form when there are no parameters definitions', () => {
component.success.subscribe((res) => {
expect(component.reportForm).toBeDefined();
expect(component.reportForm.valid).toEqual(true);
expect(component.reportForm.controls).toEqual({});
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportNoParameterDefinitions
});
});
it('Should load the task list when a process definition is selected', () => {
component.successReportParams.subscribe((res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(2);
expect(res[0].id).toEqual('Fake task name 1');
expect(res[0].name).toEqual('Fake task name 1');
expect(res[1].id).toEqual('Fake task name 2');
expect(res[1].name).toEqual('Fake task name 2');
});
component.reportId = '100';
component.reportParameters = new ReportParametersModel(analyticParamsMock.reportDefParamTask);
component.onProcessDefinitionChanges(analyticParamsMock.fieldProcessDef);
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamTaskOptions
});
});
it('Should emit an error with a 404 response when the options response is not found', (done) => {
component.error.subscribe((err) => {
expect(err).toBeDefined();
done();
});
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/report-params/1').andReturn({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamProcessDef
});
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/process-definitions').andReturn({
status: 404,
contentType: 'json',
responseText: []
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
});
it('Should emit an error with a 404 response when the report parameters response is not found', (done) => {
component.error.subscribe((err) => {
expect(err).toBeDefined();
done();
});
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 404,
contentType: 'json',
responseText: []
});
});
it('Should convert a string in number', () => {
let numberConvert = component.convertNumber('2');
expect(numberConvert).toEqual(2);
});
describe('When the form is rendered correctly', () => {
let validForm: boolean = true;
let values: any = {
dateRange: {
startDate: '2016-09-01', endDate: '2016-10-05'
},
statusGroup: {
status: 'All'
},
processDefGroup: {
processDefinitionId: 'FakeProcess:1:22'
},
taskGroup: {
taskName: 'FakeTaskName'
},
durationGroup: {
duration: 22
},
dateIntervalGroup: {
dateRangeInterval: 120
},
processInstanceGroup: {
slowProcessInstanceInteger: 2
},
typeFilteringGroup: {
typeFiltering: true
}
};
beforeEach(async(() => {
let reportId = 1;
let change = new SimpleChange(null, reportId, true);
component.ngOnChanges({'reportId': change});
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamStatus
});
fixture.whenStable().then(() => {
component.toggleParameters();
component.reportId = '1';
spyOn(component, 'isFormValid').and.callFake(() => {
return validForm;
});
fixture.detectChanges();
});
}));
afterEach(() => {
validForm = true;
});
it('Should be able to change the report title', (done) => {
let title: HTMLElement = element.querySelector('h4');
title.click();
fixture.detectChanges();
let reportName: HTMLInputElement = <HTMLInputElement> element.querySelector('#reportName');
expect(reportName).not.toBeNull();
reportName.focus();
component.reportParameters.name = 'FAKE_TEST_NAME';
reportName.value = 'FAKE_TEST_NAME';
reportName.dispatchEvent(new Event('blur'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
let titleChanged: HTMLElement = element.querySelector('h4');
expect(titleChanged.textContent.trim()).toEqual('FAKE_TEST_NAME');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: analyticParamsMock.reportDefParamStatus
});
});
xit('Should show a dialog to allowing report save', async(() => {
component.saveReportSuccess.subscribe((repId) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(repId).toBe('1');
});
});
component.submit(values);
fixture.detectChanges();
let saveButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#save-button');
expect(saveButton).toBeDefined();
expect(saveButton).not.toBeNull();
saveButton.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
let reportDialogTitle: HTMLElement = <HTMLElement> window.document.querySelector('#report-dialog-title');
let saveTitleSubMessage: HTMLElement = <HTMLElement> window.document.querySelector('#save-title-submessage');
let inputSaveName: HTMLInputElement = <HTMLInputElement> window.document.querySelector('#repName');
let performActionButton: HTMLButtonElement = <HTMLButtonElement> window.document.querySelector('#action-dialog-button');
let todayDate = component.getTodayDate();
expect(reportDialogTitle).not.toBeNull('Dialog title should not be null');
expect(saveTitleSubMessage).not.toBeNull('Dialog save title submessage should not be null');
expect(inputSaveName.value.trim()).toEqual(analyticParamsMock.reportDefParamStatus.name + ' ( ' + todayDate + ' )');
expect(performActionButton).not.toBeNull('Dialog action button should not be null');
performActionButton.click();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json'
});
});
}));
xit('Should show a dialog to allowing report export', async(() => {
component.submit(values);
fixture.detectChanges();
let exportButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#export-button');
expect(exportButton).toBeDefined();
expect(exportButton).not.toBeNull();
exportButton.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
let reportDialogTitle: HTMLElement = <HTMLElement> window.document.querySelector('#report-dialog-title');
let inputSaveName: HTMLInputElement = <HTMLInputElement> window.document.querySelector('#repName');
let performActionButton: HTMLButtonElement = <HTMLButtonElement> window.document.querySelector('#action-dialog-button');
let todayDate = component.getTodayDate();
expect(reportDialogTitle).not.toBeNull();
expect(inputSaveName.value.trim()).toEqual(analyticParamsMock.reportDefParamStatus.name + ' ( ' + todayDate + ' )');
expect(performActionButton).not.toBeNull();
performActionButton.click();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json'
});
});
}));
it('Should raise an event for report deleted', async(() => {
let deleteButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#delete-button');
expect(deleteButton).toBeDefined();
expect(deleteButton).not.toBeNull();
component.deleteReportSuccess.subscribe((reportId) => {
expect(reportId).not.toBeNull();
});
deleteButton.click();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json'
});
}));
it('Should hide export button if the form is not valid', async(() => {
let exportButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#export-button');
expect(exportButton).toBeDefined();
expect(exportButton).not.toBeNull();
validForm = false;
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
exportButton = <HTMLButtonElement> element.querySelector('#export-button');
expect(exportButton).toBeNull();
});
}));
it('Should hide save button if the form is not valid', async(() => {
let saveButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#save-button');
expect(saveButton).toBeDefined();
expect(saveButton).not.toBeNull();
validForm = false;
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
saveButton = <HTMLButtonElement> element.querySelector('#save-button');
expect(saveButton).toBeNull();
});
}));
it('Should show export and save button when the form became valid', async(() => {
validForm = false;
fixture.detectChanges();
let saveButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#save-button');
let exportButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#export-button');
expect(saveButton).toBeNull();
expect(exportButton).toBeNull();
validForm = true;
fixture.whenStable().then(() => {
fixture.detectChanges();
saveButton = <HTMLButtonElement> element.querySelector('#save-button');
exportButton = <HTMLButtonElement> element.querySelector('#export-button');
expect(saveButton).not.toBeNull();
expect(saveButton).toBeDefined();
expect(exportButton).not.toBeNull();
expect(exportButton).toBeDefined();
});
}));
});
});
});

View File

@@ -0,0 +1,384 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ContentService, LogService } from '@alfresco/core';
import {
AfterContentChecked,
Component,
EventEmitter,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material';
import * as moment from 'moment';
import { ParameterValueModel, ReportParameterDetailsModel, ReportParametersModel, ReportQuery } from '../../diagram';
import { AnalyticsService } from '../services/analytics.service';
@Component({
selector: 'adf-analytics-report-parameters, analytics-report-parameters',
templateUrl: './analytics-report-parameters.component.html',
styleUrls: ['./analytics-report-parameters.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class AnalyticsReportParametersComponent implements OnInit, OnChanges, OnDestroy, AfterContentChecked {
public static FORMAT_DATE_ACTIVITI: string = 'YYYY-MM-DD';
@Input()
appId: number;
@Input()
reportId: string;
@Input()
hideComponent: boolean = false;
@Output()
success = new EventEmitter();
@Output()
error = new EventEmitter();
@Output()
edit = new EventEmitter();
@Output()
formValueChanged = new EventEmitter();
@Output()
saveReportSuccess = new EventEmitter();
@Output()
deleteReportSuccess = new EventEmitter();
@ViewChild('reportNameDialog')
reportNameDialog: any;
onDropdownChanged = new EventEmitter();
successReportParams = new EventEmitter();
successParamOpt = new EventEmitter();
reportParameters: ReportParametersModel;
reportForm: FormGroup;
action: string;
isEditable: boolean = false;
reportName: string;
private dropDownSub;
private reportParamsSub;
private paramOpts;
private reportParamQuery: ReportQuery;
private hideParameters: boolean = true;
private formValidState: boolean = false;
constructor(private analyticsService: AnalyticsService,
private formBuilder: FormBuilder,
private logService: LogService,
private contentService: ContentService,
private dialog: MatDialog) {
}
ngOnInit() {
this.dropDownSub = this.onDropdownChanged.subscribe((field) => {
let paramDependOn: ReportParameterDetailsModel = this.reportParameters.definition.parameters.find(p => p.dependsOn === field.id);
if (paramDependOn) {
this.retrieveParameterOptions(this.reportParameters.definition.parameters, this.appId, this.reportId, field.value);
}
});
this.paramOpts = this.successReportParams.subscribe((report: ReportParametersModel) => {
if (report.hasParameters()) {
this.retrieveParameterOptions(report.definition.parameters, this.appId);
this.generateFormGroupFromParameter(report.definition.parameters);
}
});
}
ngOnChanges(changes: SimpleChanges) {
this.isEditable = false;
if (this.reportForm) {
this.reportForm.reset();
}
let reportId = changes['reportId'];
if (reportId && reportId.currentValue) {
this.getReportParams(reportId.currentValue);
}
let appId = changes['appId'];
if (appId && (appId.currentValue || appId.currentValue === null)) {
this.getReportParams(this.reportId);
}
}
private generateFormGroupFromParameter(parameters: ReportParameterDetailsModel[]) {
let formBuilderGroup: any = {};
parameters.forEach((param: ReportParameterDetailsModel) => {
switch (param.type) {
case 'dateRange' :
formBuilderGroup.dateRange = new FormGroup({}, Validators.required);
break;
case 'processDefinition':
formBuilderGroup.processDefGroup = new FormGroup({
processDefinitionId: new FormControl(null, Validators.required, null)
}, Validators.required);
break;
case 'duration':
formBuilderGroup.durationGroup = new FormGroup({
duration: new FormControl(null, Validators.required, null)
}, Validators.required);
break;
case 'dateInterval':
formBuilderGroup.dateIntervalGroup = new FormGroup({
dateRangeInterval: new FormControl(null, Validators.required, null)
}, Validators.required);
break;
case 'boolean':
formBuilderGroup.typeFilteringGroup = new FormGroup({
typeFiltering: new FormControl(null, Validators.required, null)
}, Validators.required);
break;
case 'task':
formBuilderGroup.taskGroup = new FormGroup({
taskName: new FormControl(null, Validators.required, null)
}, Validators.required);
break;
case 'integer':
formBuilderGroup.processInstanceGroup = new FormGroup({
slowProcessInstanceInteger: new FormControl(null, Validators.required, null)
}, Validators.required);
break;
case 'status':
formBuilderGroup.statusGroup = new FormGroup({
status: new FormControl(null, Validators.required, null)
}, Validators.required);
break;
default:
return;
}
});
this.reportForm = this.formBuilder.group(formBuilderGroup);
this.reportForm.valueChanges.subscribe(data => this.onValueChanged(data));
this.reportForm.statusChanges.subscribe(data => this.onStatusChanged(data));
}
public getReportParams(reportId: string) {
this.reportParamsSub = this.analyticsService.getReportParams(reportId).subscribe(
(res: ReportParametersModel) => {
this.reportParameters = res;
if (this.reportParameters.hasParameters()) {
this.successReportParams.emit(res);
} else {
this.reportForm = this.formBuilder.group({});
this.success.emit();
}
},
(err: any) => {
this.error.emit(err);
}
);
}
private retrieveParameterOptions(parameters: ReportParameterDetailsModel[], appId: number, reportId?: string, processDefinitionId?: string) {
parameters.forEach((param) => {
this.analyticsService.getParamValuesByType(param.type, appId, reportId, processDefinitionId).subscribe(
(opts: ParameterValueModel[]) => {
param.options = opts;
this.successParamOpt.emit(opts);
},
(err: any) => {
this.error.emit(err);
}
);
});
}
onProcessDefinitionChanges(field: any) {
if (field.value) {
this.onDropdownChanged.emit(field);
}
}
public submit(values: any) {
this.reportParamQuery = this.convertFormValuesToReportParamQuery(values);
this.success.emit(this.reportParamQuery);
}
onValueChanged(values: any) {
this.formValueChanged.emit(values);
if (this.reportForm && this.reportForm.valid) {
this.submit(values);
}
}
onStatusChanged(status: any) {
if (this.reportForm && !this.reportForm.pending && this.reportForm.dirty) {
this.formValidState = this.reportForm.valid;
}
}
public convertMomentDate(date: string) {
return moment(date, AnalyticsReportParametersComponent.FORMAT_DATE_ACTIVITI, true)
.format(AnalyticsReportParametersComponent.FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z';
}
public getTodayDate() {
return moment().format(AnalyticsReportParametersComponent.FORMAT_DATE_ACTIVITI);
}
public convertNumber(value: string): number {
return value != null ? parseInt(value, 10) : 0;
}
convertFormValuesToReportParamQuery(values: any): ReportQuery {
let reportParamQuery: ReportQuery = new ReportQuery();
if (values.dateRange) {
reportParamQuery.dateRange.startDate = this.convertMomentDate(values.dateRange.startDate);
reportParamQuery.dateRange.endDate = this.convertMomentDate(values.dateRange.endDate);
}
if (values.statusGroup) {
reportParamQuery.status = values.statusGroup.status;
}
if (values.processDefGroup) {
reportParamQuery.processDefinitionId = values.processDefGroup.processDefinitionId;
}
if (values.taskGroup) {
reportParamQuery.taskName = values.taskGroup.taskName;
}
if (values.durationGroup) {
reportParamQuery.duration = values.durationGroup.duration;
}
if (values.dateIntervalGroup) {
reportParamQuery.dateRangeInterval = values.dateIntervalGroup.dateRangeInterval;
}
if (values.processInstanceGroup) {
reportParamQuery.slowProcessInstanceInteger = this.convertNumber(values.processInstanceGroup.slowProcessInstanceInteger);
}
if (values.typeFilteringGroup) {
reportParamQuery.typeFiltering = values.typeFilteringGroup.typeFiltering;
}
return reportParamQuery;
}
ngOnDestroy() {
this.dropDownSub.unsubscribe();
this.paramOpts.unsubscribe();
if (this.reportParamsSub) {
this.reportParamsSub.unsubscribe();
}
}
public editEnable() {
this.isEditable = true;
}
public editDisable() {
this.isEditable = false;
}
public editTitle() {
this.reportParamsSub = this.analyticsService.updateReport(this.reportParameters.id, this.reportParameters.name).subscribe(
(res: ReportParametersModel) => {
this.editDisable();
this.edit.emit(this.reportParameters.name);
},
(err: any) => {
this.error.emit(err);
}
);
}
public showDialog(event: string) {
this.dialog.open(this.reportNameDialog, { width: '500px' });
this.action = event;
this.reportName = this.reportParameters.name + ' ( ' + this.getTodayDate() + ' )';
}
closeDialog() {
this.dialog.closeAll();
}
performAction(action: string, reportParamQuery: ReportQuery) {
reportParamQuery.reportName = this.reportName;
this.closeDialog();
if (action === 'Save') {
this.doSave(reportParamQuery);
} else if (action === 'Export') {
this.doExport(reportParamQuery);
}
this.resetActions();
}
resetActions() {
this.action = '';
this.reportName = '';
}
isSaveAction() {
return this.action === 'Save';
}
isFormValid() {
return this.reportForm && this.reportForm.dirty && this.reportForm.valid;
}
doExport(paramQuery: ReportQuery) {
this.analyticsService.exportReportToCsv(this.reportId, paramQuery).subscribe(
(data: any) => {
let blob: Blob = new Blob([data], {type: 'text/csv'});
this.contentService.downloadBlob(blob, paramQuery.reportName + '.csv');
});
}
doSave(paramQuery: ReportQuery) {
this.analyticsService.saveReport(this.reportId, paramQuery).subscribe(() => {
this.saveReportSuccess.emit(this.reportId);
});
}
deleteReport(reportId: string) {
this.analyticsService.deleteReport(reportId).subscribe(() => {
this.deleteReportSuccess.emit(reportId);
}, error => this.logService.error(error));
}
ngAfterContentChecked() {
if (this.reportForm && this.reportForm.valid) {
this.reportForm.markAsDirty();
}
}
toggleParameters() {
this.hideParameters = !this.hideParameters;
}
isParametersHide() {
return this.hideParameters;
}
}

View File

@@ -0,0 +1,15 @@
<div class="adf-analytics-container">
<analytics-report-parameters [appId]="appId" [reportId]="reportId"
[hideComponent]="hideParameters"
(formValueChanged)="reset()"
(success)="showReport($event)"
(saveReportSuccess)="onSaveReportSuccess($event)"
(deleteReportSuccess)="onDeleteReportSuccess()"
(edit)="onEditReport($event)">
</analytics-report-parameters>
<adf-analytics-generator [reportId]="reportId"
[reportParamQuery]="reportParamQuery"
#analyticsgenerator>
</adf-analytics-generator>
</div>

View File

@@ -0,0 +1 @@
.chart {display: block; width: 100%;}

View File

@@ -0,0 +1,85 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DiagramsModule } from '../../diagram';
import { ChartsModule } from 'ng2-charts';
import { AnalyticsGeneratorComponent } from '../components/analytics-generator.component';
import { AnalyticsReportHeatMapComponent } from '../components/analytics-report-heat-map.component';
import { AnalyticsReportListComponent } from '../components/analytics-report-list.component';
import { AnalyticsReportParametersComponent } from '../components/analytics-report-parameters.component';
import { AnalyticsComponent } from '../components/analytics.component';
import { WIDGET_ANALYTICS_DIRECTIVES } from '../components/widgets/index';
import { AnalyticsService } from '../services/analytics.service';
export const ANALYTICS_DIRECTIVES: any[] = [
AnalyticsComponent,
AnalyticsGeneratorComponent,
AnalyticsReportParametersComponent,
AnalyticsReportListComponent,
AnalyticsReportHeatMapComponent,
WIDGET_ANALYTICS_DIRECTIVES
];
export const ANALYTICS_PROVIDERS: any[] = [
AnalyticsService
];
declare let jasmine: any;
describe('AnalyticsComponent', () => {
let component: any;
let fixture: ComponentFixture<AnalyticsComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
ChartsModule,
DiagramsModule
],
declarations: [
...ANALYTICS_DIRECTIVES
],
providers: [
...ANALYTICS_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AnalyticsComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
describe('Rendering tests', () => {
beforeEach(() => {
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
});
});

View File

@@ -0,0 +1,77 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';
import { ReportQuery } from '../../diagram';
import { AnalyticsGeneratorComponent } from './analytics-generator.component';
@Component({
selector: 'adf-analytics',
templateUrl: './analytics.component.html',
styleUrls: ['./analytics.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class AnalyticsComponent implements OnChanges {
@Input()
appId: number;
@Input()
reportId: number;
@Input()
hideParameters: boolean = false;
@Output()
editReport = new EventEmitter();
@Output()
reportSaved = new EventEmitter();
@Output()
reportDeleted = new EventEmitter();
@ViewChild('analyticsgenerator')
analyticsgenerator: AnalyticsGeneratorComponent;
reportParamQuery: ReportQuery;
ngOnChanges(changes: SimpleChanges) {
this.analyticsgenerator.reset();
}
public showReport($event) {
this.analyticsgenerator.generateReport(this.reportId, $event);
}
public reset() {
this.analyticsgenerator.reset();
}
public onEditReport(name: string) {
this.editReport.emit(name);
}
public onSaveReportSuccess(reportId) {
this.reportSaved.emit(reportId);
}
public onDeleteReportSuccess() {
this.reportDeleted.emit();
}
}

View File

@@ -0,0 +1,9 @@
<div [formGroup]="formGroup">
<mat-checkbox
color="primary"
formControlName="{{controllerName}}"
[id]="field.id"
[checked]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="changeValue(field)">{{field.nameKey | translate}}</mat-checkbox>
</div>

View File

@@ -0,0 +1,44 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
/* tslint:disable:no-access-missing-member */
import { Component, ElementRef, Input, ViewEncapsulation } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { WidgetComponent } from './../widget.component';
@Component({
selector: 'analytics-checkbox-widget',
templateUrl: './checkbox.widget.html',
encapsulation: ViewEncapsulation.None
})
export class CheckboxWidgetAanalyticsComponent extends WidgetComponent {
@Input()
field: any;
@Input('group')
public formGroup: FormGroup;
@Input('controllerName')
public controllerName: string;
constructor(public elementRef: ElementRef) {
super();
}
}

View File

@@ -0,0 +1,54 @@
<label>{{field.nameKey | translate}}</label><br>
<div [formGroup]="dateRange">
<small *ngIf="isStartDateGreaterThanEndDate()" class="adf-date-range-analytics-text-danger">
{{'DATE-WIDGET.MESSAGES.START-LESS-THAN-END-DATE' | translate}}
</small>
<small *ngIf="isStartDateEmpty()" class="adf-date-range-analytics-text-danger">
{{'DATE-WIDGET.MESSAGES.START-DATE-REQUIRED' | translate}}
</small>
<mat-grid-list cols="2" rowHeight="80px">
<mat-grid-tile>
<mat-form-field>
<input
matInput
[min]="minDate"
[max]="maxDate"
formControlName="startDate"
[matDatepicker]="startDate"
[value]="startDatePicker"
(keydown)="true"
(dateChange)="onGroupValueChanged()"
placeholder="{{'DATE-WIDGET.START-DATE' | translate}}"
id="startDate_id"
required>
<mat-datepicker-toggle matSuffix [for]="startDate" ></mat-datepicker-toggle>
</mat-form-field>
<mat-datepicker
#startDate
[touchUi]="true">
</mat-datepicker>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field>
<input
matInput
[min]="minDate"
[max]="maxDate"
formControlName="endDate"
[matDatepicker]="endDate"
[value]="endDatePicker"
(keydown)="true"
(dateChange)="onGroupValueChanged()"
placeholder="{{'DATE-WIDGET.END-DATE' | translate}}"
id="endDate_id"
required>
<mat-datepicker-toggle matSuffix [for]="endDate" ></mat-datepicker-toggle>
</mat-form-field>
<mat-datepicker
#endDate
[touchUi]="true">
</mat-datepicker>
</mat-grid-tile>
</mat-grid-list>
</div>

View File

@@ -0,0 +1,7 @@
@mixin adf-analytics-date-range-widget-theme($theme) {
$warn: map-get($theme, warn);
.adf-date-range-analytics-text-danger {
color: mat-color($warn);
}
}

View File

@@ -0,0 +1,113 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { MOMENT_DATE_FORMATS, MomentDateAdapter, UserPreferencesService } from '@alfresco/core';
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
import * as moment from 'moment';
import { Moment } from 'moment';
@Component({
selector: 'adf-date-range-widget',
templateUrl: './date-range.widget.html',
providers: [
{provide: DateAdapter, useClass: MomentDateAdapter},
{provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS}],
styleUrls: ['./date-range.widget.scss'],
encapsulation: ViewEncapsulation.None
})
export class DateRangeWidgetComponent implements OnInit {
public FORMAT_DATE_ACTIVITI: string = 'YYYY-MM-DD';
public SHOW_FORMAT: string = 'DD/MM/YYYY';
@Input('group')
public dateRange: FormGroup;
@Input()
field: any;
@Output()
dateRangeChanged: EventEmitter<any> = new EventEmitter<any>();
minDate: Moment;
maxDate: Moment;
startDatePicker: Moment = moment();
endDatePicker: Moment = moment();
constructor(
private dateAdapter: DateAdapter<Moment>,
private preferences: UserPreferencesService) {
}
ngOnInit() {
this.preferences.locale$.subscribe( (locale) => {
this.dateAdapter.setLocale(locale);
});
let momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
momentDateAdapter.overrideDisplyaFormat = this.SHOW_FORMAT;
if (this.field) {
if (this.field.value && this.field.value.startDate) {
this.startDatePicker = moment(this.field.value.startDate, this.FORMAT_DATE_ACTIVITI);
}
if (this.field.value && this.field.value.endDate) {
this.endDatePicker = moment(this.field.value.endDate, this.FORMAT_DATE_ACTIVITI);
}
}
let startDateControl = new FormControl(this.startDatePicker);
startDateControl.setValidators(Validators.required);
this.dateRange.addControl('startDate', startDateControl);
let endDateControl = new FormControl(this.endDatePicker);
endDateControl.setValidators(Validators.required);
this.dateRange.addControl('endDate', endDateControl);
this.dateRange.setValidators(this.dateCheck);
this.dateRange.valueChanges.subscribe(() => this.onGroupValueChanged());
}
onGroupValueChanged() {
if (this.dateRange.valid) {
let dateStart = this.convertToMomentDateWithTime(this.dateRange.controls.startDate.value);
let endStart = this.convertToMomentDateWithTime(this.dateRange.controls.endDate.value);
this.dateRangeChanged.emit({startDate: dateStart, endDate: endStart});
}
}
convertToMomentDateWithTime(date: string) {
return moment(date, this.FORMAT_DATE_ACTIVITI, true).format(this.FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z';
}
dateCheck(formControl: AbstractControl) {
let startDate = moment(formControl.get('startDate').value);
let endDate = moment(formControl.get('endDate').value);
let result = startDate.isAfter(endDate);
return result ? {'greaterThan': true} : null;
}
isStartDateGreaterThanEndDate() {
return this.dateRange && this.dateRange.errors && this.dateRange.errors.greaterThan;
}
isStartDateEmpty() {
return this.dateRange && this.dateRange.controls.startDate && !this.dateRange.controls.startDate.valid;
}
}

View File

@@ -0,0 +1,11 @@
<div class="adf-dropdown-widget" [formGroup]="formGroup">
<label class="adf-dropdown-widget__label" [attr.for]="field.id">{{field.nameKey | translate}}</label>
<select [formControlName]="controllerName"
[attr.id]="'select-' + field.id"
class="adf-dropdown-widget__select"
[(ngModel)]="field.value"
(ngModelChange)="changeValue($event)">
<option *ngIf="showDefaultOption" value="null">{{defaultOptionText}}</option>
<option *ngFor="let opt of field.options" [value]="opt.id">{{opt.label}}</option>
</select>
</div>

View File

@@ -0,0 +1,19 @@
.adf-dropdown-widget {
width: 100%;
}
.adf-dropdown-widget__select {
width: 100%;
}
.adf-dropdown-widget__invalid .adf-dropdown-widget__select {
border-color: #d50000;
}
.adf-dropdown-widget__invalid .adf-dropdown-widget__label {
color: #d50000;
}
.adf-dropdown-widget__invalid .adf-dropdown-widget__label:after {
background-color: #d50000;
}

View File

@@ -0,0 +1,76 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
/* tslint:disable::no-access-missing-member */
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { WidgetComponent } from './../widget.component';
@Component({
selector: 'analytics-dropdown-widget',
templateUrl: './dropdown.widget.html',
styleUrls: ['./dropdown.widget.scss'],
encapsulation: ViewEncapsulation.None
})
export class DropdownWidgetAanalyticsComponent extends WidgetComponent implements OnInit {
@Input()
field: any;
@Input('group')
public formGroup: FormGroup;
@Input('controllerName')
public controllerName: string;
@Output()
fieldChanged: EventEmitter<any> = new EventEmitter<any>();
@Input()
showDefaultOption: boolean = true;
@Input()
required: boolean = false;
@Input()
defaultOptionText: string = 'Choose One';
constructor() {
super();
}
ngOnInit() {
if (this.required) {
this.formGroup.get(this.controllerName).setValidators(Validators.compose(this.buildValidatorList()));
}
}
validateDropDown(controller: FormControl) {
return controller.value !== 'null' ? null : { controllerName: false };
}
buildValidatorList() {
let validatorList = [];
validatorList.push(Validators.required);
if (this.showDefaultOption) {
validatorList.push(this.validateDropDown);
}
return validatorList;
}
}

View File

@@ -0,0 +1,23 @@
<div class="adf-duration-widget-grid">
<div class="adf-duration-widget-cell">
<div class="adf-number-widget">
<mat-form-field class="example-full-width" floatPlaceholder="always">
<input matInput
placeholder="{{field.nameKey | translate}}"
type="text"
pattern="-?[0-9]*(\.[0-9]+)?"
[id]="field.id"
[value]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="calculateDuration()">
</mat-form-field>
</div>
</div>
<div class="adf-duration-widget-cell">
<div class="dropdown-container">
<analytics-dropdown-widget [field]="duration" [group]="formGroup" [controllerName]="'timeType'"
[showDefaultOption]="false"
(fieldChanged)="calculateDuration()"></analytics-dropdown-widget>
</div>
</div>
</div>

View File

@@ -0,0 +1,20 @@
.adf-duration-widget-grid {
display: flex;
justify-content: space-between;
}
.adf-duration-widget-cell {
width: 49%;
}
.adf-number-widget {
width: 100%;
.mat-form-field {
width: 100%;
}
}
.dropdown-container {
margin-top: 30px;
}

View File

@@ -0,0 +1,84 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
/* tslint:disable::no-access-missing-member */
import { Component, ElementRef, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ParameterValueModel, ReportParameterDetailsModel } from '../../../../diagram';
import { NumberWidgetAanlyticsComponent } from './../number/number.widget';
@Component({
selector: 'duration-widget',
templateUrl: './duration.widget.html',
styleUrls: ['./duration.widget.scss'],
encapsulation: ViewEncapsulation.None
})
export class DurationWidgetComponent extends NumberWidgetAanlyticsComponent implements OnInit {
@Input()
field: any;
@Input('group')
public formGroup: FormGroup;
@Input('controllerName')
public controllerName: string;
@Input()
required: boolean = false;
duration: ReportParameterDetailsModel;
currentValue: number;
public selectionGroup: FormGroup;
constructor(public elementRef: ElementRef) {
super(elementRef);
}
ngOnInit() {
let timeType = new FormControl();
this.formGroup.addControl('timeType', timeType);
if (this.required) {
this.formGroup.get(this.controllerName).setValidators(Validators.required);
}
if (this.field.value === null) {
this.field.value = 0;
}
let paramOptions: ParameterValueModel[] = [];
paramOptions.push(new ParameterValueModel({id: '1', name: 'Seconds'}));
paramOptions.push(new ParameterValueModel({id: '60', name: 'Minutes'}));
paramOptions.push(new ParameterValueModel({id: '3600', name: 'Hours'}));
paramOptions.push(new ParameterValueModel({id: '86400', name: 'Days', selected: true}));
this.duration = new ReportParameterDetailsModel({id: 'duration', name: 'duration', options: paramOptions});
this.duration.value = paramOptions[0].id;
}
public calculateDuration() {
if (this.field && this.duration.value ) {
this.currentValue = parseInt(this.field.value, 10) * parseInt(this.duration.value, 10);
this.formGroup.get(this.controllerName).setValue(this.currentValue);
this.fieldChanged.emit({value: this.currentValue});
}
}
}

View File

@@ -0,0 +1,37 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { CheckboxWidgetAanalyticsComponent } from './checkbox/checkbox.widget';
import { DateRangeWidgetComponent } from './date-range/date-range.widget';
import { DropdownWidgetAanalyticsComponent } from './dropdown/dropdown.widget';
import { DurationWidgetComponent } from './duration/duration.widget';
import { NumberWidgetAanlyticsComponent } from './number/number.widget';
// primitives
export * from './dropdown/dropdown.widget';
export * from './number/number.widget';
export * from './duration/duration.widget';
export * from './checkbox/checkbox.widget';
export * from './date-range/date-range.widget';
export const WIDGET_ANALYTICS_DIRECTIVES: any[] = [
DropdownWidgetAanalyticsComponent,
NumberWidgetAanlyticsComponent,
DurationWidgetComponent,
CheckboxWidgetAanalyticsComponent,
DateRangeWidgetComponent
];

View File

@@ -0,0 +1,13 @@
<div class="adf-number-widget" [formGroup]="formGroup">
<mat-form-field class="example-full-width" floatPlaceholder="always">
<input matInput
placeholder="{{field.nameKey | translate}}"
formControlName="{{controllerName}}"
type="text"
pattern="-?[0-9]*(\.[0-9]+)?"
[id]="field.id"
[value]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="changeValue(field)">
</mat-form-field>
</div>

View File

@@ -0,0 +1,7 @@
.adf-number-widget {
width: 100%;
.mat-form-field {
width: 100%;
}
}

View File

@@ -0,0 +1,54 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
/* tslint:disable::no-access-missing-member */
import { Component, ElementRef, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { FormGroup, Validators } from '@angular/forms';
import { WidgetComponent } from './../widget.component';
@Component({
selector: 'analytics-number-widget',
templateUrl: './number.widget.html',
styleUrls: ['./number.widget.scss'],
encapsulation: ViewEncapsulation.None
})
export class NumberWidgetAanlyticsComponent extends WidgetComponent implements OnInit {
@Input()
field: any;
@Input('group')
public formGroup: FormGroup;
@Input('controllerName')
public controllerName: string;
@Input()
required: boolean = false;
constructor(public elementRef: ElementRef) {
super();
}
ngOnInit() {
if (this.required) {
this.formGroup.get(this.controllerName).setValidators(Validators.required);
}
}
}

View File

@@ -0,0 +1,50 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
export class WidgetComponent implements OnChanges {
@Input()
field: any;
@Output()
fieldChanged: EventEmitter<any> = new EventEmitter<any>();
ngOnChanges(changes: SimpleChanges) {
let field = changes['field'];
if (field && field.currentValue) {
this.fieldChanged.emit(field.currentValue.value);
return;
}
}
hasField() {
return this.field ? true : false;
}
hasValue(): boolean {
return this.field &&
this.field.value !== null &&
this.field.value !== undefined;
}
changeValue(field: any) {
this.fieldChanged.emit(field);
}
}

View File

@@ -0,0 +1,18 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './public-api';

View File

@@ -0,0 +1,66 @@
Error.stackTraceLimit = Infinity;
require('core-js/es6');
require('core-js/es7/reflect');
require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy');
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
var appContext = require.context(".", true, /\.spec\.ts/);
appContext.keys().forEach(appContext);
const TestBed = require('@angular/core/testing').TestBed;
const browser = require('@angular/platform-browser-dynamic/testing');
const CoreModule = require('@alfresco/core').CoreModule;
const AppConfigService = require('@alfresco/core').AppConfigService;
const AppConfigServiceMock = require('@alfresco/core').AppConfigServiceMock;
const TranslationService = require('@alfresco/core').TranslationService;
const TranslationMock = require('@alfresco/core').TranslationMock;
TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting());
patchTestBedToDestroyFixturesAfterEveryTest(TestBed);
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreModule],
providers: [
{provide: AppConfigService, useClass: AppConfigServiceMock},
{provide: TranslationService, useClass: TranslationMock}
]
});
});
afterEach(() => {
TestBed.resetTestingModule();
});
function patchTestBedToDestroyFixturesAfterEveryTest(testBed) {
// Original resetTestingModule function of the TestBed.
var _resetTestingModule = testBed.resetTestingModule;
// Monkey-patch the resetTestingModule to destroy fixtures outside of a try/catch block.
// With https://github.com/angular/angular/commit/2c5a67134198a090a24f6671dcdb7b102fea6eba
// errors when destroying components are no longer causing Jasmine to fail.
testBed.resetTestingModule = function() {
try {
if(this._activeFixtures) {
this._activeFixtures.forEach(function (fixture) {
fixture.destroy();
});
}
} finally {
this._activeFixtures = [];
// Regardless of errors or not, run the original reset testing module function.
_resetTestingModule.call(this);
}
};
};

View File

@@ -0,0 +1,25 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './components/analytics.component';
export * from './components/analytics-generator.component';
export * from './components/analytics-report-list.component';
export * from './components/analytics-report-parameters.component';
export * from './services/analytics.service';
export * from './components/widgets/index';
export * from './analytics-process.module';

View File

@@ -0,0 +1,86 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
import { AlfrescoApiService } from '@alfresco/core';
import { fakeReportList } from '../../mock';
import { AnalyticsService } from './analytics.service';
declare let jasmine: any;
describe('Activiti Analytics Service', () => {
let service: AnalyticsService;
let apiService: AlfrescoApiService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
AnalyticsService
]
});
service = TestBed.get(AnalyticsService);
apiService = TestBed.get(AlfrescoApiService);
});
beforeEach(() => {
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
describe('Content tests', () => {
it('should return the report list by appId', (done) => {
service.getReportList(1).subscribe(
(reportList) => {
expect(reportList).toBeDefined();
expect(reportList.length).toEqual(2);
expect(reportList[0].name).toEqual('Fake Report 1');
expect(reportList[1].name).toEqual('Fake Report 2');
done();
}
);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeReportList)
});
});
it('should return the report by report name', (done) => {
service.getReportByName('Fake Report 2').subscribe(
(report) => {
expect(report).toBeDefined();
expect(report).not.toBeNull();
expect(report.id).toEqual(2);
done();
}
);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeReportList)
});
});
});
});

View File

@@ -0,0 +1,248 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AlfrescoApiService, LogService } from '@alfresco/core';
import { Injectable } from '@angular/core';
import { Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { ParameterValueModel, ReportParametersModel } from '../../diagram';
import {
BarChart,
Chart,
DetailsTableChart,
HeatMapChart,
MultiBarChart,
PieChart,
TableChart
} from '../../diagram';
@Injectable()
export class AnalyticsService {
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
}
/**
* Retrive all the Deployed app
* @returns {Observable<any>}
*/
getReportList(appId: number): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getReportList())
.map((res: any) => {
let reports: ReportParametersModel[] = [];
res.forEach((report: ReportParametersModel) => {
let reportModel = new ReportParametersModel(report);
if (this.isReportValid(appId, report)) {
reports.push(reportModel);
}
});
return reports;
}).catch(err => this.handleError(err));
}
/**
* Retrive Report by name
* @param reportName - string - The name of report
* @returns {Observable<any>}
*/
getReportByName(reportName: string): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getReportList())
.map((response: any) => {
return response.find(report => report.name === reportName);
}).catch(err => this.handleError(err));
}
private isReportValid(appId: number, report: ReportParametersModel) {
let isValid: boolean = true;
if (appId && appId !== 0 && report.name.includes('Process definition overview')) {
isValid = false;
}
return isValid;
}
getReportParams(reportId: string): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getReportParams(reportId))
.map((res: any) => {
return new ReportParametersModel(res);
}).catch(err => this.handleError(err));
}
getParamValuesByType(type: string, appId: number, reportId?: string, processDefinitionId?: string) {
if (type === 'status') {
return this.getProcessStatusValues();
} else if (type === 'processDefinition') {
if (appId === null || appId === undefined) {
return this.getProcessDefinitionsValuesNoApp();
} else {
return this.getProcessDefinitionsValues(appId);
}
} else if (type === 'dateInterval') {
return this.getDateIntervalValues();
} else if (type === 'task' && reportId && processDefinitionId) {
return this.getTasksByProcessDefinitionId(reportId, processDefinitionId);
} else {
return Observable.create(observer => {
observer.next(null);
observer.complete();
});
}
}
getProcessStatusValues(): Observable<any> {
let paramOptions: ParameterValueModel[] = [];
paramOptions.push(new ParameterValueModel({id: 'All', name: 'All'}));
paramOptions.push(new ParameterValueModel({id: 'Active', name: 'Active'}));
paramOptions.push(new ParameterValueModel({id: 'Complete', name: 'Complete'}));
return Observable.create(observer => {
observer.next(paramOptions);
observer.complete();
});
}
getDateIntervalValues(): Observable<any> {
let paramOptions: ParameterValueModel[] = [];
paramOptions.push(new ParameterValueModel({id: 'byHour', name: 'By hour'}));
paramOptions.push(new ParameterValueModel({id: 'byDay', name: 'By day'}));
paramOptions.push(new ParameterValueModel({id: 'byWeek', name: 'By week'}));
paramOptions.push(new ParameterValueModel({id: 'byMonth', name: 'By month'}));
paramOptions.push(new ParameterValueModel({id: 'byYear', name: 'By year'}));
return Observable.create(observer => {
observer.next(paramOptions);
observer.complete();
});
}
getMetricValues(): Observable<any> {
let paramOptions: ParameterValueModel[] = [];
paramOptions.push(new ParameterValueModel({id: 'totalCount', name: 'Number of times a step is executed'}));
paramOptions.push(new ParameterValueModel({id: 'totalTime', name: 'Total time spent in a process step'}));
paramOptions.push(new ParameterValueModel({id: 'avgTime', name: 'Average time spent in a process step'}));
return Observable.create(observer => {
observer.next(paramOptions);
observer.complete();
});
}
getProcessDefinitionsValuesNoApp(): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getProcessDefinitions())
.map((res: any) => {
let paramOptions: ParameterValueModel[] = [];
res.forEach((opt) => {
paramOptions.push(new ParameterValueModel(opt));
});
return paramOptions;
}).catch(err => this.handleError(err));
}
getProcessDefinitionsValues(appId: number): Observable<any> {
let options = {'appDefinitionId': appId};
return Observable.fromPromise(this.apiService.getInstance().activiti.processDefinitionsApi.getProcessDefinitions(options))
.map((res: any) => {
let paramOptions: ParameterValueModel[] = [];
res.data.forEach((opt) => {
paramOptions.push(new ParameterValueModel(opt));
});
return paramOptions;
}).catch(err => this.handleError(err));
}
getTasksByProcessDefinitionId(reportId: string, processDefinitionId: string): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getTasksByProcessDefinitionId(reportId, processDefinitionId))
.map((res: any) => {
let paramOptions: ParameterValueModel[] = [];
res.forEach((opt) => {
paramOptions.push(new ParameterValueModel({id: opt, name: opt}));
});
return paramOptions;
}).catch(err => this.handleError(err));
}
getReportsByParams(reportId: number, paramsQuery: any): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getReportsByParams(reportId, paramsQuery))
.map((res: any) => {
let elements: Chart[] = [];
res.elements.forEach((chartData) => {
if (chartData.type === 'pieChart') {
elements.push(new PieChart(chartData));
} else if (chartData.type === 'table') {
elements.push(new TableChart(chartData));
} else if (chartData.type === 'processDefinitionHeatMap') {
elements.push(new HeatMapChart(chartData));
} else if (chartData.type === 'masterDetailTable') {
elements.push(new DetailsTableChart(chartData));
} else if (chartData.type === 'barChart') {
elements.push(new BarChart(chartData));
} else if (chartData.type === 'multiBarChart') {
elements.push(new MultiBarChart(chartData));
}
});
return elements;
}).catch(err => this.handleError(err));
}
createDefaultReports(): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.createDefaultReports())
.map(this.toJson)
.catch(err => this.handleError(err));
}
updateReport(reportId: number, name: string): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.updateReport(reportId, name))
.map((res: any) => {
this.logService.info('upload');
}).catch(err => this.handleError(err));
}
exportReportToCsv(reportId: string, paramsQuery: any): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.exportToCsv(reportId, paramsQuery))
.map((res: any) => {
this.logService.info('export');
return res;
}).catch(err => this.handleError(err));
}
saveReport(reportId: string, paramsQuery: any): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.saveReport(reportId, paramsQuery))
.map(() => {
this.logService.info('save');
}).catch(err => this.handleError(err));
}
deleteReport(reportId: string): Observable<any> {
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.deleteReport(reportId))
.map(() => {
this.logService.info('delete');
}).catch(err => this.handleError(err));
}
private handleError(error: Response) {
this.logService.error(error);
return Observable.throw(error || 'Server error');
}
toJson(res: any) {
return res || {};
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-alfresco-publish-task [data]="data"></diagram-icon-alfresco-publish-task>

View File

@@ -0,0 +1,36 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'adf-diagram-publish-task, diagram-alfresco-publish-task',
templateUrl: './diagram-alfresco-publish-task.component.html'
})
export class DiagramAlfrescoPublishTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-box-publish-task [data]="data"></diagram-icon-box-publish-task>

View File

@@ -0,0 +1,38 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'diagram-box-publish-task',
templateUrl: './diagram-box-publish-task.component.html'
})
export class DiagramBoxPublishTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-business-rule-task [data]="data"></diagram-icon-business-rule-task>

View File

@@ -0,0 +1,34 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'diagram-business-rule-task',
templateUrl: './diagram-business-rule-task.component.html'
})
export class DiagramBusinessRuleTaskComponent {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-camel-task [data]="data"></diagram-icon-camel-task>

View File

@@ -0,0 +1,38 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'diagram-camel-task',
templateUrl: './diagram-camel-task.component.html'
})
export class DiagramCamelTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

View File

@@ -0,0 +1,26 @@
<div [ngSwitch]="data.taskType">
<div *ngSwitchCase="'mail'">
<diagram-send-task [data]="data"></diagram-send-task>
</div>
<div *ngSwitchCase="'camel'">
<diagram-camel-task [data]="data"></diagram-camel-task>
</div>
<div *ngSwitchCase="'mule'">
<diagram-mule-task [data]="data"></diagram-mule-task>
</div>
<div *ngSwitchCase="'alfresco_publish'">
<adf-diagram-publish-task [data]="data"></adf-diagram-publish-task>
</div>
<div *ngSwitchCase="'rest_call'">
<diagram-rest-call-task [data]="data"></diagram-rest-call-task>
</div>
<div *ngSwitchCase="'google_drive_publish'">
<diagram-google-drive-publish-task [data]="data"></diagram-google-drive-publish-task>
</div>
<div *ngSwitchCase="'box_publish'">
<diagram-box-publish-task [data]="data"></diagram-box-publish-task>
</div>
<div *ngSwitchDefault>
<diagram-service-task [data]="data"></diagram-service-task>
</div>
</div>

View File

@@ -0,0 +1,38 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'diagram-container-service-task',
templateUrl: './diagram-container-service-task.component.html'
})
export class DiagramContainerServiceTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-google-drive-publish-task [data]="data"></diagram-icon-google-drive-publish-task>

View File

@@ -0,0 +1,38 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'diagram-google-drive-publish-task',
templateUrl: './diagram-google-drive-publish-task.component.html'
})
export class DiagramGoogleDrivePublishTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-manual-task [data]="data"></diagram-icon-manual-task>

View File

@@ -0,0 +1,35 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'diagram-manual-task',
templateUrl: './diagram-manual-task.component.html'
})
export class DiagramManualTaskComponent {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-mule-task [data]="data"></diagram-icon-mule-task>

View File

@@ -0,0 +1,38 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'diagram-mule-task',
templateUrl: './diagram-mule-task.component.html'
})
export class DiagramMuleTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-receive-task [data]="data"></diagram-icon-receive-task>

View File

@@ -0,0 +1,34 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'diagram-receive-task',
templateUrl: './diagram-receive-task.component.html'
})
export class DiagramReceiveTaskComponent {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-rest-call-task [data]="data"></diagram-icon-rest-call-task>

View File

@@ -0,0 +1,38 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'diagram-rest-call-task',
templateUrl: './diagram-rest-call-task.component.html'
})
export class DiagramRestCallTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-script-task [data]="data"></diagram-icon-script-task>

View File

@@ -0,0 +1,34 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'diagram-script-task',
templateUrl: './diagram-script-task.component.html'
})
export class DiagramScriptTaskComponent {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-send-task [data]="data"></diagram-icon-send-task>

View File

@@ -0,0 +1,38 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'diagram-send-task',
templateUrl: './diagram-send-task.component.html'
})
export class DiagramSendTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-service-task [data]="data"></diagram-icon-service-task>

View File

@@ -0,0 +1,34 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'diagram-service-task',
templateUrl: './diagram-service-task.component.html'
})
export class DiagramServiceTaskComponent {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
}

View File

@@ -0,0 +1,5 @@
<raphael-rect [elementId]="data.id" [leftCorner]="rectLeftCorner" [width]="data.width" [height]="data.height" [radius]="options.radius"
[stroke]="options.stroke" [strokeWidth]="options.strokeWidth"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-rect>
<raphael-multiline-text [text]="data.name" [position]="textPosition" [elementWidth]="data.width"></raphael-multiline-text>
<diagram-tooltip [data]="data"></diagram-tooltip>

View File

@@ -0,0 +1,50 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { DiagramColorService } from '../../services/diagram-color.service';
@Component({
selector: 'diagram-task',
templateUrl: './diagram-task.component.html'
})
export class DiagramTaskComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
rectLeftCorner: any;
textPosition: any;
options: any = {stroke: '', fillColors: '', fillOpacity: '', strokeWidth: '', radius: 4};
constructor(public elementRef: ElementRef,
private diagramColorService: DiagramColorService) {}
ngOnInit() {
this.rectLeftCorner = {x: this.data.x, y: this.data.y};
this.textPosition = {x: this.data.x + ( this.data.width / 2 ), y: this.data.y + ( this.data.height / 2 )};
this.options.fillColors = this.diagramColorService.getFillColour(this.data.id);
this.options.stroke = this.diagramColorService.getBpmnColor(this.data, DiagramColorService.ACTIVITY_STROKE_COLOR);
this.options.strokeWidth = this.diagramColorService.getBpmnStrokeWidth(this.data);
this.options.fillOpacity = this.diagramColorService.getFillOpacity();
}
}

View File

@@ -0,0 +1,2 @@
<diagram-task [data]="data"></diagram-task>
<diagram-icon-user-task [data]="data"></diagram-icon-user-task>

View File

@@ -0,0 +1,34 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'diagram-user-task',
templateUrl: './diagram-user-task.component.html'
})
export class DiagramUserTaskComponent {
@Input()
data: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
}

View File

@@ -0,0 +1,69 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { DiagramAlfrescoPublishTaskComponent } from './diagram-alfresco-publish-task.component';
import { DiagramBoxPublishTaskComponent } from './diagram-box-publish-task.component';
import { DiagramBusinessRuleTaskComponent } from './diagram-business-rule-task.component';
import { DiagramCamelTaskComponent } from './diagram-camel-task.component';
import { DiagramContainerServiceTaskComponent } from './diagram-container-service-task.component';
import { DiagramGoogleDrivePublishTaskComponent } from './diagram-google-drive-publish-task.component';
import { DiagramManualTaskComponent } from './diagram-manual-task.component';
import { DiagramMuleTaskComponent } from './diagram-mule-task.component';
import { DiagramReceiveTaskComponent } from './diagram-receive-task.component';
import { DiagramRestCallTaskComponent } from './diagram-rest-call-task.component';
import { DiagramScriptTaskComponent } from './diagram-script-task.component';
import { DiagramSendTaskComponent } from './diagram-send-task.component';
import { DiagramServiceTaskComponent } from './diagram-service-task.component';
import { DiagramTaskComponent } from './diagram-task.component';
import { DiagramUserTaskComponent } from './diagram-user-task.component';
// primitives
export * from './diagram-container-service-task.component';
export * from './diagram-task.component';
export * from './diagram-service-task.component';
export * from './diagram-send-task.component';
export * from './diagram-user-task.component';
export * from './diagram-manual-task.component';
export * from './diagram-camel-task.component';
export * from './diagram-mule-task.component';
export * from './diagram-alfresco-publish-task.component';
export * from './diagram-rest-call-task.component';
export * from './diagram-google-drive-publish-task.component';
export * from './diagram-box-publish-task.component';
export * from './diagram-receive-task.component';
export * from './diagram-script-task.component';
export * from './diagram-business-rule-task.component';
export const DIAGRAM_ACTIVITIES_DIRECTIVES: any[] = [
DiagramContainerServiceTaskComponent,
DiagramTaskComponent,
DiagramServiceTaskComponent,
DiagramSendTaskComponent,
DiagramUserTaskComponent,
DiagramManualTaskComponent,
DiagramCamelTaskComponent,
DiagramMuleTaskComponent,
DiagramAlfrescoPublishTaskComponent,
DiagramRestCallTaskComponent,
DiagramGoogleDrivePublishTaskComponent,
DiagramBoxPublishTaskComponent,
DiagramReceiveTaskComponent,
DiagramScriptTaskComponent,
DiagramBusinessRuleTaskComponent
];

View File

@@ -0,0 +1,6 @@
<raphael-circle [center]="center" [radius]="circleRadiusInner" [strokeWidth]="options.strokeWidth" [stroke]="options.stroke"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-circle>
<raphael-circle [elementId]="data.id" [center]="center" [radius]="circleRadiusOuter" [strokeWidth]="options.strokeWidth" [stroke]="options.stroke"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-circle>
<diagram-container-icon-event [data]="data" [type]="data.eventDefinition.type" [fillColor]="signalFillColor"></diagram-container-icon-event>
<diagram-tooltip [data]="data"></diagram-tooltip>

View File

@@ -0,0 +1,58 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { DiagramColorService } from '../../services/diagram-color.service';
@Component({
selector: 'diagram-boundary-event',
templateUrl: './diagram-boundary-event.component.html'
})
export class DiagramBoundaryEventComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
center: any = {};
options: any = {stroke: '', fillColors: '', fillOpacity: '', strokeWidth: 1};
signalFillColor: string;
circleRadiusInner: number;
circleRadiusOuter: number;
constructor(public elementRef: ElementRef,
private diagramColorService: DiagramColorService) {}
ngOnInit() {
this.center.x = this.data.x + (this.data.width / 2);
this.center.y = this.data.y + (this.data.height / 2);
this.circleRadiusInner = 12;
this.circleRadiusOuter = 15;
this.options.stroke = this.diagramColorService.getBpmnColor(this.data, DiagramColorService.MAIN_STROKE_COLOR);
this.options.fillColors = this.diagramColorService.getFillColour(this.data.id);
this.options.fillOpacity = this.diagramColorService.getFillOpacity();
this.signalFillColor = 'none';
}
}

View File

@@ -0,0 +1,7 @@
<raphael-circle [center]="center" [radius]="circleRadiusInner" [strokeWidth]="options.strokeWidth" [stroke]="options.stroke"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-circle>
<raphael-circle [elementId]="data.id" [center]="center" [radius]="circleRadiusOuter" [strokeWidth]="options.strokeWidth" [stroke]="options.stroke"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-circle>
<diagram-container-icon-event [data]="data" [type]="data.eventDefinition && data.eventDefinition.type"
[fillColor]="signalFillColor"></diagram-container-icon-event>
<diagram-tooltip [data]="data"></diagram-tooltip>

View File

@@ -0,0 +1,59 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { DiagramColorService } from '../../services/diagram-color.service';
@Component({
selector: 'diagram-throw-event',
templateUrl: './diagram-throw-event.component.html'
})
export class DiagramThrowEventComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
center: any = {};
options: any = {stroke: '', fillColors: '', fillOpacity: '', strokeWidth: 1};
signalFillColor: string;
circleRadiusInner: number;
circleRadiusOuter: number;
constructor(public elementRef: ElementRef,
private diagramColorService: DiagramColorService) {
}
ngOnInit() {
this.center.x = this.data.x + (this.data.width / 2);
this.center.y = this.data.y + (this.data.height / 2);
this.circleRadiusInner = 12;
this.circleRadiusOuter = 15;
this.options.stroke = this.diagramColorService.getBpmnColor(this.data, DiagramColorService.MAIN_STROKE_COLOR);
this.options.fillColors = this.diagramColorService.getFillColour(this.data.id);
this.options.fillOpacity = this.diagramColorService.getFillOpacity();
this.signalFillColor = 'black';
}
}

View File

@@ -0,0 +1,30 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { DiagramBoundaryEventComponent } from './diagram-boundary-event.component';
import { DiagramThrowEventComponent } from './diagram-throw-event.component';
// primitives
export * from './diagram-boundary-event.component';
export * from './diagram-throw-event.component';
export const DIAGRAM_BOUNDARY_EVENTS_DIRECTIVES: any[] = [
DiagramBoundaryEventComponent,
DiagramThrowEventComponent
];

View File

@@ -0,0 +1,2 @@
<raphael-flow-arrow [flow]="flow"></raphael-flow-arrow>
<diagram-tooltip [data]="flow"></diagram-tooltip>

View File

@@ -0,0 +1,36 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'adf-diagram-sequence-flow, diagram-sequence-flow',
templateUrl: './diagram-sequence-flow.component.html'
})
export class DiagramSequenceFlowComponent implements OnInit {
@Input()
flow: any;
@Output()
error = new EventEmitter();
constructor(public elementRef: ElementRef) {}
ngOnInit() {
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,703 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
import * as boundaryEventMock from '../../mock/diagram/diagramBoundary.mock';
import { DiagramComponent } from './index';
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
declare let jasmine: any;
describe('Diagrams boundary', () => {
let component: any;
let fixture: ComponentFixture<DiagramComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
...DIAGRAM_DIRECTIVES,
...RAPHAEL_DIRECTIVES
],
providers: [
...DIAGRAM_PROVIDERS,
...RAPHAEL_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DiagramComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
component.processInstanceId = '38399';
component.processDefinitionId = 'fakeprocess:24:38399';
component.metricPercentages = { startEvent: 0 };
});
afterEach(() => {
component.success.unsubscribe();
jasmine.Ajax.uninstall();
});
let ajaxReply = (resp: any) => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: resp
});
};
describe('Diagrams component Boundary events with process instance id: ', () => {
it('Should render the Boundary time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryTimeEvent] };
ajaxReply(resp);
}));
it('Should render the Active Boundary time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryTimeEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Boundary time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryTimeEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Boundary error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryErrorEvent] };
ajaxReply(resp);
}));
it('Should render the Active Boundary error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryErrorEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Boundary error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryErrorEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Boundary signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundarySignalEvent] };
ajaxReply(resp);
}));
it('Should render the Active Boundary signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundarySignalEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Boundary signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundarySignalEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Boundary signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Active Boundary signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryMessageEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Boundary signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryMessageEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Boundary signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Active Boundary signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryMessageEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Boundary signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryMessageEventCompleted] };
ajaxReply(resp);
}));
});
describe('Diagrams component Boundary events: ', () => {
it('Should render the Boundary time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryTimeEvent] };
ajaxReply(resp);
}));
it('Should render the Boundary error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryErrorEvent] };
ajaxReply(resp);
}));
it('Should render the Boundary signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundarySignalEvent] };
ajaxReply(resp);
}));
it('Should render the Boundary signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Boundary signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-boundary-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [boundaryEventMock.boundaryMessageEvent] };
ajaxReply(resp);
}));
});
});

View File

@@ -0,0 +1,579 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
import * as intermediateCatchingMock from '../../mock/diagram/diagramIntermediate.mock';
import { DiagramComponent } from './index';
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
declare let jasmine: any;
describe('Diagrams Catching', () => {
let component: any;
let fixture: ComponentFixture<DiagramComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
...DIAGRAM_DIRECTIVES,
...RAPHAEL_DIRECTIVES
],
providers: [
...DIAGRAM_PROVIDERS,
...RAPHAEL_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DiagramComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
component.processInstanceId = '38399';
component.processDefinitionId = 'fakeprocess:24:38399';
component.metricPercentages = { startEvent: 0 };
});
afterEach(() => {
component.success.unsubscribe();
jasmine.Ajax.uninstall();
});
let ajaxReply = (resp: any) => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: resp
});
};
describe('Diagrams component Intermediate Catching events: ', () => {
it('Should render the Intermediate catching time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEvent] };
ajaxReply(resp);
}));
it('Should render the Intermediate catching error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEvent] };
ajaxReply(resp);
}));
it('Should render the Intermediate catching signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEvent] };
ajaxReply(resp);
}));
it('Should render the Intermediate catching signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEvent] };
ajaxReply(resp);
}));
});
describe('Diagrams component Intermediate Catching events with process instance id: ', () => {
it('Should render the Intermediate catching time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEvent] };
ajaxReply(resp);
}));
it('Should render the Active Intermediate catching time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Intermediate catching time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Intermediate catching error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEvent] };
ajaxReply(resp);
}));
it('Should render the Active Intermediate catching error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Intermediate catching error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Intermediate catching signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEvent] };
ajaxReply(resp);
}));
it('Should render the Intermediate Active catching signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Intermediate catching signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Intermediate catching signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Active Intermediate catching signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Intermediate catching signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-intermediate-catching-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEventCompleted] };
ajaxReply(resp);
}));
});
});

View File

@@ -0,0 +1,3 @@
.diagram {
border: 1px solid lightgray; overflow:auto
}

View File

@@ -0,0 +1,643 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
import * as diagramsEventsMock from '../../mock/diagram/diagramEvents.mock';
import { DiagramComponent } from './index';
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
declare let jasmine: any;
describe('Diagrams events', () => {
let component: any;
let fixture: ComponentFixture<DiagramComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
...DIAGRAM_DIRECTIVES,
...RAPHAEL_DIRECTIVES
],
providers: [
...DIAGRAM_PROVIDERS,
...RAPHAEL_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DiagramComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
component.processInstanceId = '38399';
component.processDefinitionId = 'fakeprocess:24:38399';
component.metricPercentages = { startEvent: 0 };
});
afterEach(() => {
component.success.unsubscribe();
jasmine.Ajax.uninstall();
});
let ajaxReply = (resp: any) => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: resp
});
};
describe('Diagrams component Events: ', () => {
it('Should render the Start Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startEvent] };
ajaxReply(resp);
}));
it('Should render the Start Timer Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-timer > raphael-icon-timer');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startTimeEvent] };
ajaxReply(resp);
}));
it('Should render the Start Signal Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-signal > raphael-icon-signal');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startSignalEvent] };
ajaxReply(resp);
}));
it('Should render the Start Message Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-message > raphael-icon-message');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Start Error Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startErrorEvent] };
ajaxReply(resp);
}));
it('Should render the End Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.endEvent] };
ajaxReply(resp);
}));
it('Should render the End Error Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.endErrorEvent] };
ajaxReply(resp);
}));
});
describe('Diagrams component Events with process instance id: ', () => {
it('Should render the Start Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startEvent] };
ajaxReply(resp);
}));
it('Should render the Active Start Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]');
expect(event).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Start Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(event).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Start Timer Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-timer > raphael-icon-timer');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startTimeEvent] };
ajaxReply(resp);
}));
it('Should render the Active Start Timer Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-timer > raphael-icon-timer');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startTimeEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Start Timer Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-timer > raphael-icon-timer');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startTimeEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Start Signal Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-signal > raphael-icon-signal');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startSignalEvent] };
ajaxReply(resp);
}));
it('Should render the Active Start Signal Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-signal > raphael-icon-signal');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startSignalEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Start Signal Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-signal > raphael-icon-signal');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startSignalEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Start Message Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-message > raphael-icon-message');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Active Start Message Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-message > raphael-icon-message');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startMessageEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Start Message Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-message > raphael-icon-message');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startMessageEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Start Error Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startErrorEvent] };
ajaxReply(resp);
}));
it('Should render the Active Start Error Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startErrorEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Start Error Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.startErrorEventCompleted] };
ajaxReply(resp);
}));
it('Should render the End Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.endEvent] };
ajaxReply(resp);
}));
it('Should render the Active End Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]');
expect(event).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.endEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed End Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(event).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.endEventCompleted] };
ajaxReply(resp);
}));
it('Should render the End Error Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.endErrorEvent] };
ajaxReply(resp);
}));
it('Should render the Active End Error Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.endErrorEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed End Error Event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).toBeDefined();
let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(event).not.toBeNull();
let iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' +
' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error');
expect(iconEvent).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsEventsMock.endErrorEventCompleted] };
ajaxReply(resp);
}));
});
});

View File

@@ -0,0 +1,119 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
import * as flowsMock from '../../mock/diagram/diagramFlows.mock';
import { DiagramComponent } from './index';
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
declare let jasmine: any;
describe('Diagrams flows', () => {
let component: any;
let fixture: ComponentFixture<DiagramComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
...DIAGRAM_DIRECTIVES,
...RAPHAEL_DIRECTIVES
],
providers: [
...DIAGRAM_PROVIDERS,
...RAPHAEL_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DiagramComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
component.processInstanceId = '38399';
component.processDefinitionId = 'fakeprocess:24:38399';
component.metricPercentages = { startEvent: 0 };
});
afterEach(() => {
component.success.unsubscribe();
jasmine.Ajax.uninstall();
});
let ajaxReply = (resp: any) => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: resp
});
};
describe('Diagrams component Flows with process instance id: ', () => {
it('Should render the flow', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-sequence-flow > raphael-flow-arrow');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.flows[0].id);
expect(tooltip.textContent).toContain(res.flows[0].type);
});
});
component.ngOnChanges();
let resp = { flows: [flowsMock.flow] };
ajaxReply(resp);
}));
});
describe('Diagrams component Flows: ', () => {
it('Should render the flow', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-sequence-flow > raphael-flow-arrow');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.flows[0].id);
expect(tooltip.textContent).toContain(res.flows[0].type);
});
});
component.ngOnChanges();
let resp = { flows: [flowsMock.flow] };
ajaxReply(resp);
}));
});
});

View File

@@ -0,0 +1,459 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
import * as diagramsGatewaysMock from '../../mock/diagram/diagramGateways.mock';
import { DiagramComponent } from './index';
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
declare let jasmine: any;
describe('Diagrams gateways', () => {
let component: any;
let fixture: ComponentFixture<DiagramComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
...DIAGRAM_DIRECTIVES,
...RAPHAEL_DIRECTIVES
],
providers: [
...DIAGRAM_PROVIDERS,
...RAPHAEL_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DiagramComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
component.processInstanceId = '38399';
component.processDefinitionId = 'fakeprocess:24:38399';
component.metricPercentages = { startEvent: 0 };
});
afterEach(() => {
component.success.unsubscribe();
jasmine.Ajax.uninstall();
});
let ajaxReply = (resp: any) => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: resp
});
};
describe('Diagrams component Gateways: ', () => {
it('Should render the Exclusive Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.exclusiveGatway] };
ajaxReply(resp);
}));
it('Should render the Inclusive Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.inclusiveGatway] };
ajaxReply(resp);
}));
it('Should render the Parallel Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.parallelGatway] };
ajaxReply(resp);
}));
it('Should render the Event Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-event-gateway');
expect(shape1).not.toBeNull();
expect(shape1.children.length).toBe(4);
let outerCircle = shape1.children[1];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape1.children[2];
expect(innerCircle.localName).toEqual('raphael-circle');
let shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon');
expect(shape2).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.eventGatway] };
ajaxReply(resp);
}));
});
describe('Diagrams component Gateways with process instance id: ', () => {
it('Should render the Exclusive Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.exclusiveGatway] };
ajaxReply(resp);
}));
it('Should render the Active Exclusive Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.exclusiveGatwayActive] };
ajaxReply(resp);
}));
it('Should render the Completed Exclusive Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.exclusiveGatwayCompleted] };
ajaxReply(resp);
}));
it('Should render the Inclusive Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.inclusiveGatway] };
ajaxReply(resp);
}));
it('Should render the Active Inclusive Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.inclusiveGatwayActive] };
ajaxReply(resp);
}));
it('Should render the Completed Inclusive Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.inclusiveGatwayCompleted] };
ajaxReply(resp);
}));
it('Should render the Parallel Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.parallelGatway] };
ajaxReply(resp);
}));
it('Should render the Active Parallel Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.parallelGatwayActive] };
ajaxReply(resp);
}));
it('Should render the Completed Parallel Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus');
expect(shape1).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.parallelGatwayCompleted] };
ajaxReply(resp);
}));
it('Should render the Event Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-event-gateway');
expect(shape1).not.toBeNull();
expect(shape1.children.length).toBe(4);
let outerCircle = shape1.children[1];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape1.children[2];
expect(innerCircle.localName).toEqual('raphael-circle');
let shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon');
expect(shape2).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.eventGatway] };
ajaxReply(resp);
}));
it('Should render the Active Event Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-event-gateway');
expect(shape1).not.toBeNull();
expect(shape1.children.length).toBe(4);
let outerCircle = shape1.children[1];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape1.children[2];
expect(innerCircle.localName).toEqual('raphael-circle');
let shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon');
expect(shape2).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.eventGatwayActive] };
ajaxReply(resp);
}));
it('Should render the Completed Event Gateway', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]');
expect(shape).not.toBeNull();
let shape1: any = element.querySelector('diagram-event-gateway');
expect(shape1).not.toBeNull();
expect(shape1.children.length).toBe(4);
let outerCircle = shape1.children[1];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape1.children[2];
expect(innerCircle.localName).toEqual('raphael-circle');
let shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon');
expect(shape2).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [diagramsGatewaysMock.eventGatwayCompleted] };
ajaxReply(resp);
}));
});
});

View File

@@ -0,0 +1,67 @@
<div *ngIf="diagram" class="diagram">
<div *ngFor="let element of diagram.elements">
<div [ngSwitch]="element.type">
<div *ngSwitchCase="'StartEvent'">
<diagram-start-event [data]="element"></diagram-start-event>
</div>
<div *ngSwitchCase="'ExclusiveGateway'">
<diagram-exclusive-gateway [data]="element"></diagram-exclusive-gateway>
</div>
<div *ngSwitchCase="'InclusiveGateway'">
<diagram-inclusive-gateway [data]="element"></diagram-inclusive-gateway>
</div>
<div *ngSwitchCase="'EventGateway'">
<diagram-event-gateway [data]="element"></diagram-event-gateway>
</div>
<div *ngSwitchCase="'ParallelGateway'">
<diagram-parallel-gateway [data]="element"></diagram-parallel-gateway>
</div>
<div *ngSwitchCase="'EndEvent'">
<diagram-end-event [data]="element"></diagram-end-event>
</div>
<div *ngSwitchCase="'UserTask'">
<diagram-user-task [data]="element"></diagram-user-task>
</div>
<div *ngSwitchCase="'ManualTask'">
<diagram-manual-task [data]="element"></diagram-manual-task>
</div>
<div *ngSwitchCase="'ServiceTask'">
<diagram-container-service-task [data]="element"></diagram-container-service-task>
</div>
<div *ngSwitchCase="'ReceiveTask'">
<diagram-receive-task [data]="element"></diagram-receive-task>
</div>
<div *ngSwitchCase="'ScriptTask'">
<diagram-script-task [data]="element"></diagram-script-task>
</div>
<div *ngSwitchCase="'BusinessRuleTask'">
<diagram-business-rule-task [data]="element"></diagram-business-rule-task>
</div>
<div *ngSwitchCase="'BoundaryEvent'">
<diagram-boundary-event [data]="element"></diagram-boundary-event>
</div>
<div *ngSwitchCase="'ThrowEvent'">
<diagram-throw-event [data]="element"></diagram-throw-event>
</div>
<div *ngSwitchCase="'IntermediateCatchEvent'">
<diagram-intermediate-catching-event [data]="element"></diagram-intermediate-catching-event>
</div>
<div *ngSwitchCase="'SubProcess'">
<diagram-subprocess [data]="element"></diagram-subprocess>
</div>
<div *ngSwitchCase="'EventSubProcess'">
<diagram-event-subprocess [data]="element"></diagram-event-subprocess>
</div>
</div>
</div>
<div *ngFor="let flow of diagram.flows">
<div [ngSwitch]="flow.type">
<div *ngSwitchCase="'sequenceFlow'">
<diagram-sequence-flow [flow]="flow"></diagram-sequence-flow>
</div>
</div>
</div>
<div *ngIf="diagram.pools">
<diagram-pools [pools]="diagram.pools"></diagram-pools>
</div>
</div>

View File

@@ -0,0 +1,227 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
import * as structuralMock from '../../mock/diagram/diagramStructural.mock';
import { DiagramComponent } from './index';
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
declare let jasmine: any;
describe('Diagrams structural', () => {
let component: any;
let fixture: ComponentFixture<DiagramComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
...DIAGRAM_DIRECTIVES,
...RAPHAEL_DIRECTIVES
],
providers: [
...DIAGRAM_PROVIDERS,
...RAPHAEL_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DiagramComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
component.processInstanceId = '38399';
component.processDefinitionId = 'fakeprocess:24:38399';
component.metricPercentages = { startEvent: 0 };
});
afterEach(() => {
component.success.unsubscribe();
jasmine.Ajax.uninstall();
});
let ajaxReply = (resp: any) => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: resp
});
};
describe('Diagrams component Structural: ', () => {
it('Should render the Subprocess', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-subprocess > raphael-rect');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [structuralMock.subProcess] };
ajaxReply(resp);
}));
it('Should render the Event Subprocess', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-event-subprocess > raphael-rect');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [structuralMock.eventSubProcess] };
ajaxReply(resp);
}));
});
describe('Diagrams component Structural with process instance id: ', () => {
it('Should render the Subprocess', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-subprocess > raphael-rect');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [structuralMock.subProcess] };
ajaxReply(resp);
}));
it('Should render the Active Subprocess', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-subprocess > raphael-rect[ng-reflect-stroke="#017501"]');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [structuralMock.subProcessActive] };
ajaxReply(resp);
}));
it('Should render the Completed Subprocess', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-subprocess > raphael-rect[ng-reflect-stroke="#2632aa"]');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [structuralMock.subProcessCompleted] };
ajaxReply(resp);
}));
it('Should render the Event Subprocess', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-event-subprocess > raphael-rect');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [structuralMock.eventSubProcess] };
ajaxReply(resp);
}));
it('Should render the Active Event Subprocess', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-event-subprocess > raphael-rect[ng-reflect-stroke="#017501"]');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [structuralMock.eventSubProcessActive] };
ajaxReply(resp);
}));
it('Should render the Completed Event Subprocess', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-event-subprocess > raphael-rect[ng-reflect-stroke="#2632aa"]');
expect(shape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [structuralMock.eventSubProcessCompleted] };
ajaxReply(resp);
}));
});
});

View File

@@ -0,0 +1,161 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
import * as swimLanesMock from '../../mock/diagram/diagramSwimlanes.mock';
import { DiagramComponent } from './index';
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
declare let jasmine: any;
describe('Diagrams swim', () => {
let component: any;
let fixture: ComponentFixture<DiagramComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
...DIAGRAM_DIRECTIVES,
...RAPHAEL_DIRECTIVES
],
providers: [
...DIAGRAM_PROVIDERS,
...RAPHAEL_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DiagramComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
component.processInstanceId = '38399';
component.processDefinitionId = 'fakeprocess:24:38399';
component.metricPercentages = { startEvent: 0 };
});
afterEach(() => {
component.success.unsubscribe();
jasmine.Ajax.uninstall();
});
let ajaxReply = (resp: any) => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: resp
});
};
describe('Diagrams component Swim lane: ', () => {
it('Should render the Pool', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-pool > raphael-rect');
expect(shape).not.toBeNull();
let shapeText: any = element.querySelector('diagram-pool > raphael-text');
expect(shapeText).not.toBeNull();
expect(shapeText.attributes[2].value).toEqual('Activiti');
});
});
component.ngOnChanges();
let resp = { pools: [swimLanesMock.pool] };
ajaxReply(resp);
}));
it('Should render the Pool with Lanes', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shapeLane: any = element.querySelector('diagram-lanes > div > div > diagram-lane');
expect(shapeLane).not.toBeNull();
let shapeRect: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-rect');
expect(shapeRect).not.toBeNull();
let shapeText: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-text');
expect(shapeText).not.toBeNull();
expect(shapeText.attributes[2].value).toEqual('Beckend');
});
});
component.ngOnChanges();
let resp = { pools: [swimLanesMock.poolLanes] };
ajaxReply(resp);
}));
});
describe('Diagrams component Swim lane with process instance id: ', () => {
it('Should render the Pool', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-pool > raphael-rect');
expect(shape).not.toBeNull();
let shapeText: any = element.querySelector('diagram-pool > raphael-text');
expect(shapeText).not.toBeNull();
expect(shapeText.attributes[2].value).toEqual('Activiti');
});
});
component.ngOnChanges();
let resp = { pools: [swimLanesMock.pool] };
ajaxReply(resp);
}));
it('Should render the Pool with Lanes', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shapeLane: any = element.querySelector('diagram-lanes > div > div > diagram-lane');
expect(shapeLane).not.toBeNull();
let shapeRect: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-rect');
expect(shapeRect).not.toBeNull();
let shapeText: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-text');
expect(shapeText).not.toBeNull();
expect(shapeText.attributes[2].value).toEqual('Beckend');
});
});
component.ngOnChanges();
let resp = { pools: [swimLanesMock.poolLanes] };
ajaxReply(resp);
}));
});
});

View File

@@ -0,0 +1,687 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebugElement } from '@angular/core';
import * as throwEventMock from '../../mock/diagram/diagramThrow.mock';
import { DiagramComponent } from './index';
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
declare let jasmine: any;
describe('Diagrams throw', () => {
let component: any;
let fixture: ComponentFixture<DiagramComponent>;
let debug: DebugElement;
let element: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
...DIAGRAM_DIRECTIVES,
...RAPHAEL_DIRECTIVES
],
providers: [
...DIAGRAM_PROVIDERS,
...RAPHAEL_PROVIDERS
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DiagramComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
element = fixture.nativeElement;
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
component.processInstanceId = '38399';
component.processDefinitionId = 'fakeprocess:24:38399';
component.metricPercentages = { startEvent: 0 };
});
afterEach(() => {
component.success.unsubscribe();
jasmine.Ajax.uninstall();
});
let ajaxReply = (resp: any) => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: resp
});
};
describe('Diagrams component Throw events with process instance id: ', () => {
it('Should render the Throw time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwTimeEvent] };
ajaxReply(resp);
}));
it('Should render the Active Throw time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwTimeEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Throw time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwTimeEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Throw error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwErrorEvent] };
ajaxReply(resp);
}));
it('Should render the Active Throw error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwErrorEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Throw error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwErrorEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Throw signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwSignalEvent] };
ajaxReply(resp);
}));
it('Should render the Active Throw signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwSignalEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Throw signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwSignalEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Throw signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Active Throw signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwMessageEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Throw signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwMessageEventCompleted] };
ajaxReply(resp);
}));
it('Should render the Throw signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Active Throw signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwMessageEventActive] };
ajaxReply(resp);
}));
it('Should render the Completed Throw signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]');
expect(coloredShape).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwMessageEventCompleted] };
ajaxReply(resp);
}));
});
describe('Diagrams component Throw events: ', () => {
it('Should render the Throw time event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-timer');
expect(iconShape).not.toBeNull();
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwTimeEvent] };
ajaxReply(resp);
}));
it('Should render the Throw error event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-error');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwErrorEvent] };
ajaxReply(resp);
}));
it('Should render the Throw signal event', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-signal');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwSignalEvent] };
ajaxReply(resp);
}));
it('Should render the Throw signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwMessageEvent] };
ajaxReply(resp);
}));
it('Should render the Throw signal message', async(() => {
component.success.subscribe((res) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(res).not.toBeNull();
let shape: any = element.querySelector('diagram-throw-event');
expect(shape).not.toBeNull();
expect(shape.children.length).toBe(4);
let outerCircle = shape.children[0];
expect(outerCircle.localName).toEqual('raphael-circle');
let innerCircle = shape.children[1];
expect(innerCircle.localName).toEqual('raphael-circle');
let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' +
' div > div > diagram-icon-message');
expect(iconShape).not.toBeNull();
let tooltip: any = element.querySelector('diagram-tooltip > div');
expect(tooltip.textContent).toContain(res.elements[0].id);
expect(tooltip.textContent).toContain(res.elements[0].type);
});
});
component.ngOnChanges();
let resp = { elements: [throwEventMock.throwMessageEvent] };
ajaxReply(resp);
}));
});
});

View File

@@ -0,0 +1,123 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { DiagramElementModel, DiagramModel } from '../models/diagram.model';
import { DiagramColorService } from '../services/diagram-color.service';
import { DiagramsService } from '../services/diagrams.service';
import { RaphaelService } from './raphael/raphael.service';
@Component({
selector: 'adf-diagram',
styleUrls: ['./diagram.component.css'],
templateUrl: './diagram.component.html'
})
export class DiagramComponent implements OnChanges {
@Input()
processDefinitionId: any;
@Input()
processInstanceId: any;
@Input()
metricPercentages: any;
@Input()
metricColor: any;
@Input()
metricType: string = '';
@Input()
width: number = 1000;
@Input()
height: number = 500;
@Output()
success = new EventEmitter();
@Output()
error = new EventEmitter();
PADDING_WIDTH: number = 60;
PADDING_HEIGHT: number = 60;
diagram: DiagramModel;
constructor(private diagramColorService: DiagramColorService,
private raphaelService: RaphaelService,
private diagramsService: DiagramsService) {
}
ngOnChanges(changes: SimpleChanges) {
this.reset();
this.diagramColorService.setTotalColors(this.metricColor);
if (this.processDefinitionId) {
this.getProcessDefinitionModel(this.processDefinitionId);
} else {
this.getRunningProcessDefinitionModel(this.processInstanceId);
}
}
getRunningProcessDefinitionModel(processInstanceId: string) {
this.diagramsService.getRunningProcessDefinitionModel(processInstanceId).subscribe(
(res: any) => {
this.diagram = new DiagramModel(res);
this.raphaelService.setting(this.diagram.diagramWidth + this.PADDING_WIDTH,
this.diagram.diagramHeight + this.PADDING_HEIGHT);
this.setMetricValueToDiagramElement(this.diagram, this.metricPercentages, this.metricType);
this.success.emit(res);
},
(err: any) => {
this.error.emit(err);
}
);
}
getProcessDefinitionModel(processDefinitionId: string) {
this.diagramsService.getProcessDefinitionModel(processDefinitionId).subscribe(
(res: any) => {
this.diagram = new DiagramModel(res);
this.raphaelService.setting(this.diagram.diagramWidth + this.PADDING_WIDTH,
this.diagram.diagramHeight + this.PADDING_HEIGHT);
this.setMetricValueToDiagramElement(this.diagram, this.metricPercentages, this.metricType);
this.success.emit(res);
},
(err: any) => {
this.error.emit(err);
}
);
}
setMetricValueToDiagramElement(diagram: DiagramModel, metrics: any, metricType: string) {
for (let key in metrics) {
if (metrics.hasOwnProperty(key)) {
let foundElement: DiagramElementModel = diagram.elements.find(
(element: DiagramElementModel) => element.id === key);
if (foundElement) {
foundElement.value = metrics[key];
foundElement.dataType = metricType;
}
}
}
}
reset() {
this.raphaelService.reset();
}
}

View File

@@ -0,0 +1 @@
<diagram-event [data]="data" [options]="options" [iconFillColor]="iconFillColor"></diagram-event>

View File

@@ -0,0 +1,50 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { DiagramColorService } from '../../services/diagram-color.service';
@Component({
selector: 'diagram-end-event',
templateUrl: './diagram-end-event.component.html'
})
export class DiagramEndEventComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
options: any = {stroke: '', fillColors: '', fillOpacity: '', strokeWidth: '', radius: ''};
iconFillColor: any;
constructor(public elementRef: ElementRef,
private diagramColorService: DiagramColorService) {}
ngOnInit() {
this.options.radius = 14;
this.options.strokeWidth = 4;
this.options.stroke = this.diagramColorService.getBpmnColor(this.data, DiagramColorService.MAIN_STROKE_COLOR);
this.options.fillColors = this.diagramColorService.getFillColour(this.data.id);
this.options.fillOpacity = this.diagramColorService.getFillOpacity();
this.iconFillColor = 'black';
}
}

View File

@@ -0,0 +1,5 @@
<raphael-circle [elementId]="data.id" [center]="center" [radius]="options.radius" [strokeWidth]="options.strokeWidth" [stroke]="options.stroke"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-circle>
<diagram-container-icon-event [data]="data" [type]="data.eventDefinition && data.eventDefinition.type"
[fillColor]="iconFillColor"></diagram-container-icon-event>
<diagram-tooltip [data]="data"></diagram-tooltip>

View File

@@ -0,0 +1,48 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'diagram-event',
templateUrl: './diagram-event.component.html'
})
export class DiagramEventComponent implements OnInit {
@Input()
data: any;
@Input()
options: any = {stroke: '', fillColors: '', fillOpacity: '', strokeWidth: '', radius: ''};
@Input()
iconFillColor: any;
@Output()
error = new EventEmitter();
center: any = {};
constructor(public elementRef: ElementRef) {}
ngOnInit() {
this.center.x = this.data.x + (this.data.width / 2);
this.center.y = this.data.y + (this.data.height / 2);
}
}

View File

@@ -0,0 +1 @@
<diagram-event [data]="data" [options]="options" [iconFillColor]="iconFillColor"></diagram-event>

View File

@@ -0,0 +1,50 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { DiagramColorService } from '../../services/diagram-color.service';
@Component({
selector: 'diagram-start-event',
templateUrl: './diagram-start-event.component.html'
})
export class DiagramStartEventComponent implements OnInit {
@Input()
data: any;
@Output()
error = new EventEmitter();
options: any = {stroke: '', fillColors: '', fillOpacity: '', strokeWidth: '', radius: ''};
iconFillColor: any;
constructor(public elementRef: ElementRef,
private diagramColorService: DiagramColorService) {}
ngOnInit() {
this.options.radius = 15;
this.options.strokeWidth = 1;
this.options.stroke = this.diagramColorService.getBpmnColor(this.data, DiagramColorService.MAIN_STROKE_COLOR);
this.options.fillColors = this.diagramColorService.getFillColour(this.data.id);
this.options.fillOpacity = this.diagramColorService.getFillOpacity();
this.iconFillColor = 'none';
}
}

View File

@@ -0,0 +1,33 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* tslint:disable:component-selector */
import { DiagramEndEventComponent } from './diagram-end-event.component';
import { DiagramEventComponent } from './diagram-event.component';
import { DiagramStartEventComponent } from './diagram-start-event.component';
// primitives
export * from './diagram-event.component';
export * from './diagram-start-event.component';
export * from './diagram-end-event.component';
export const DIAGRAM_EVENTS_DIRECTIVES: any[] = [
DiagramEventComponent,
DiagramStartEventComponent,
DiagramEndEventComponent
];

View File

@@ -0,0 +1,7 @@
<diagram-gateway [data]="data"></diagram-gateway>
<raphael-circle [center]="center" [radius]="circleRadiusInner" [strokeWidth]="options.strokeWidth" [stroke]="options.stroke"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-circle>
<raphael-circle [center]="center" [radius]="circleRadiusOuter" [strokeWidth]="options.strokeWidth" [stroke]="options.stroke"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-circle>
<raphael-pentagon [center]="centerPentagon" [strokeWidth]="pentaStrokeWidth" [stroke]="options.stroke"
[fillColors]="options.fillColors" [fillOpacity]="options.fillOpacity"></raphael-pentagon>

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