mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-19 17:14:57 +00:00
Merge pull request #871 from Alfresco/dev-mvitale-799
Create report list and report charts
This commit is contained in:
commit
d85baaf8da
@ -31,6 +31,7 @@ import { ActivitiFormModule } from 'ng2-activiti-form';
|
|||||||
import { ActivitiTaskListModule } from 'ng2-activiti-tasklist';
|
import { ActivitiTaskListModule } from 'ng2-activiti-tasklist';
|
||||||
import { ActivitiProcessListModule } from 'ng2-activiti-processlist';
|
import { ActivitiProcessListModule } from 'ng2-activiti-processlist';
|
||||||
import { UserInfoComponentModule } from 'ng2-alfresco-userinfo';
|
import { UserInfoComponentModule } from 'ng2-alfresco-userinfo';
|
||||||
|
import { AnalyticsModule } from 'ng2-activiti-analytics';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { routing } from './app.routes';
|
import { routing } from './app.routes';
|
||||||
@ -65,7 +66,8 @@ import {
|
|||||||
ActivitiFormModule.forRoot(),
|
ActivitiFormModule.forRoot(),
|
||||||
ActivitiTaskListModule.forRoot(),
|
ActivitiTaskListModule.forRoot(),
|
||||||
ActivitiProcessListModule.forRoot(),
|
ActivitiProcessListModule.forRoot(),
|
||||||
UserInfoComponentModule.forRoot()
|
UserInfoComponentModule.forRoot(),
|
||||||
|
AnalyticsModule.forRoot()
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
@ -63,7 +63,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="mdl-layout__tab-panel" id="report">
|
<section class="mdl-layout__tab-panel" id="report">
|
||||||
<div class="page-content"><!-- Your content goes here --></div>
|
<div class="page-content">
|
||||||
|
<div class="mdl-grid">
|
||||||
|
<div class="mdl-cell mdl-cell--4-col task-column mdl-shadow--2dp">
|
||||||
|
<analytics-report-list (reportClick)="onReportClick($event)"></analytics-report-list>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-cell mdl-cell--8-col task-column mdl-shadow--2dp">
|
||||||
|
<activiti-analytics *ngIf="report" [reportId]="report.id"></activiti-analytics>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
@ -79,6 +79,7 @@ export class ActivitiDemoComponent implements AfterViewChecked {
|
|||||||
processSchemaColumns: any [] = [];
|
processSchemaColumns: any [] = [];
|
||||||
|
|
||||||
taskFilter: any;
|
taskFilter: any;
|
||||||
|
report: any;
|
||||||
processFilter: any;
|
processFilter: any;
|
||||||
|
|
||||||
sub: Subscription;
|
sub: Subscription;
|
||||||
@ -140,6 +141,10 @@ export class ActivitiDemoComponent implements AfterViewChecked {
|
|||||||
this.taskFilter = event;
|
this.taskFilter = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onReportClick(event: any) {
|
||||||
|
this.report = event;
|
||||||
|
}
|
||||||
|
|
||||||
onSuccessTaskFilterList(event: any) {
|
onSuccessTaskFilterList(event: any) {
|
||||||
this.taskFilter = this.activitifilter.getCurrentFilter();
|
this.taskFilter = this.activitifilter.getCurrentFilter();
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
<script src="node_modules/material-design-lite/material.min.js"></script>
|
<script src="node_modules/material-design-lite/material.min.js"></script>
|
||||||
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
||||||
<link href="node_modules/flag-icon-css/css/flag-icon.min.css" rel="stylesheet">
|
<link href="node_modules/flag-icon-css/css/flag-icon.min.css" rel="stylesheet">
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en'
|
||||||
|
rel='stylesheet' type='text/css'>
|
||||||
|
<link rel="stylesheet" href="node_modules/md-date-time-picker/dist/css/mdDateTimePicker.css" media="all">
|
||||||
|
|
||||||
<!-- 1. Load libraries -->
|
<!-- 1. Load libraries -->
|
||||||
<!-- Polyfill(s) for Safari (pre-10.x) -->
|
<!-- Polyfill(s) for Safari (pre-10.x) -->
|
||||||
@ -34,6 +37,9 @@
|
|||||||
<script src="node_modules/pdfjs-dist/build/pdf.js"></script>
|
<script src="node_modules/pdfjs-dist/build/pdf.js"></script>
|
||||||
<script src="node_modules/pdfjs-dist/build/pdf.worker.js"></script>
|
<script src="node_modules/pdfjs-dist/build/pdf.worker.js"></script>
|
||||||
<script src="node_modules/pdfjs-dist/web/pdf_viewer.js"></script>
|
<script src="node_modules/pdfjs-dist/web/pdf_viewer.js"></script>
|
||||||
|
<script src="node_modules/chart.js/dist/Chart.bundle.min.js"></script>
|
||||||
|
<script src="node_modules/md-date-time-picker/dist/js/mdDateTimePicker.min.js"></script>
|
||||||
|
<script src="node_modules/md-date-time-picker/dist/js/draggabilly.pkgd.min.js"></script>
|
||||||
|
|
||||||
<!-- Polyfill(s) for dialogs -->
|
<!-- Polyfill(s) for dialogs -->
|
||||||
<script src="node_modules/dialog-polyfill/dialog-polyfill.js"></script>
|
<script src="node_modules/dialog-polyfill/dialog-polyfill.js"></script>
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||||
// other libraries
|
// other libraries
|
||||||
'rxjs': 'npm:rxjs',
|
'rxjs': 'npm:rxjs',
|
||||||
|
'moment': 'npm:moment/min/moment.min.js',
|
||||||
|
'ng2-charts' : 'npm:ng2-charts',
|
||||||
'ng2-translate': 'npm:ng2-translate',
|
'ng2-translate': 'npm:ng2-translate',
|
||||||
'ng2-alfresco-core': 'npm:ng2-alfresco-core/dist',
|
'ng2-alfresco-core': 'npm:ng2-alfresco-core/dist',
|
||||||
'ng2-alfresco-datatable': 'npm:ng2-alfresco-datatable/dist',
|
'ng2-alfresco-datatable': 'npm:ng2-alfresco-datatable/dist',
|
||||||
@ -37,7 +39,8 @@
|
|||||||
'ng2-activiti-tasklist': 'npm:ng2-activiti-tasklist/dist',
|
'ng2-activiti-tasklist': 'npm:ng2-activiti-tasklist/dist',
|
||||||
'alfresco-js-api': 'npm:alfresco-js-api/dist',
|
'alfresco-js-api': 'npm:alfresco-js-api/dist',
|
||||||
'ng2-activiti-processlist': 'npm:ng2-activiti-processlist/dist',
|
'ng2-activiti-processlist': 'npm:ng2-activiti-processlist/dist',
|
||||||
'ng2-alfresco-userinfo': 'npm:ng2-alfresco-userinfo/dist'
|
'ng2-alfresco-userinfo': 'npm:ng2-alfresco-userinfo/dist',
|
||||||
|
'ng2-activiti-analytics': 'npm:ng2-activiti-analytics/dist'
|
||||||
},
|
},
|
||||||
// packages tells the System loader how to load when no filename and/or no extension
|
// packages tells the System loader how to load when no filename and/or no extension
|
||||||
packages: {
|
packages: {
|
||||||
@ -49,6 +52,7 @@
|
|||||||
defaultExtension: 'js'
|
defaultExtension: 'js'
|
||||||
},
|
},
|
||||||
'ng2-translate': { defaultExtension: 'js' },
|
'ng2-translate': { defaultExtension: 'js' },
|
||||||
|
'ng2-charts': { defaultExtension: 'js' },
|
||||||
|
|
||||||
'ng2-alfresco-core': { main: './index.js', defaultExtension: 'js'},
|
'ng2-alfresco-core': { main: './index.js', defaultExtension: 'js'},
|
||||||
'ng2-alfresco-datatable': { main: './index.js', defaultExtension: 'js'},
|
'ng2-alfresco-datatable': { main: './index.js', defaultExtension: 'js'},
|
||||||
@ -63,7 +67,8 @@
|
|||||||
'ng2-alfresco-webscript': { main: './index.js', defaultExtension: 'js'},
|
'ng2-alfresco-webscript': { main: './index.js', defaultExtension: 'js'},
|
||||||
'ng2-alfresco-tag': { main: './index.js', defaultExtension: 'js'},
|
'ng2-alfresco-tag': { main: './index.js', defaultExtension: 'js'},
|
||||||
'alfresco-js-api': { main: './alfresco-js-api.js', defaultExtension: 'js'},
|
'alfresco-js-api': { main: './alfresco-js-api.js', defaultExtension: 'js'},
|
||||||
'ng2-alfresco-userinfo': { main: './index.js', defaultExtension: 'js'}
|
'ng2-alfresco-userinfo': { main: './index.js', defaultExtension: 'js'},
|
||||||
|
'ng2-activiti-analytics': { main: './index.js', defaultExtension: 'js'}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})(this);
|
})(this);
|
||||||
|
@ -17,13 +17,27 @@
|
|||||||
|
|
||||||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||||
import { CoreModule } from 'ng2-alfresco-core';
|
import { CoreModule } from 'ng2-alfresco-core';
|
||||||
import { AnalyticsComponent } from './src/components/analytics.component';
|
|
||||||
|
import { AnalyticsReportListComponent } from './src/components/analytics-report-list.component';
|
||||||
|
import { AnalyticsComponent } from './src/components/analytics.component';
|
||||||
|
import { AnalyticsService } from './src/services/analytics.service';
|
||||||
import { CHART_DIRECTIVES } from 'ng2-charts/ng2-charts';
|
import { CHART_DIRECTIVES } from 'ng2-charts/ng2-charts';
|
||||||
|
|
||||||
|
import { WIDGET_DIRECTIVES } from './src/components/widgets/index';
|
||||||
|
|
||||||
export * from './src/components/analytics.component';
|
export * from './src/components/analytics.component';
|
||||||
|
export * from './src/components/analytics-report-list.component';
|
||||||
|
export * from './src/services/analytics.service';
|
||||||
|
export * from './src/components/widgets/index';
|
||||||
|
|
||||||
export const ANALYTICS_DIRECTIVES: any[] = [
|
export const ANALYTICS_DIRECTIVES: any[] = [
|
||||||
AnalyticsComponent
|
AnalyticsComponent,
|
||||||
|
AnalyticsReportListComponent,
|
||||||
|
WIDGET_DIRECTIVES
|
||||||
|
];
|
||||||
|
|
||||||
|
export const ANALYTICS_PROVIDERS: any[] = [
|
||||||
|
AnalyticsService
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -32,7 +46,10 @@ export const ANALYTICS_DIRECTIVES: any[] = [
|
|||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...ANALYTICS_DIRECTIVES,
|
...ANALYTICS_DIRECTIVES,
|
||||||
CHART_DIRECTIVES
|
...CHART_DIRECTIVES
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
...ANALYTICS_PROVIDERS
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
...ANALYTICS_DIRECTIVES
|
...ANALYTICS_DIRECTIVES
|
||||||
@ -43,7 +60,7 @@ export class AnalyticsModule {
|
|||||||
return {
|
return {
|
||||||
ngModule: AnalyticsModule,
|
ngModule: AnalyticsModule,
|
||||||
providers: [
|
providers: [
|
||||||
...ANALYTICS_DIRECTIVES
|
...ANALYTICS_PROVIDERS
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -52,10 +52,11 @@ var map = {
|
|||||||
// other libraries
|
// other libraries
|
||||||
'rxjs': 'npm:rxjs',
|
'rxjs': 'npm:rxjs',
|
||||||
'ng2-translate': 'npm:ng2-translate',
|
'ng2-translate': 'npm:ng2-translate',
|
||||||
|
|
||||||
'ng2-charts' : 'npm:ng2-charts',
|
'ng2-charts' : 'npm:ng2-charts',
|
||||||
|
'moment' : 'npm:moment/min/moment.min.js',
|
||||||
|
|
||||||
'alfresco-js-api': 'npm:alfresco-js-api/dist',
|
'alfresco-js-api': 'npm:alfresco-js-api/dist',
|
||||||
|
'ng2-activiti-analytics': 'npm:ng2-activiti-analytics/dist',
|
||||||
'ng2-alfresco-core': 'npm:ng2-alfresco-core/dist'
|
'ng2-alfresco-core': 'npm:ng2-alfresco-core/dist'
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,9 +64,11 @@ var packages = {
|
|||||||
'app': { main: 'main.js', defaultExtension: 'js' },
|
'app': { main: 'main.js', defaultExtension: 'js' },
|
||||||
'rxjs': { defaultExtension: 'js' },
|
'rxjs': { defaultExtension: 'js' },
|
||||||
'ng2-translate': { defaultExtension: 'js' },
|
'ng2-translate': { defaultExtension: 'js' },
|
||||||
|
'ng2-charts': { defaultExtension: 'js' },
|
||||||
|
'moment': { defaultExtension: 'js' },
|
||||||
|
|
||||||
'ng2-charts' : '/base/node_modules/ng2-charts',
|
|
||||||
'alfresco-js-api': { main: './alfresco-js-api.js', defaultExtension: 'js'},
|
'alfresco-js-api': { main: './alfresco-js-api.js', defaultExtension: 'js'},
|
||||||
|
'ng2-activiti-analytics': { main: './index.js', defaultExtension: 'js'},
|
||||||
'ng2-alfresco-core': { main: './index.js', defaultExtension: 'js'}
|
'ng2-alfresco-core': { main: './index.js', defaultExtension: 'js'}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,17 +86,17 @@ System.import('@angular/core/testing')
|
|||||||
|
|
||||||
function initTestBed(){
|
function initTestBed(){
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
System.import('@angular/core/testing'),
|
System.import('@angular/core/testing'),
|
||||||
System.import('@angular/platform-browser-dynamic/testing')
|
System.import('@angular/platform-browser-dynamic/testing')
|
||||||
])
|
])
|
||||||
.then(function (providers) {
|
.then(function (providers) {
|
||||||
var coreTesting = providers[0];
|
var coreTesting = providers[0];
|
||||||
var browserTesting = providers[1];
|
var browserTesting = providers[1];
|
||||||
|
|
||||||
coreTesting.TestBed.initTestEnvironment(
|
coreTesting.TestBed.initTestEnvironment(
|
||||||
browserTesting.BrowserDynamicTestingModule,
|
browserTesting.BrowserDynamicTestingModule,
|
||||||
browserTesting.platformBrowserDynamicTesting());
|
browserTesting.platformBrowserDynamicTesting());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import all spec files and start karma
|
// Import all spec files and start karma
|
||||||
@ -102,6 +105,6 @@ function initTesting () {
|
|||||||
allSpecFiles.map(function (moduleName) {
|
allSpecFiles.map(function (moduleName) {
|
||||||
return System.import(moduleName);
|
return System.import(moduleName);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.then(__karma__.start, __karma__.error);
|
.then(__karma__.start, __karma__.error);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ module.exports = function (config) {
|
|||||||
|
|
||||||
'node_modules/alfresco-js-api/dist/alfresco-js-api.js',
|
'node_modules/alfresco-js-api/dist/alfresco-js-api.js',
|
||||||
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, watched: false},
|
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, watched: false},
|
||||||
{pattern: 'node_modules/ng2-translate/**/*.js.map', included: false, watched: false},
|
|
||||||
|
|
||||||
'karma-test-shim.js',
|
'karma-test-shim.js',
|
||||||
|
|
||||||
@ -44,9 +43,9 @@ module.exports = function (config) {
|
|||||||
{pattern: 'dist/**/*.css', included: true, served: true, watched: true},
|
{pattern: 'dist/**/*.css', included: true, served: true, watched: true},
|
||||||
|
|
||||||
// ng2-components
|
// ng2-components
|
||||||
{pattern: 'node_modules/ng2-alfresco-core/dist/**/*.*', included: false, served: true, watched: false},
|
{ pattern: 'node_modules/ng2-alfresco-core/dist/**/*.*', included: false, served: true, watched: false },
|
||||||
|
{ pattern: 'node_modules/ng2-charts/**/*.js', included: false, served: true, watched: false },
|
||||||
{pattern: 'node_modules/ng2-charts/**/*.js', included: false, served: true, watched: false},
|
{ pattern: 'node_modules/moment/**/*.js', included: false, served: true, watched: false },
|
||||||
|
|
||||||
// paths to support debugging with source maps in dev tools
|
// paths to support debugging with source maps in dev tools
|
||||||
{pattern: 'src/**/*.ts', included: false, watched: false},
|
{pattern: 'src/**/*.ts', included: false, watched: false},
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
"description": "Activiti Angular2 Analytics Component",
|
"description": "Activiti Angular2 Analytics Component",
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"author": "Alfresco Software, Ltd.",
|
"author": "Alfresco Software, Ltd.",
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"typings": "./dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "npm install rimraf && rimraf dist node_modules typings",
|
"clean": "npm install rimraf && rimraf dist node_modules typings",
|
||||||
"build": "npm run tslint && rimraf dist && tsc && npm run copy-dist && license-check",
|
"build": "npm run tslint && rimraf dist && tsc && npm run copy-dist && license-check",
|
||||||
@ -21,8 +23,16 @@
|
|||||||
"prepublish": "npm run build",
|
"prepublish": "npm run build",
|
||||||
"travis": "echo 'placeholder'"
|
"travis": "echo 'placeholder'"
|
||||||
},
|
},
|
||||||
"main": "./dist/index.js",
|
"contributors": [
|
||||||
"typings": "./dist/index.d.ts",
|
{
|
||||||
|
"name": "Mario Romano",
|
||||||
|
"email": "mario.romnao@alfresco.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Maurizio Vitale",
|
||||||
|
"email": "maurizio.vitale84@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Alfresco/alfresco-ng2-components.git"
|
"url": "https://github.com/Alfresco/alfresco-ng2-components.git"
|
||||||
@ -30,21 +40,6 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
|
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Mario Romano",
|
|
||||||
"email": "mario.romnao@alfresco.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"keywords": [
|
|
||||||
"ng2",
|
|
||||||
"angular",
|
|
||||||
"angular2",
|
|
||||||
"analytics",
|
|
||||||
"alfresco-component",
|
|
||||||
"alfresco"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/common": "2.0.0",
|
"@angular/common": "2.0.0",
|
||||||
"@angular/compiler": "2.0.0",
|
"@angular/compiler": "2.0.0",
|
||||||
@ -56,38 +51,44 @@
|
|||||||
"@angular/router": "3.0.0",
|
"@angular/router": "3.0.0",
|
||||||
"@angular/upgrade": "2.0.0",
|
"@angular/upgrade": "2.0.0",
|
||||||
"@types/node": "^6.0.42",
|
"@types/node": "^6.0.42",
|
||||||
|
"alfresco-js-api": "^0.3.0",
|
||||||
|
"chart.js": "^2.1.4",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
|
"md-date-time-picker": "^2.2.0",
|
||||||
|
"ng2-alfresco-core": "0.3.2",
|
||||||
|
"ng2-charts": "1.1.0",
|
||||||
|
"ng2-translate": "2.5.0",
|
||||||
"reflect-metadata": "^0.1.3",
|
"reflect-metadata": "^0.1.3",
|
||||||
"rxjs": "5.0.0-beta.12",
|
"rxjs": "5.0.0-beta.12",
|
||||||
"systemjs": "0.19.27",
|
"systemjs": "0.19.27",
|
||||||
"zone.js": "^0.6.23",
|
"zone.js": "^0.6.23"
|
||||||
"ng2-translate": "2.5.0",
|
|
||||||
"alfresco-js-api": "^0.3.0",
|
|
||||||
"ng2-alfresco-core": "0.3.2",
|
|
||||||
"ng2-charts": "1.1.0",
|
|
||||||
"chart.js": "^2.1.4"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/core-js": "^0.9.32",
|
"@types/core-js": "^0.9.32",
|
||||||
"@types/jasmine": "^2.2.33",
|
"@types/jasmine": "^2.2.33",
|
||||||
"concurrently": "^2.2.0",
|
"concurrently": "^2.2.0",
|
||||||
"cpx": "1.3.1",
|
"cpx": "^1.3.1",
|
||||||
|
"jasmine-ajax": "^3.2.0",
|
||||||
"jasmine-core": "2.4.1",
|
"jasmine-core": "2.4.1",
|
||||||
"karma": "0.13.22",
|
"karma": "~0.13.22",
|
||||||
"karma-chrome-launcher": "1.0.1",
|
"karma-chrome-launcher": "~1.0.1",
|
||||||
"karma-coverage": "1.0.0",
|
"karma-coverage": "^1.0.0",
|
||||||
"karma-jasmine": "1.0.2",
|
"karma-jasmine": "~1.0.2",
|
||||||
"karma-jasmine-ajax": "0.1.13",
|
"karma-jasmine-ajax": "^0.1.13",
|
||||||
"karma-mocha-reporter": "2.0.3",
|
"karma-jasmine-html-reporter": "^0.2.0",
|
||||||
"karma-jasmine-html-reporter": "0.2.0",
|
"karma-mocha-reporter": "^2.0.3",
|
||||||
"license-check": "1.1.5",
|
"license-check": "^1.0.4",
|
||||||
|
"remap-istanbul": "^0.6.3",
|
||||||
"rimraf": "2.5.2",
|
"rimraf": "2.5.2",
|
||||||
"remap-istanbul": "0.6.3",
|
"traceur": "^0.0.91",
|
||||||
"traceur": "0.0.91",
|
"tslint": "^3.8.1",
|
||||||
"tslint": "3.8.1",
|
|
||||||
"typescript": "^2.0.3",
|
"typescript": "^2.0.3",
|
||||||
"wsrv": "^0.1.5"
|
"wsrv": "^0.1.5"
|
||||||
},
|
},
|
||||||
|
"keywords": [
|
||||||
|
"tag",
|
||||||
|
"alfresco-component"
|
||||||
|
],
|
||||||
"license-check-config": {
|
"license-check-config": {
|
||||||
"src": [
|
"src": [
|
||||||
"./dist/**/*.js"
|
"./dist/**/*.js"
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
<div class="menu-container">
|
||||||
|
<ul class='mdl-list'>
|
||||||
|
<li class="mdl-list__item" (click)="selectReport(report)" *ngFor="let report of reports; let idx = index">
|
||||||
|
<span [attr.id]="'report-list-' + idx" class="mdl-list__item-primary-content">
|
||||||
|
<i class="material-icons mdl-list__item-icon">assignment</i>
|
||||||
|
<span class="text">{{report.name}}</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
@ -0,0 +1,131 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
|
import { CoreModule } from 'ng2-alfresco-core';
|
||||||
|
import { AnalyticsReportListComponent } from '../components/analytics-report-list.component';
|
||||||
|
import { AnalyticsService } from '../services/analytics.service';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
|
declare let jasmine: any;
|
||||||
|
|
||||||
|
describe('Test ng2-activiti-analytics Report list', () => {
|
||||||
|
|
||||||
|
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: any;
|
||||||
|
let fixture: ComponentFixture<AnalyticsReportListComponent>;
|
||||||
|
let debug: DebugElement;
|
||||||
|
let element: HTMLElement;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
CoreModule
|
||||||
|
],
|
||||||
|
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('Report render the report list relative to a single app', (done) => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.onSuccess.subscribe(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(element.querySelector('#report-list-0 > i').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.onError.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);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,93 @@
|
|||||||
|
/*!
|
||||||
|
* @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, OnInit, Output } from '@angular/core';
|
||||||
|
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||||
|
import { AnalyticsService } from '../services/analytics.service';
|
||||||
|
import { ReportModel } from '../models/report.model';
|
||||||
|
import { Observer } from 'rxjs/Observer';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'analytics-report-list',
|
||||||
|
templateUrl: './analytics-report-list.component.html',
|
||||||
|
styleUrls: ['./analytics-report-list.component.css']
|
||||||
|
})
|
||||||
|
export class AnalyticsReportListComponent implements OnInit {
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
reportClick: EventEmitter<ReportModel> = new EventEmitter<ReportModel>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onSuccess = new EventEmitter();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onError = new EventEmitter();
|
||||||
|
|
||||||
|
private reportObserver: Observer<any>;
|
||||||
|
report$: Observable<any>;
|
||||||
|
|
||||||
|
currentReport: any;
|
||||||
|
|
||||||
|
reports: ReportModel[] = [];
|
||||||
|
|
||||||
|
constructor(private auth: AlfrescoAuthenticationService,
|
||||||
|
private analyticsService: AnalyticsService) {
|
||||||
|
|
||||||
|
this.report$ = new Observable<ReportModel>(observer => this.reportObserver = observer).share();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.report$.subscribe((report: ReportModel) => {
|
||||||
|
this.reports.push(report);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.getReportListByAppId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getReportListByAppId() {
|
||||||
|
this.analyticsService.getReportList().subscribe(
|
||||||
|
(res: ReportModel[]) => {
|
||||||
|
res.forEach((report) => {
|
||||||
|
this.reportObserver.next(report);
|
||||||
|
});
|
||||||
|
this.onSuccess.emit(res);
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
this.onError.emit(err);
|
||||||
|
console.log(err);
|
||||||
|
},
|
||||||
|
() => console.log('Reports loaded')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
isReportsEmpty(): boolean {
|
||||||
|
return this.reports === undefined || (this.reports && this.reports.length === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the current report
|
||||||
|
* @param report
|
||||||
|
*/
|
||||||
|
public selectReport(report: any) {
|
||||||
|
this.currentReport = report;
|
||||||
|
this.reportClick.emit(report);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
.chart {display: block; width: 100%;}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-widget__invalid .mdl-textfield__error {
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
@ -1,21 +1,113 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
<div *ngIf="reportDetails">
|
||||||
|
<form [formGroup]="reportForm" novalidate>
|
||||||
|
<h1>{{reportDetails.name}}</h1>
|
||||||
|
<div *ngFor="let field of reportDetails.definition.parameters">
|
||||||
|
<div [ngSwitch]="field.type">
|
||||||
|
<div *ngSwitchCase="'integer'">
|
||||||
|
<br>
|
||||||
|
<number-widget [field]="field"
|
||||||
|
(fieldChanged)="onNumberChanges(field)"></number-widget>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'duration'">
|
||||||
|
<br>
|
||||||
|
<duration-widget [field]="field"
|
||||||
|
(fieldChanged)="onDurationChanges($event)"></duration-widget>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'boolean'">
|
||||||
|
<br>
|
||||||
|
<checkbox-widget [field]="field"
|
||||||
|
(fieldChanged)="onTypeFilteringChanges(field)"></checkbox-widget>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'status'">
|
||||||
|
<br>
|
||||||
|
<dropdown-widget [field]="field"
|
||||||
|
(fieldChanged)="onStatusChanges(field)"></dropdown-widget>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'processDefinition'">
|
||||||
|
<br>
|
||||||
|
<dropdown-widget [field]="field"
|
||||||
|
(fieldChanged)="onProcessDefinitionChanges(field)" #processDefinition></dropdown-widget>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'task'">
|
||||||
|
<br>
|
||||||
|
<dropdown-widget [field]="field"
|
||||||
|
(fieldChanged)="onTaskChanges(field)"></dropdown-widget>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'dateRange'">
|
||||||
|
<br>
|
||||||
|
<date-range-widget [field]="field" [group]="reportForm.controls.dateRange"
|
||||||
|
(dateRangeChanged)="onDateRangeChange($event)"></date-range-widget>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'dateInterval'">
|
||||||
|
<br>
|
||||||
|
<dropdown-widget [field]="field" [showDefaultOption]="false"
|
||||||
|
(fieldChanged)="onDateRangeIntervalChange(field)"></dropdown-widget>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchDefault>
|
||||||
|
<span>UNKNOWN WIDGET TYPE: {{field.type}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<button type="submit" class="mdl-button mdl-js-button mdl-button--fab" (click)="createReport()" >
|
||||||
|
<i class="material-icons">refresh</i>
|
||||||
|
</button>
|
||||||
|
<div *ngIf="debug">
|
||||||
|
<p>ReportForm : {{ reportForm.value | json }}</p>
|
||||||
|
<p>ReportForm valid : {{ reportForm.valid }}</p>
|
||||||
|
<p>ReportForm status : {{ reportForm.errors | json }}</p>
|
||||||
|
<p>ReportForm FormGroup valid : {{ reportForm.controls.dateRange.valid | json }}</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
<base-chart class="chart"
|
<div *ngFor="let report of reports">
|
||||||
[data]="lineChartData"
|
<h2>{{report.title}}</h2>
|
||||||
[labels]="lineChartLabels"
|
<div [ngSwitch]="report.type">
|
||||||
[options]="lineChartOptions"
|
<div *ngSwitchCase="'pie'">
|
||||||
[chartType]="lineChartType"
|
<div class="col-md-6">
|
||||||
(chartHover)="chartHovered($event)"
|
<base-chart class="chart"
|
||||||
(chartClick)="chartClicked($event)"></base-chart>
|
[data]="report.data"
|
||||||
</div>
|
[datasets]="report.datasets"
|
||||||
<div class="col-md-6">
|
[labels]="report.labels"
|
||||||
<base-chart class="chart"
|
[chartType]="report.type"
|
||||||
[data]="pieChartData"
|
(chartClick)="chartClicked($event)"></base-chart>
|
||||||
[labels]="pieChartLabels"
|
</div>
|
||||||
[chartType]="pieChartType"
|
</div>
|
||||||
(chartHover)="chartHovered($event)"
|
<div *ngSwitchCase="'table'">
|
||||||
(chartClick)="chartClicked($event)"></base-chart>
|
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||||
</div>
|
<tr>
|
||||||
<div class="col-md-12 text-center" style="margin-top: 10px;">
|
<th *ngFor="let label of report.labels">{{label | translate}}</th>
|
||||||
<button (click)="randomizeType()" style="display: inline-block">Toggle</button>
|
</tr>
|
||||||
</div>
|
<tr *ngFor="let rows of report.datasets" style="text-align: center;">
|
||||||
|
<td *ngFor="let row of rows">{{row | translate }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'masterDetailTable'">
|
||||||
|
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||||
|
<tr>
|
||||||
|
<th *ngFor="let label of report.labels">{{label | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
<tr *ngFor="let rows of report.datasets" style="text-align: center;">
|
||||||
|
<td *ngFor="let row of rows">{{row | translate }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'bar'">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<base-chart class="chart"
|
||||||
|
[datasets]="report.datasets"
|
||||||
|
[labels]="report.labels"
|
||||||
|
[options]="report.options"
|
||||||
|
[chartType]="report.type"
|
||||||
|
(chartClick)="chartClicked($event)"></base-chart>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchDefault>
|
||||||
|
<span>UNKNOWN WIDGET TYPE: {{report.type}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -16,16 +16,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
import { AnalyticsComponent } from './analytics.component';
|
|
||||||
import { DebugElement } from '@angular/core';
|
|
||||||
import {
|
import {
|
||||||
AlfrescoAuthenticationService,
|
|
||||||
AlfrescoSettingsService,
|
|
||||||
AlfrescoApiService,
|
|
||||||
CoreModule
|
CoreModule
|
||||||
} from 'ng2-alfresco-core';
|
} from 'ng2-alfresco-core';
|
||||||
|
|
||||||
describe('Test ng2-alfresco-analytics analytics component ', () => {
|
import { AnalyticsReportListComponent } from '../components/analytics-report-list.component';
|
||||||
|
import { AnalyticsComponent } from '../components/analytics.component';
|
||||||
|
import { WIDGET_DIRECTIVES } from '../components/widgets/index';
|
||||||
|
import { CHART_DIRECTIVES } from 'ng2-charts/ng2-charts';
|
||||||
|
|
||||||
|
import { AnalyticsService } from '../services/analytics.service';
|
||||||
|
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
|
export const ANALYTICS_DIRECTIVES: any[] = [
|
||||||
|
AnalyticsComponent,
|
||||||
|
AnalyticsReportListComponent,
|
||||||
|
WIDGET_DIRECTIVES
|
||||||
|
];
|
||||||
|
export const ANALYTICS_PROVIDERS: any[] = [
|
||||||
|
AnalyticsService
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
describe('Show component HTML', () => {
|
||||||
|
|
||||||
let component: any;
|
let component: any;
|
||||||
let fixture: ComponentFixture<AnalyticsComponent>;
|
let fixture: ComponentFixture<AnalyticsComponent>;
|
||||||
@ -37,25 +51,26 @@ describe('Test ng2-alfresco-analytics analytics component ', () => {
|
|||||||
imports: [
|
imports: [
|
||||||
CoreModule
|
CoreModule
|
||||||
],
|
],
|
||||||
declarations: [AnalyticsComponent],
|
declarations: [
|
||||||
|
...ANALYTICS_DIRECTIVES,
|
||||||
|
...CHART_DIRECTIVES
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
AlfrescoSettingsService,
|
...ANALYTICS_PROVIDERS
|
||||||
AlfrescoAuthenticationService,
|
|
||||||
AlfrescoApiService
|
|
||||||
]
|
]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(AnalyticsComponent);
|
fixture = TestBed.createComponent(AnalyticsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
debug = fixture.debugElement;
|
debug = fixture.debugElement;
|
||||||
element = fixture.nativeElement;
|
element = fixture.nativeElement;
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
xit('No test', () => {
|
it('Display component tag base-chart', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
});
|
||||||
|
@ -15,35 +15,170 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component, EventEmitter, OnInit, OnChanges, Input, Output, SimpleChanges, ViewChild } from '@angular/core';
|
||||||
|
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||||
|
import { AnalyticsService } from '../services/analytics.service';
|
||||||
|
import { ReportModel, ReportQuery, ParameterValueModel, ReportParameterModel } from '../models/report.model';
|
||||||
|
import { Chart } from '../models/chart.model';
|
||||||
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
moduleId: module.id,
|
moduleId: module.id,
|
||||||
selector: 'activiti-analytics',
|
selector: 'activiti-analytics',
|
||||||
templateUrl: './analytics.component.html'
|
templateUrl: './analytics.component.html',
|
||||||
|
styleUrls: ['./analytics.component.css']
|
||||||
})
|
})
|
||||||
export class AnalyticsComponent {
|
export class AnalyticsComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
constructor() {
|
@ViewChild('processDefinition')
|
||||||
|
processDefinition: any;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
reportId: string;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onSuccess = new EventEmitter();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onError = new EventEmitter();
|
||||||
|
|
||||||
|
reportDetails: ReportModel;
|
||||||
|
|
||||||
|
reportParamQuery = new ReportQuery();
|
||||||
|
|
||||||
|
reports: any[];
|
||||||
|
|
||||||
|
reportForm: FormGroup;
|
||||||
|
|
||||||
|
debug: boolean = true;
|
||||||
|
|
||||||
|
constructor(private translate: AlfrescoTranslationService,
|
||||||
|
private analyticsService: AnalyticsService,
|
||||||
|
private formBuilder: FormBuilder ) {
|
||||||
console.log('AnalyticsComponent');
|
console.log('AnalyticsComponent');
|
||||||
|
if (translate) {
|
||||||
|
translate.addTranslationFolder('node_modules/ng2-activiti-analytics/src');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lineChart
|
ngOnInit() {
|
||||||
public lineChartData: Array<any> = [
|
let today = moment().format('YYYY-MM-DD');
|
||||||
[65, 59, 80, 81, 56, 55, 40],
|
this.reportForm = this.formBuilder.group({
|
||||||
[28, 48, 40, 19, 86, 27, 90]
|
dateRange: this.formBuilder.group({
|
||||||
];
|
startDate: [today, Validators.required],
|
||||||
public lineChartLabels: Array<any> = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
|
endDate: [today, Validators.required]
|
||||||
public lineChartType: string = 'line';
|
})
|
||||||
public pieChartType: string = 'pie';
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Pie
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
public pieChartLabels: string[] = ['Download Sales', 'In-Store Sales', 'Mail Sales'];
|
let reportId = changes['reportId'];
|
||||||
public pieChartData: number[] = [300, 500, 100];
|
if (reportId && reportId.currentValue) {
|
||||||
|
this.getParamsReports(reportId.currentValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public randomizeType(): void {
|
public getParamsReports(reportId: string) {
|
||||||
this.lineChartType = this.lineChartType === 'line' ? 'bar' : 'line';
|
this.reset();
|
||||||
this.pieChartType = this.pieChartType === 'doughnut' ? 'pie' : 'doughnut';
|
this.analyticsService.getParamsReports(reportId).subscribe(
|
||||||
|
(res: ReportModel) => {
|
||||||
|
this.reportDetails = res;
|
||||||
|
this.retriveParameterOptions();
|
||||||
|
this.onSuccess.emit(res);
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
this.onError.emit(err);
|
||||||
|
console.log(err);
|
||||||
|
},
|
||||||
|
() => console.log('Login done')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private retriveParameterOptions() {
|
||||||
|
this.reportDetails.definition.parameters.forEach((param) => {
|
||||||
|
this.analyticsService.getParamValuesByType(param.type).subscribe(
|
||||||
|
(opts: ParameterValueModel[]) => {
|
||||||
|
param.options = opts;
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
console.log(err);
|
||||||
|
},
|
||||||
|
() => console.log(`${param.type} options loaded`)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public createReport() {
|
||||||
|
this.analyticsService.getReportsByParams(this.reportDetails.id, this.reportParamQuery).subscribe(
|
||||||
|
(res: Chart[]) => {
|
||||||
|
this.reports = res;
|
||||||
|
this.onSuccess.emit(res);
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
this.onError.emit(err);
|
||||||
|
console.log(err);
|
||||||
|
},
|
||||||
|
() => console.log('Login done')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onNumberChanges(field: any) {
|
||||||
|
this.reset();
|
||||||
|
this.reportParamQuery.slowProcessInstanceInteger = parseInt(field.value, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDurationChanges(field: any) {
|
||||||
|
this.reset();
|
||||||
|
if (field && field.value) {
|
||||||
|
this.reportParamQuery.duration = parseInt(field.value, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTypeFilteringChanges(field: any) {
|
||||||
|
this.reset();
|
||||||
|
this.reportParamQuery.typeFiltering = field.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onStatusChanges(field: any) {
|
||||||
|
this.reset();
|
||||||
|
this.reportParamQuery.status = field.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onProcessDefinitionChanges(field: any) {
|
||||||
|
this.reset();
|
||||||
|
if (field.value) {
|
||||||
|
this.reportParamQuery.processDefinitionId = field.value;
|
||||||
|
this.analyticsService.getTasksByProcessDefinitionId(this.reportId, this.reportParamQuery.processDefinitionId).subscribe(
|
||||||
|
(res: any) => {
|
||||||
|
let paramTask: ReportParameterModel = this.reportDetails.definition.parameters.find(p => p.type === 'task');
|
||||||
|
if (paramTask) {
|
||||||
|
paramTask.options = res;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTaskChanges(field: any) {
|
||||||
|
this.reset();
|
||||||
|
this.reportParamQuery.taskName = field.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onDateRangeChange(dateRange: any) {
|
||||||
|
this.reset();
|
||||||
|
this.reportParamQuery.dateRange.startDate = dateRange.startDate;
|
||||||
|
this.reportParamQuery.dateRange.endDate = dateRange.endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onDateRangeIntervalChange(field: any) {
|
||||||
|
this.reset();
|
||||||
|
this.reportParamQuery.dateRangeInterval = field.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public reset() {
|
||||||
|
this.reports = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public chartClicked(e: any): void {
|
public chartClicked(e: any): void {
|
||||||
@ -53,4 +188,8 @@ export class AnalyticsComponent {
|
|||||||
public chartHovered(e: any): void {
|
public chartHovered(e: any): void {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public convertNumber(value: string): number {
|
||||||
|
return parseInt(value, 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" [attr.for]="field.id">
|
||||||
|
<input type="checkbox"
|
||||||
|
[attr.id]="field.id"
|
||||||
|
class="mdl-checkbox__input"
|
||||||
|
[checked]="field.value"
|
||||||
|
[(ngModel)]="field.value"
|
||||||
|
(ngModelChange)="changeValue(field)">
|
||||||
|
<span class="mdl-checkbox__label">{{field.nameKey | translate}}</span>
|
||||||
|
</label>
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
|
||||||
|
declare var componentHandler;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'checkbox-widget',
|
||||||
|
templateUrl: './checkbox.widget.html'
|
||||||
|
})
|
||||||
|
export class CheckboxWidget extends WidgetComponent {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
.date-picker-mdl {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
<label>{{field.nameKey | translate}}</label><br>
|
||||||
|
<div [formGroup]="dateRange">
|
||||||
|
<small *ngIf="dateRange.errors && dateRange.errors.greaterThan" [hidden]="!dateRange.errors" class="text-danger">
|
||||||
|
Start date must be less than End date
|
||||||
|
</small>
|
||||||
|
<div class="mdl-grid">
|
||||||
|
<div class="mdl-cell mdl-cell--4-col">
|
||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||||
|
<input class="mdl-textfield__input"
|
||||||
|
formControlName="startDate"
|
||||||
|
type="text"
|
||||||
|
(onOk)="onOkStart(startElement)"
|
||||||
|
id="startDateInput" #startElement>
|
||||||
|
<label class="mdl-textfield__label" for="startDateInput">Start Date</label>
|
||||||
|
<small [hidden]="dateRange.controls.startDate.valid" class="text-danger">
|
||||||
|
Start is required
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-cell mdl-cell--2-col">
|
||||||
|
<button id="startDateButton" class="mdl-button mdl-js-button mdl-button--fab date-picker-mdl">
|
||||||
|
<i class="material-icons">date_range</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-cell mdl-cell--4-col">
|
||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||||
|
<input class="mdl-textfield__input"
|
||||||
|
formControlName="endDate"
|
||||||
|
type="text"
|
||||||
|
(onOk)="onOkEnd(endElement)"
|
||||||
|
id="endDateInput" #endElement>
|
||||||
|
<label class="mdl-textfield__label" for="endDateInput">End Date</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-cell mdl-cell--2-col">
|
||||||
|
<button id="endDateButton" class="mdl-button mdl-js-button mdl-button--fab date-picker-mdl">
|
||||||
|
<i class="material-icons">date_range</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="debug">
|
||||||
|
<p>FormGroup : {{ dateRange.value | json }}</p>
|
||||||
|
<p>FormGroup valid : {{ dateRange.valid }}</p>
|
||||||
|
<p>FormGroup status : {{ dateRange.errors | json }}</p>
|
||||||
|
<p>FormGroup start status : {{ dateRange.controls.startDate.errors | json }}</p>
|
||||||
|
<p>FormGroup end status: {{ dateRange.controls.endDate.errors | json }}</p>
|
||||||
|
</div>
|
@ -0,0 +1,137 @@
|
|||||||
|
/*!
|
||||||
|
* @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, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';
|
||||||
|
import { AbstractControl, FormGroup, FormBuilder } from '@angular/forms';
|
||||||
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
|
||||||
|
declare let mdDateTimePicker: any;
|
||||||
|
|
||||||
|
function dateCheck(c: AbstractControl) {
|
||||||
|
let startDate = moment(c.get('startDate').value);
|
||||||
|
let endDate = moment(c.get('endDate').value);
|
||||||
|
let result = startDate.isAfter(endDate);
|
||||||
|
return result ? {'greaterThan': true} : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'date-range-widget',
|
||||||
|
templateUrl: './date-range.widget.html',
|
||||||
|
styleUrls: ['./date-range.widget.css']
|
||||||
|
})
|
||||||
|
export class DateRangeWidget extends WidgetComponent {
|
||||||
|
|
||||||
|
public static FORMAT_DATE_ACTIVITI: string = 'YYYY-MM-DD';
|
||||||
|
|
||||||
|
@ViewChild('startElement')
|
||||||
|
startElement: any;
|
||||||
|
|
||||||
|
@ViewChild('endElement')
|
||||||
|
endElement: any;
|
||||||
|
|
||||||
|
@Input('group')
|
||||||
|
public dateRange: FormGroup;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
field: any;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
dateRangeChanged: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
debug: boolean = true;
|
||||||
|
|
||||||
|
dialogStart: any = new mdDateTimePicker.default({
|
||||||
|
type: 'date',
|
||||||
|
future: moment().add(21, 'years')
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogEnd: any = new mdDateTimePicker.default({
|
||||||
|
type: 'date',
|
||||||
|
future: moment().add(21, 'years')
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor(public elementRef: ElementRef,
|
||||||
|
private formBuilder: FormBuilder) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.initForm();
|
||||||
|
this.initSartDateDialog();
|
||||||
|
this.initEndDateDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
initForm() {
|
||||||
|
this.dateRange.setValidators(dateCheck);
|
||||||
|
this.dateRange.valueChanges.subscribe(data => this.onGroupValueChanged(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
initSartDateDialog() {
|
||||||
|
this.dialogStart.trigger = this.startElement.nativeElement;
|
||||||
|
|
||||||
|
let startDateButton = document.getElementById('startDateButton');
|
||||||
|
startDateButton.addEventListener('click', () => {
|
||||||
|
this.dialogStart.toggle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initEndDateDialog() {
|
||||||
|
this.dialogEnd.trigger = this.endElement.nativeElement;
|
||||||
|
|
||||||
|
let endDateButton = document.getElementById('endDateButton');
|
||||||
|
endDateButton.addEventListener('click', () => {
|
||||||
|
this.dialogEnd.toggle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onOkStart(inputEl: HTMLInputElement) {
|
||||||
|
let date = this.dialogStart.time.format(DateRangeWidget.FORMAT_DATE_ACTIVITI);
|
||||||
|
this.dateRange.patchValue({
|
||||||
|
startDate: date
|
||||||
|
});
|
||||||
|
let materialElemen: any = inputEl.parentElement;
|
||||||
|
if (materialElemen) {
|
||||||
|
materialElemen.MaterialTextfield.change(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onOkEnd(inputEl: HTMLInputElement) {
|
||||||
|
let date = this.dialogEnd.time.format(DateRangeWidget.FORMAT_DATE_ACTIVITI);
|
||||||
|
this.dateRange.patchValue({
|
||||||
|
endDate: date
|
||||||
|
});
|
||||||
|
|
||||||
|
let materialElemen: any = inputEl.parentElement;
|
||||||
|
if (materialElemen) {
|
||||||
|
materialElemen.MaterialTextfield.change(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onGroupValueChanged(data: any) {
|
||||||
|
if (this.dateRange.valid) {
|
||||||
|
let dateStart = this.convertMomentDate(this.dateRange.controls['startDate'].value);
|
||||||
|
let endStart = this.convertMomentDate(this.dateRange.controls['endDate'].value);
|
||||||
|
this.dateRangeChanged.emit({startDate: dateStart, endDate: endStart});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public convertMomentDate(date: string) {
|
||||||
|
return moment(date, DateRangeWidget.FORMAT_DATE_ACTIVITI, true).format(DateRangeWidget.FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
.date-widget {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-widget__invalid .mdl-textfield__input {
|
||||||
|
border-color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-widget__invalid .mdl-textfield__label {
|
||||||
|
color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-widget__invalid .mdl-textfield__label:after {
|
||||||
|
background-color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-widget__invalid .mdl-textfield__error {
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label date-widget"
|
||||||
|
[class.date-widget__invalid]="!field.isValid">
|
||||||
|
<input class="mdl-textfield__input"
|
||||||
|
type="text"
|
||||||
|
[attr.id]="field.id"
|
||||||
|
[(ngModel)]="field.value"
|
||||||
|
[disabled]="field.readOnly">
|
||||||
|
<label class="mdl-textfield__label" [attr.for]="field.id">{{field.nameKey | translate}} (d-M-yyyy)</label>
|
||||||
|
<span *ngIf="field.validationSummary" class="mdl-textfield__error">{{field.validationSummary}}</span>
|
||||||
|
</div>
|
@ -0,0 +1,51 @@
|
|||||||
|
/*!
|
||||||
|
* @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 } from '@angular/core';
|
||||||
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'date-widget',
|
||||||
|
templateUrl: './date.widget.html',
|
||||||
|
styleUrls: ['./date.widget.css']
|
||||||
|
})
|
||||||
|
export class DateWidget extends WidgetComponent {
|
||||||
|
|
||||||
|
constructor(private elementRef: ElementRef) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupMaterialComponents(componentHandler: any): boolean {
|
||||||
|
// workaround for MDL issues with dynamic components
|
||||||
|
if (componentHandler) {
|
||||||
|
componentHandler.upgradeAllRegistered();
|
||||||
|
if (this.elementRef && this.hasValue()) {
|
||||||
|
let el = this.elementRef.nativeElement;
|
||||||
|
let container = el.querySelector('.mdl-textfield');
|
||||||
|
if (container) {
|
||||||
|
container.MaterialTextfield.change(this.field.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-widget__invalid .mdl-textfield__error {
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
<div class="dropdown-widget">
|
||||||
|
<label class="dropdown-widget__label" [attr.for]="field.id">{{field.nameKey | translate}}</label>
|
||||||
|
<select class="dropdown-widget__select"
|
||||||
|
[(ngModel)]="field.value" (ngModelChange)="changeValue($event)" required>
|
||||||
|
<option *ngIf="showDefaultOption">{{defaultOptionText}}</option>
|
||||||
|
<option *ngFor="let opt of field.options" [value]="opt.id">{{opt.label}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
@ -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 { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'dropdown-widget',
|
||||||
|
templateUrl: './dropdown.widget.html',
|
||||||
|
styleUrls: ['./dropdown.widget.css']
|
||||||
|
})
|
||||||
|
export class DropdownWidget extends WidgetComponent {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
field: any;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
fieldChanged: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
showDefaultOption: boolean = true;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
defaultOptionText: string = 'Choose One';
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(error: any) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
.number-widget {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-widget__invalid .mdl-textfield__input {
|
||||||
|
border-color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-widget__invalid .mdl-textfield__label {
|
||||||
|
color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-widget__invalid .mdl-textfield__label:after {
|
||||||
|
background-color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-widget__invalid .mdl-textfield__error {
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<div class="mdl-grid">
|
||||||
|
<div class="mdl-cell mdl-cell--6-col">
|
||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label number-widget">
|
||||||
|
<input class="mdl-textfield__input"
|
||||||
|
type="text"
|
||||||
|
pattern="-?[0-9]*(\.[0-9]+)?"
|
||||||
|
[attr.id]="field.id"
|
||||||
|
[(ngModel)]="field.value"
|
||||||
|
(ngModelChange)="calculateDuration()">
|
||||||
|
<label class="mdl-textfield__label" [attr.for]="field.id">{{field.nameKey | translate}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-cell mdl-cell--6-col">
|
||||||
|
<div style="margin-top: 30px">
|
||||||
|
<dropdown-widget [field]="duration" [showDefaultOption]="false"
|
||||||
|
(fieldChanged)="calculateDuration()"></dropdown-widget>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, ElementRef, OnInit } from '@angular/core';
|
||||||
|
import { NumberWidget } from './../number/number.widget';
|
||||||
|
import { ReportParameterModel, ParameterValueModel } from './../../../models/report.model';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'duration-widget',
|
||||||
|
templateUrl: './duration.widget.html',
|
||||||
|
styleUrls: ['./duration.widget.css']
|
||||||
|
})
|
||||||
|
export class DurationWidget extends NumberWidget implements OnInit {
|
||||||
|
duration: ReportParameterModel;
|
||||||
|
currentValue: number;
|
||||||
|
|
||||||
|
constructor(public elementRef: ElementRef) {
|
||||||
|
super(elementRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
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 ReportParameterModel({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.fieldChanged.emit({value: this.currentValue});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { DropdownWidget } from './dropdown/dropdown.widget';
|
||||||
|
import { NumberWidget } from './number/number.widget';
|
||||||
|
import { DurationWidget } from './duration/duration.widget';
|
||||||
|
import { CheckboxWidget } from './checkbox/checkbox.widget';
|
||||||
|
import { DateWidget } from './date/date.widget';
|
||||||
|
import { DateRangeWidget } from './date-range/date-range.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/date.widget';
|
||||||
|
export * from './date-range/date-range.widget';
|
||||||
|
|
||||||
|
export const WIDGET_DIRECTIVES: any[] = [
|
||||||
|
DropdownWidget,
|
||||||
|
NumberWidget,
|
||||||
|
DurationWidget,
|
||||||
|
CheckboxWidget,
|
||||||
|
DateWidget,
|
||||||
|
DateRangeWidget
|
||||||
|
];
|
@ -0,0 +1,19 @@
|
|||||||
|
.number-widget {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-widget__invalid .mdl-textfield__input {
|
||||||
|
border-color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-widget__invalid .mdl-textfield__label {
|
||||||
|
color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-widget__invalid .mdl-textfield__label:after {
|
||||||
|
background-color: #d50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-widget__invalid .mdl-textfield__error {
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label number-widget">
|
||||||
|
<input class="mdl-textfield__input"
|
||||||
|
type="text"
|
||||||
|
pattern="-?[0-9]*(\.[0-9]+)?"
|
||||||
|
[attr.id]="field.id"
|
||||||
|
[(ngModel)]="field.value"
|
||||||
|
(ngModelChange)="changeValue(field)">
|
||||||
|
<label class="mdl-textfield__label" [attr.for]="field.id">{{field.nameKey | translate}}</label>
|
||||||
|
</div>
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, ElementRef } from '@angular/core';
|
||||||
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'number-widget',
|
||||||
|
templateUrl: './number.widget.html',
|
||||||
|
styleUrls: ['./number.widget.css']
|
||||||
|
})
|
||||||
|
export class NumberWidget extends WidgetComponent {
|
||||||
|
|
||||||
|
constructor(public elementRef: ElementRef) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupMaterialComponents(handler: any): boolean {
|
||||||
|
// workaround for MDL issues with dynamic components
|
||||||
|
if (handler) {
|
||||||
|
handler.upgradeAllRegistered();
|
||||||
|
if (this.elementRef && this.hasValue()) {
|
||||||
|
let container = this.elementRef.nativeElement.querySelector('.mdl-textfield');
|
||||||
|
if (container) {
|
||||||
|
container.MaterialTextfield.change(this.field.value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { Input, AfterViewInit, Output, EventEmitter, SimpleChanges, OnChanges } from '@angular/core';
|
||||||
|
|
||||||
|
declare var componentHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base widget component.
|
||||||
|
*/
|
||||||
|
export class WidgetComponent implements AfterViewInit, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.setupMaterialComponents(componentHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupMaterialComponents(handler?: any): boolean {
|
||||||
|
// workaround for MDL issues with dynamic components
|
||||||
|
if (handler) {
|
||||||
|
handler.upgradeAllRegistered();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,40 @@
|
|||||||
{
|
{
|
||||||
"ANALYTICS": {
|
"ANALYTICS": {
|
||||||
"TTILE": "ANALYTICS"
|
"TTILE": "ANALYTICS"
|
||||||
|
},
|
||||||
|
"__KEY_REPORTING": {
|
||||||
|
"DEFAULT-REPORTS": {
|
||||||
|
"PROCESS-DEFINITION-OVERVIEW": {
|
||||||
|
"GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS": "Total number of process definitions",
|
||||||
|
"GENERAL-TABLE-TOTAL-PROCESS-INSTANCES": "Total number of process instances",
|
||||||
|
"GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES": "Total number of active process instances",
|
||||||
|
"GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES": "Total number of completed process instances"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"REPORTING": {
|
||||||
|
"DEFAULT-REPORTS": {
|
||||||
|
"PROCESS-HEAT-MAP": {
|
||||||
|
"TYPE-FILTERING": "Include all process steps (Unchecking this, will remove pass through steps like start events, gateways, etc.)?"
|
||||||
|
},
|
||||||
|
"PROCESS-INSTANCES-OVERVIEW": {
|
||||||
|
"PROCESS-DEFINITION": "Process definition",
|
||||||
|
"DATE-RANGE": "Date range",
|
||||||
|
"SLOW-PROC-INST-NUMBER": "How many of the slowest process instances should be displayed?"
|
||||||
|
},
|
||||||
|
"TASK-OVERVIEW": {
|
||||||
|
"PROCESS-DEFINITION": "Process definition",
|
||||||
|
"DATE-RANGE": "Date range",
|
||||||
|
"DATE-RANGE-INTERVAL": "Aggregate dates by"
|
||||||
|
},
|
||||||
|
"TASK-SLA": {
|
||||||
|
"TASK": "Task",
|
||||||
|
"PROCESS-DEFINITION": "Process definition",
|
||||||
|
"DATE-RANGE": "Date range",
|
||||||
|
"SLA-DURATION": "What is the time this task needs to be completed in to be within the SLA?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PROCESS-STATUS": "Process status",
|
||||||
|
"TASK-STATUS": "Task status"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
160
ng2-components/ng2-activiti-analytics/src/models/chart.model.ts
Normal file
160
ng2-components/ng2-activiti-analytics/src/models/chart.model.ts
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*!
|
||||||
|
* @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 class Chart {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
this.id = obj && obj.id || null;
|
||||||
|
if (obj && obj.type) {
|
||||||
|
this.type = this.convertType(obj.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private convertType(type: string) {
|
||||||
|
let chartType = '';
|
||||||
|
switch (type) {
|
||||||
|
case 'pieChart':
|
||||||
|
chartType = 'pie';
|
||||||
|
break;
|
||||||
|
case 'table':
|
||||||
|
chartType = 'table';
|
||||||
|
break;
|
||||||
|
case 'line':
|
||||||
|
chartType = 'line';
|
||||||
|
break;
|
||||||
|
case 'barChart':
|
||||||
|
chartType = 'bar';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
chartType = 'table';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return chartType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LineChart extends Chart {
|
||||||
|
title: string;
|
||||||
|
titleKey: string;
|
||||||
|
labels: string[] = [];
|
||||||
|
datasets: any[] = [];
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
super(obj);
|
||||||
|
this.title = obj && obj.title || null;
|
||||||
|
this.titleKey = obj && obj.titleKey || null;
|
||||||
|
this.labels = obj && obj.columnNames.slice(1, obj.columnNames.length);
|
||||||
|
|
||||||
|
obj.rows.forEach((value: any) => {
|
||||||
|
this.datasets.push({data: value.slice(1, value.length), label: value[0]});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BarChart extends Chart {
|
||||||
|
title: string;
|
||||||
|
titleKey: string;
|
||||||
|
labels: string[] = [];
|
||||||
|
datasets: any[] = [];
|
||||||
|
data: any[] = [];
|
||||||
|
options: any = {
|
||||||
|
scales: {
|
||||||
|
yAxes: [{
|
||||||
|
ticks: {
|
||||||
|
beginAtZero: true,
|
||||||
|
stepSize: 1
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
super(obj);
|
||||||
|
this.title = obj && obj.title || null;
|
||||||
|
this.titleKey = obj && obj.titleKey || null;
|
||||||
|
obj.values.forEach((params: any) => {
|
||||||
|
let dataValue = [];
|
||||||
|
params.values.forEach((info: any) => {
|
||||||
|
info.forEach((value: any, index: any) => {
|
||||||
|
if (index % 2 === 0) {
|
||||||
|
this.labels.push(value);
|
||||||
|
} else {
|
||||||
|
dataValue.push(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.datasets.push({data: dataValue, label: params.key});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TableChart extends Chart {
|
||||||
|
title: string;
|
||||||
|
titleKey: string;
|
||||||
|
labels: string[] = [];
|
||||||
|
datasets: any[] = [];
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
super(obj);
|
||||||
|
this.title = obj && obj.title || null;
|
||||||
|
this.titleKey = obj && obj.titleKey || null;
|
||||||
|
this.labels = obj && obj.columnNames;
|
||||||
|
this.datasets = obj && obj.rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class HeatMapChart extends Chart {
|
||||||
|
title: string;
|
||||||
|
titleKey: string;
|
||||||
|
labels: string[] = [];
|
||||||
|
datasets: any[] = [];
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
super(obj);
|
||||||
|
this.title = obj && obj.title || null;
|
||||||
|
this.titleKey = obj && obj.titleKey || null;
|
||||||
|
this.labels = obj && obj.columnNames;
|
||||||
|
this.datasets = obj && obj.rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PieChart extends Chart {
|
||||||
|
title: string;
|
||||||
|
titleKey: string;
|
||||||
|
labels: string[] = [];
|
||||||
|
data: string[] = [];
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
super(obj);
|
||||||
|
this.title = obj && obj.title || null;
|
||||||
|
this.titleKey = obj && obj.titleKey || null;
|
||||||
|
if (obj.values) {
|
||||||
|
obj.values.forEach((value: any) => {
|
||||||
|
this.add(value.key, value.y);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add(label: string, data: string) {
|
||||||
|
this.labels.push(label);
|
||||||
|
this.data.push(data);
|
||||||
|
}
|
||||||
|
}
|
136
ng2-components/ng2-activiti-analytics/src/models/report.model.ts
Normal file
136
ng2-components/ng2-activiti-analytics/src/models/report.model.ts
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This object represent the report definition.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @returns {ReportModel} .
|
||||||
|
*/
|
||||||
|
export class ReportModel {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
definition: ReportParametersModel;
|
||||||
|
created: string;
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
this.id = obj && obj.id;
|
||||||
|
this.name = obj && obj.name || null;
|
||||||
|
if (obj && obj.definition) {
|
||||||
|
this.definition = new ReportParametersModel(JSON.parse(obj.definition));
|
||||||
|
}
|
||||||
|
this.created = obj && obj.created || null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReportParametersModel {
|
||||||
|
parameters: ReportParameterModel[] = [];
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
obj.parameters.forEach((params: any) => {
|
||||||
|
let reportParamsModel = new ReportParameterModel(params);
|
||||||
|
this.parameters.push(reportParamsModel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
findParam(name: string): ReportParameterModel {
|
||||||
|
this.parameters.forEach((param) => {
|
||||||
|
return param.type === name ? param : null;
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This object represent the report parameter definition.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @returns {ReportParameterModel} .
|
||||||
|
*/
|
||||||
|
export class ReportParameterModel {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
nameKey: string;
|
||||||
|
type: string;
|
||||||
|
value: string;
|
||||||
|
options: ParameterValueModel[];
|
||||||
|
dependsOn: string;
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
this.id = obj && obj.id;
|
||||||
|
this.name = obj && obj.name || null;
|
||||||
|
this.nameKey = obj && obj.nameKey || null;
|
||||||
|
this.type = obj && obj.type || null;
|
||||||
|
this.value = obj && obj.value || null;
|
||||||
|
this.options = obj && obj.options || null;
|
||||||
|
this.dependsOn = obj && obj.dependsOn || null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ParameterValueModel {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
this.id = obj && obj.id;
|
||||||
|
this.name = obj && obj.name || null;
|
||||||
|
this.value = obj && obj.value || null;
|
||||||
|
this.version = obj && obj.version || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get label () {
|
||||||
|
return this.version ? `${this.name} (v ${this.version}) ` : this.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class ReportQuery {
|
||||||
|
processDefinitionId: string;
|
||||||
|
status: string;
|
||||||
|
taskName: string;
|
||||||
|
typeFiltering: boolean;
|
||||||
|
dateRange: ReportDateRange;
|
||||||
|
dateRangeInterval: string;
|
||||||
|
slowProcessInstanceInteger: number;
|
||||||
|
duration: number;
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
this.processDefinitionId = obj && obj.processDefinitionId || null;
|
||||||
|
this.status = obj && obj.status || null;
|
||||||
|
this.taskName = obj && obj.taskName || null;
|
||||||
|
this.dateRangeInterval = obj && obj.dateRangeInterval || null;
|
||||||
|
this.typeFiltering = obj && obj.typeFiltering || false;
|
||||||
|
this.slowProcessInstanceInteger = obj && obj.slowProcessInstanceInteger || 0;
|
||||||
|
this.duration = obj && obj.duration || 0;
|
||||||
|
this.dateRange = new ReportDateRange(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReportDateRange {
|
||||||
|
startDate: string;
|
||||||
|
endDate: string;
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
this.startDate = obj && obj.startDate || null;
|
||||||
|
this.endDate = obj && obj.endDate || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,211 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { Injectable } from '@angular/core';
|
||||||
|
import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
import { Response, Http, Headers, RequestOptions, URLSearchParams } from '@angular/http';
|
||||||
|
import { ReportModel, ParameterValueModel } from '../models/report.model';
|
||||||
|
import { Chart, PieChart, TableChart, BarChart } from '../models/chart.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AnalyticsService {
|
||||||
|
|
||||||
|
constructor(private authService: AlfrescoAuthenticationService,
|
||||||
|
private http: Http,
|
||||||
|
private alfrescoSettingsService: AlfrescoSettingsService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrive all the Deployed app
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
getReportList(): Observable<any> {
|
||||||
|
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/reports`;
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
return this.http
|
||||||
|
.get(url, options)
|
||||||
|
.map((res: any) => {
|
||||||
|
let reports: ReportModel[] = [];
|
||||||
|
let body = res.json();
|
||||||
|
body.forEach((report: ReportModel) => {
|
||||||
|
let reportModel = new ReportModel(report);
|
||||||
|
reports.push(reportModel);
|
||||||
|
});
|
||||||
|
if (body && body.length === 0) {
|
||||||
|
return this.createDefaultReports();
|
||||||
|
}
|
||||||
|
return reports;
|
||||||
|
}).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
getParamsReports(reportId: string): Observable<any> {
|
||||||
|
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/report-params/${reportId}`;
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
return this.http
|
||||||
|
.get(url, options)
|
||||||
|
.map((res: any) => {
|
||||||
|
let body = res.json();
|
||||||
|
return new ReportModel(body);
|
||||||
|
}).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
getParamValuesByType(type: string, reportId?: string, processDefinitionId?: string) {
|
||||||
|
if (type === 'status') {
|
||||||
|
return this.getProcessStatusValues();
|
||||||
|
} else if (type === 'processDefinition') {
|
||||||
|
return this.getProcessDefinitionsValues();
|
||||||
|
} else if (type === 'dateInterval') {
|
||||||
|
return this.getDateIntervalValues();
|
||||||
|
} else if (type === 'task') {
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getProcessDefinitionsValues(appId?: string): Observable<any> {
|
||||||
|
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/process-definitions`;
|
||||||
|
let params: URLSearchParams;
|
||||||
|
if (appId) {
|
||||||
|
params = new URLSearchParams();
|
||||||
|
params.set('appDefinitionId', appId);
|
||||||
|
}
|
||||||
|
let options = this.getRequestOptions(params);
|
||||||
|
return this.http
|
||||||
|
.get(url, options)
|
||||||
|
.map((res: any) => {
|
||||||
|
let paramOptions: ParameterValueModel[] = [];
|
||||||
|
let body = res.json();
|
||||||
|
body.forEach((opt) => {
|
||||||
|
paramOptions.push(new ParameterValueModel(opt));
|
||||||
|
});
|
||||||
|
return paramOptions;
|
||||||
|
}).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTasksByProcessDefinitionId(reportId: string, processDefinitionId: string): Observable<any> {
|
||||||
|
if (processDefinitionId) {
|
||||||
|
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/report-params/${reportId}/tasks`;
|
||||||
|
let params: URLSearchParams;
|
||||||
|
if (processDefinitionId) {
|
||||||
|
params = new URLSearchParams();
|
||||||
|
params.set('processDefinitionId', processDefinitionId);
|
||||||
|
}
|
||||||
|
let options = this.getRequestOptions(params);
|
||||||
|
return this.http
|
||||||
|
.get(url, options)
|
||||||
|
.map((res: any) => {
|
||||||
|
let paramOptions: ParameterValueModel[] = [];
|
||||||
|
let body = res.json();
|
||||||
|
body.forEach((opt) => {
|
||||||
|
paramOptions.push(new ParameterValueModel({id: opt, name: opt}));
|
||||||
|
});
|
||||||
|
return paramOptions;
|
||||||
|
}).catch(this.handleError);
|
||||||
|
} else {
|
||||||
|
return Observable.create(observer => {
|
||||||
|
observer.next(null);
|
||||||
|
observer.complete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getReportsByParams(reportId: number, paramsQuery: any): Observable<any> {
|
||||||
|
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/reporting/report-params/${reportId}`;
|
||||||
|
let body = JSON.stringify(paramsQuery);
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
return this.http
|
||||||
|
.post(url, body, options)
|
||||||
|
.map((res: any) => {
|
||||||
|
let elements: Chart[] = [];
|
||||||
|
let bodyRes = res.json();
|
||||||
|
bodyRes.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 TableChart(chartData));
|
||||||
|
} else if (chartData.type === 'masterDetailTable') {
|
||||||
|
elements.push(new TableChart(chartData));
|
||||||
|
} else if (chartData.type === 'barChart') {
|
||||||
|
elements.push(new BarChart(chartData));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createDefaultReports(): ReportModel[] {
|
||||||
|
let reports: ReportModel[] = [];
|
||||||
|
return reports;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHeaders(): Headers {
|
||||||
|
return new Headers({
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': this.authService.getTicketBpm()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRequestOptions(param?: any): RequestOptions {
|
||||||
|
let headers = this.getHeaders();
|
||||||
|
return new RequestOptions({headers: headers, withCredentials: true, search: param});
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleError(error: Response) {
|
||||||
|
console.error(error);
|
||||||
|
return Observable.throw(error.json().error || 'Server error');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -60,7 +60,8 @@
|
|||||||
"rxjs": "5.0.0-beta.12",
|
"rxjs": "5.0.0-beta.12",
|
||||||
"systemjs": "0.19.27",
|
"systemjs": "0.19.27",
|
||||||
"zone.js": "^0.6.23",
|
"zone.js": "^0.6.23",
|
||||||
|
"md-date-time-picker": "^2.2.0",
|
||||||
|
"moment": "2.15.1",
|
||||||
"material-design-icons": "2.2.3",
|
"material-design-icons": "2.2.3",
|
||||||
"material-design-lite": "1.2.1",
|
"material-design-lite": "1.2.1",
|
||||||
"ng2-translate": "2.5.0",
|
"ng2-translate": "2.5.0",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user