mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
@@ -10,6 +10,7 @@ Please ask before on our gitter channel https://gitter.im/Alfresco/alfresco-ng2-
|
||||
- [ ] New feature request
|
||||
- [ ] Bug
|
||||
- [ ] Support request
|
||||
- [ ] Documentation
|
||||
```
|
||||
**Current behavior:**
|
||||
<!-- Describe the current behavior. -->
|
||||
|
||||
+14
-7
@@ -32,24 +32,31 @@ env:
|
||||
|
||||
before_script:
|
||||
- if ([ "$MODULE" != "ng2-alfresco-core" ]); then
|
||||
(cd ng2-components/ng2-alfresco-core; if [ ! -d "dist" ]; then npm install; fi; npm link);
|
||||
(cd ng2-components/ng2-alfresco-core; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-alfresco-documentlist" ] || [ "$MODULE" == "ng2-alfresco-webscript" ] || [ "$MODULE" == "ng2-activiti-processlist" ] || [ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
||||
(cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; if [ ! -d "dist" ]; then npm install; fi; npm link);
|
||||
(cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-activiti-tasklist" ] || [ "$MODULE" == "ng2-activiti-processlist" ]); then
|
||||
(cd ng2-components/ng2-activiti-form; npm link ng2-alfresco-core; if [ ! -d "dist" ]; then npm install; fi; npm link);
|
||||
(cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
(cd ng2-components/ng2-activiti-form; npm link ng2-alfresco-core; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-activiti-processlist" ]); then
|
||||
(cd ng2-components/ng2-activiti-tasklist; npm link ng2-alfresco-core; npm link ng2-alfresco-datatable; npm link ng2-activiti-form; if [ ! -d "dist" ]; then npm install; fi; npm link);
|
||||
(cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
(cd ng2-components/ng2-activiti-form; npm link ng2-alfresco-core; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
(cd ng2-components/ng2-activiti-tasklist; npm link ng2-alfresco-core; npm link ng2-alfresco-datatable; npm link ng2-activiti-form; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-activiti-analytics" ]); then
|
||||
(cd ng2-components/ng2-activiti-diagrams; npm link ng2-alfresco-core; if [ ! -d "dist" ]; then npm install; fi; npm link);
|
||||
(cd ng2-components/ng2-activiti-diagrams; npm link ng2-alfresco-core; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
fi
|
||||
- if ([ "$MODULE" == "ng2-alfresco-search" ]); then
|
||||
(cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
(cd ng2-components/ng2-alfresco-documentlist; npm link ng2-alfresco-core; npm link ng2-alfresco-datatable; if [ ! -d "bundles" ]; then npm link; fi);
|
||||
fi
|
||||
- cd ng2-components/$MODULE;
|
||||
- npm run travis;
|
||||
- npm install;
|
||||
script: npm run test
|
||||
#npm insall run install, build and tests
|
||||
script: npm install
|
||||
# Send coverage data to Coveralls
|
||||
after_success:
|
||||
bash <(curl -s https://codecov.io/bash) -X gcov
|
||||
|
||||
Vendored
+4
-2
@@ -6,6 +6,8 @@
|
||||
"**/.hg": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/*.js": { "when": "$(basename).ts"},
|
||||
"**/*.js.map": { "when": "$(basename)"}
|
||||
}
|
||||
"**/*.js.map": { "when": "$(basename)"},
|
||||
"**/*.d.ts": { "when": "$(basename).ts"}
|
||||
},
|
||||
"editor.renderIndentGuides": true
|
||||
}
|
||||
|
||||
@@ -56,6 +56,12 @@ To view the complete list of all the components that you can use to build your c
|
||||
|
||||
You can browse all the components at the following [page](http://devproducts.alfresco.com/).
|
||||
|
||||
## Demo Application
|
||||
|
||||
A separate application showcasing integration of components can be found [here](https://github.com/Alfresco/alfresco-ng2-components/tree/master/demo-shell-ng2).
|
||||
|
||||
You will find examples of basic interaction for both BPM and ECM sets of widgets.
|
||||
|
||||
## Yeoman generators
|
||||
|
||||
To speed up the development of your Alfresco Angular 2 application, or Alfresco Angular 2 component, use one of the Yeoman generators.
|
||||
|
||||
+17
-15
@@ -1,4 +1,9 @@
|
||||
# Test against this version of Node.js
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- development
|
||||
- dev-build-test
|
||||
|
||||
environment:
|
||||
nodejs_version: "5"
|
||||
@@ -25,22 +30,19 @@ install:
|
||||
# Get the latest stable version of Node.js or io.js
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
# install module
|
||||
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (cd ng2-components/ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-activiti-tasklist && npm link ng2-alfresco-core && npm link ng2-alfresco-datatable && npm link ng2-activiti-form && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-analytics (cd ng2-components/ng2-activiti-diagrams && npm link link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (cd ng2-components/ng2-alfresco-core && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-search (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-search (cd ng2-components/ng2-alfresco-documentlist && npm link ng2-alfresco-core && npm link ng2-alfresco-datatable && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-activiti-tasklist && npm link ng2-alfresco-core && npm link ng2-alfresco-datatable && npm link ng2-activiti-form && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm link && cd ../../)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-analytics (cd ng2-components/ng2-activiti-diagrams && npm link link ng2-alfresco-core && npm link && cd ../../)
|
||||
- cd ng2-components/%COMPONENT_NAME%
|
||||
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (npm link ng2-alfresco-core)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (npm link ng2-alfresco-datatable)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (npm link ng2-alfresco-datatable && npm link ng2-activiti-form && npm link ng2-activiti-tasklist)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (npm link ng2-alfresco-datatable && npm link ng2-activiti-form)
|
||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (npm link ng2-alfresco-datatable)
|
||||
- IF %COMPONENT_NAME% EQU ng2-activiti-analytics (npm link ng2-activiti-diagrams)
|
||||
- npm run travis
|
||||
|
||||
# Post-install test scripts.
|
||||
test_script:
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
|
||||
## Installing
|
||||
|
||||
To correctly use this demo check that on your machine is running Node version 6.9.2 LTS or higher.
|
||||
To correctly use this demo check that on your machine is running [Node](https://nodejs.org/en/) version 6.9.2 LTS or higher.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/Alfresco/alfresco-ng2-components.git
|
||||
cd alfresco-ng2-components/demo-shell-ng2/
|
||||
npm install
|
||||
```
|
||||
|
||||
@@ -28,22 +30,26 @@ This command compiles and starts the project in watch mode.
|
||||
Browser will automatically reload upon changes.
|
||||
Upon start you can navigate to `http://localhost:3000` with your preferred browser.
|
||||
|
||||
### Important notes
|
||||
|
||||
This script is recommended for development environment and not suited for headless servers and network access.
|
||||
|
||||
## Production build
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
npm run start:dist
|
||||
```
|
||||
|
||||
This command builds broject in `production` mode.
|
||||
All output is placed to `dist` folder and can be served your preferred web server.
|
||||
You should need no additional files outside the `dist` folder.
|
||||
|
||||
In order to quickly test the output you can use the [wsrv](https://www.npmjs.com/package/wsrv) tool (lightweight web server):
|
||||
### Important notes
|
||||
|
||||
```sh
|
||||
npm install -g wsrv
|
||||
wsrv -s -o dist/
|
||||
```
|
||||
By default demo application is configured to use [wsrv](https://www.npmjs.com/package/wsrv) tool (lightweight web server)
|
||||
to serve production build output. It will be running at `0.0.0.0` address with port `3000` and allow you accessing your application
|
||||
via network. However you can use any web server of your choice in production.
|
||||
|
||||
## Development branch build
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- Always shows a header, even in smaller screens. -->
|
||||
<div mdl class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
|
||||
<header class="mdl-layout__header main_header_adf" [ngClass]="{hide: isLoginPage()}">
|
||||
<header class="mdl-layout__header main_header_adf" [ngClass]="{hide: isAPageWithHeaderBar()}">
|
||||
<div class="mdl-button-padding mdl-layout__header-row">
|
||||
|
||||
<!-- User Info -->
|
||||
|
||||
@@ -17,13 +17,7 @@
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import {
|
||||
AlfrescoTranslationService,
|
||||
AlfrescoAuthenticationService,
|
||||
AlfrescoSettingsService,
|
||||
StorageService
|
||||
} from 'ng2-alfresco-core';
|
||||
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoSettingsService, StorageService, LogService } from 'ng2-alfresco-core';
|
||||
|
||||
declare var document: any;
|
||||
|
||||
@@ -38,44 +32,34 @@ export class AppComponent {
|
||||
ecmHost: string = 'http://' + window.location.hostname + ':8080';
|
||||
bpmHost: string = 'http://' + window.location.hostname + ':9999';
|
||||
|
||||
constructor(public auth: AlfrescoAuthenticationService,
|
||||
public router: Router,
|
||||
public alfrescoSettingsService: AlfrescoSettingsService,
|
||||
private translate: AlfrescoTranslationService,
|
||||
private storage: StorageService) {
|
||||
constructor(private authService: AlfrescoAuthenticationService,
|
||||
private router: Router,
|
||||
private settingsService: AlfrescoSettingsService,
|
||||
private translateService: AlfrescoTranslationService,
|
||||
private storage: StorageService,
|
||||
private logService: LogService) {
|
||||
this.setEcmHost();
|
||||
this.setBpmHost();
|
||||
this.setProvider();
|
||||
|
||||
if (translate) {
|
||||
if (translateService) {
|
||||
if (process.env.ENV === 'production') {
|
||||
translate.addTranslationFolder('custom', 'i18n/custom-translation');
|
||||
translate.addTranslationFolder('ng2-alfresco-login', 'i18n/custom-translation/alfresco-login');
|
||||
translateService.addTranslationFolder('custom', 'i18n/custom-translation');
|
||||
translateService.addTranslationFolder('ng2-alfresco-login', 'i18n/custom-translation/alfresco-login');
|
||||
} else {
|
||||
translate.addTranslationFolder('custom', 'custom-translation');
|
||||
translate.addTranslationFolder('ng2-alfresco-login', 'custom-translation/alfresco-login');
|
||||
translateService.addTranslationFolder('custom', 'custom-translation');
|
||||
translateService.addTranslationFolder('ng2-alfresco-login', 'custom-translation/alfresco-login');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isLoggedIn(): boolean {
|
||||
this.redirectToLoginPageIfNotLoggedIn();
|
||||
return this.auth.isLoggedIn();
|
||||
}
|
||||
|
||||
redirectToLoginPageIfNotLoggedIn(): void {
|
||||
if (!this.isLoginPage() && !this.auth.isLoggedIn()) {
|
||||
this.router.navigate(['/login']);
|
||||
}
|
||||
}
|
||||
|
||||
isLoginPage(): boolean {
|
||||
isAPageWithHeaderBar(): boolean {
|
||||
return location.pathname === '/login' || location.pathname === '/settings';
|
||||
}
|
||||
|
||||
onLogout(event) {
|
||||
event.preventDefault();
|
||||
this.auth.logout()
|
||||
this.authService.logout()
|
||||
.subscribe(
|
||||
() => {
|
||||
this.navigateToLogin();
|
||||
@@ -84,7 +68,7 @@ export class AppComponent {
|
||||
if (error && error.response && error.response.status === 401) {
|
||||
this.navigateToLogin();
|
||||
} else {
|
||||
console.error('An unknown error occurred while logging out', error);
|
||||
this.logService.error('An unknown error occurred while logging out', error);
|
||||
this.navigateToLogin();
|
||||
}
|
||||
}
|
||||
@@ -107,7 +91,7 @@ export class AppComponent {
|
||||
}
|
||||
|
||||
changeLanguage(lang: string) {
|
||||
this.translate.use(lang);
|
||||
this.translateService.use(lang);
|
||||
this.hideDrawer();
|
||||
}
|
||||
|
||||
@@ -118,25 +102,25 @@ export class AppComponent {
|
||||
|
||||
private setEcmHost() {
|
||||
if (this.storage.hasItem(`ecmHost`)) {
|
||||
this.alfrescoSettingsService.ecmHost = this.storage.getItem(`ecmHost`);
|
||||
this.settingsService.ecmHost = this.storage.getItem(`ecmHost`);
|
||||
this.ecmHost = this.storage.getItem(`ecmHost`);
|
||||
} else {
|
||||
this.alfrescoSettingsService.ecmHost = this.ecmHost;
|
||||
this.settingsService.ecmHost = this.ecmHost;
|
||||
}
|
||||
}
|
||||
|
||||
private setBpmHost() {
|
||||
if (this.storage.hasItem(`bpmHost`)) {
|
||||
this.alfrescoSettingsService.bpmHost = this.storage.getItem(`bpmHost`);
|
||||
this.settingsService.bpmHost = this.storage.getItem(`bpmHost`);
|
||||
this.bpmHost = this.storage.getItem(`bpmHost`);
|
||||
} else {
|
||||
this.alfrescoSettingsService.bpmHost = this.bpmHost;
|
||||
this.settingsService.bpmHost = this.bpmHost;
|
||||
}
|
||||
}
|
||||
|
||||
private setProvider() {
|
||||
if (this.storage.hasItem(`providers`)) {
|
||||
this.alfrescoSettingsService.setProviders(this.storage.getItem(`providers`));
|
||||
this.settingsService.setProviders(this.storage.getItem(`providers`));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import { ActivitiTaskListModule } from 'ng2-activiti-tasklist';
|
||||
import { ActivitiProcessListModule } from 'ng2-activiti-processlist';
|
||||
import { UserInfoComponentModule } from 'ng2-alfresco-userinfo';
|
||||
import { AnalyticsModule } from 'ng2-activiti-analytics';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { routing } from './app.routes';
|
||||
import { CustomEditorsModule } from './components/activiti/custom-editor/custom-editor.component';
|
||||
@@ -59,13 +58,13 @@ import {
|
||||
BrowserModule,
|
||||
routing,
|
||||
CoreModule.forRoot(),
|
||||
LoginModule,
|
||||
LoginModule.forRoot(),
|
||||
SearchModule.forRoot(),
|
||||
DataTableModule,
|
||||
DataTableModule.forRoot(),
|
||||
DocumentListModule.forRoot(),
|
||||
UploadModule.forRoot(),
|
||||
TagModule.forRoot(),
|
||||
WebScriptModule,
|
||||
WebScriptModule.forRoot(),
|
||||
ViewerModule.forRoot(),
|
||||
ActivitiFormModule.forRoot(),
|
||||
ActivitiTaskListModule.forRoot(),
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import { ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
|
||||
@Component({
|
||||
selector: 'about-page',
|
||||
@@ -27,31 +28,31 @@ export class AboutComponent implements OnInit {
|
||||
|
||||
data: ObjectDataTableAdapter;
|
||||
|
||||
constructor(private http: Http) {
|
||||
constructor(private http: Http,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.http.get('/versions.json').subscribe(response => {
|
||||
var regexp = new RegExp("^(ng2-activiti|ng2-alfresco|alfresco-)", 'g');
|
||||
let regexp = new RegExp('^(ng2-activiti|ng2-alfresco|alfresco-)', 'g');
|
||||
|
||||
var alfrescoPackages = Object.keys(response.json().dependencies).filter(function (val) {
|
||||
console.log(val);
|
||||
let alfrescoPackages = Object.keys(response.json().dependencies).filter((val) => {
|
||||
this.logService.log(val);
|
||||
return regexp.test(val);
|
||||
});
|
||||
|
||||
let alfrescoPackagesTableRappresentation = [];
|
||||
alfrescoPackages.forEach((val)=> {
|
||||
console.log(response.json().dependencies[val]);
|
||||
alfrescoPackagesTableRappresentation.push({name:val,version:response.json().dependencies[val].version});
|
||||
let alfrescoPackagesTableRappresentation = [];
|
||||
alfrescoPackages.forEach((val) => {
|
||||
this.logService.log(response.json().dependencies[val]);
|
||||
alfrescoPackagesTableRappresentation.push({name: val, version: response.json().dependencies[val].version});
|
||||
});
|
||||
|
||||
console.log(alfrescoPackagesTableRappresentation);
|
||||
this.logService.log(alfrescoPackagesTableRappresentation);
|
||||
|
||||
this.data = new ObjectDataTableAdapter(alfrescoPackagesTableRappresentation, [
|
||||
{type: 'text', key: 'name', title: 'Name', sortable: true},
|
||||
{type: 'text', key: 'version', title: 'Version', sortable: true}
|
||||
]);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<!-- TABS -->
|
||||
|
||||
<div class="mdl-layout__tab-bar mdl-js-ripple-effect">
|
||||
<a id="tasks-header" href="#tasks" class="mdl-layout__tab is-active">TASKS</a>
|
||||
<a id="processes-header" href="#processes" class="mdl-layout__tab" (click)="activeProcess()">PROCESSES</a>
|
||||
<a id="report-header" href="#report" class="mdl-layout__tab" (click)="activeReports()">REPORTS</a>
|
||||
<a id="tasks-header" href="#tasks" class="mdl-layout__tab" [class.is-active]="activeTab === 'tasks'" (click)="activeTab = 'tasks'">TASKS</a>
|
||||
<a id="processes-header" href="#processes" class="mdl-layout__tab" [class.is-active]="activeTab === 'processes'" (click)="activeTab = 'processes'">PROCESSES</a>
|
||||
<a id="report-header" href="#report" class="mdl-layout__tab" [class.is-active]="activeTab === 'reports'" (click)="activeTab = 'reports'">REPORTS</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<!-- TASKS COMPONENT -->
|
||||
|
||||
<section class="mdl-layout__tab-panel is-active" id="tasks">
|
||||
<section class="mdl-layout__tab-panel" [class.is-active]="activeTab === 'tasks'" id="tasks">
|
||||
<div class="page-content">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
|
||||
@@ -36,6 +36,7 @@
|
||||
[state]="taskFilter.filter.state"
|
||||
[sort]="taskFilter.filter.sort"
|
||||
[data]="dataTasks"
|
||||
[landingTaskId]="currentTaskId"
|
||||
(rowClick)="onTaskRowClick($event)" (onSuccess)="onSuccessTaskList($event)"
|
||||
#activititasklist></activiti-tasklist>
|
||||
</div>
|
||||
@@ -43,6 +44,7 @@
|
||||
<span><h5>Task Details</h5></span>
|
||||
<hr>
|
||||
<activiti-task-details [taskId]="currentTaskId" (formCompleted)="onFormCompleted($event)"
|
||||
(taskCreated)="onTaskCreated($event)"
|
||||
#activitidetails></activiti-task-details>
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,8 +54,8 @@
|
||||
|
||||
<!-- PROCESS COMPONENT -->
|
||||
|
||||
<section class="mdl-layout__tab-panel" id="processes">
|
||||
<div class="page-content" *ngIf="processTabActivie">
|
||||
<section class="mdl-layout__tab-panel" [class.is-active]="activeTab === 'processes'" id="processes">
|
||||
<div class="page-content" *ngIf="activeTab === 'processes'">
|
||||
<div class="page-content">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
|
||||
@@ -66,7 +68,7 @@
|
||||
(filterClick)="onProcessFilterClick($event)"
|
||||
(onSuccess)="onSuccessProcessFilterList($event)"></activiti-process-instance-filters>
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--3-col task-column list-column mdl-shadow--2dp">
|
||||
<div class="mdl-cell mdl-cell--3-col task-column list-column mdl-shadow--2dp" *ngIf="processFilter && !isStartProcessMode()">
|
||||
<span><h5>Process List</h5></span>
|
||||
<hr>
|
||||
<activiti-process-instance-list *ngIf="processFilter?.hasFilter()" [appId]="processFilter.appId"
|
||||
@@ -78,15 +80,19 @@
|
||||
(rowClick)="onProcessRowClick($event)"
|
||||
(onSuccess)="onSuccessProcessList($event)"></activiti-process-instance-list>
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp" *ngIf="!isStartProcessMode()">
|
||||
<div class="mdl-cell task-column mdl-shadow--2dp" *ngIf="!isStartProcessMode()"
|
||||
[class.mdl-cell--7-col]="processFilter && !isStartProcessMode()"
|
||||
[class.mdl-cell--10-col]="!processFilter || isStartProcessMode()">
|
||||
<span><h5>Process Details</h5></span>
|
||||
<hr>
|
||||
<activiti-process-instance-details [processInstanceId]="currentProcessInstanceId"
|
||||
(activitiprocesslist)="taskFormCompleted()"
|
||||
(processCancelled)="processCancelled()"></activiti-process-instance-details>
|
||||
<activiti-process-instance-details
|
||||
[processInstanceId]="currentProcessInstanceId"
|
||||
(processCancelled)="processCancelled()"
|
||||
(taskClick)="onProcessDetailsTaskClick($event)">
|
||||
</activiti-process-instance-details>
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--7-col task-column" *ngIf="isStartProcessMode()">
|
||||
<span>Start Process</span>
|
||||
<div class="mdl-cell mdl-cell--10-col task-column mdl-shadow--2dp" *ngIf="isStartProcessMode()">
|
||||
<span><h5>Start Process</h5></span>
|
||||
<hr>
|
||||
<activiti-start-process [appId]="appId" (start)="onStartProcessInstance($event)"></activiti-start-process>
|
||||
</div>
|
||||
@@ -98,8 +104,8 @@
|
||||
|
||||
<!-- ANALYTICS COMPONENT -->
|
||||
|
||||
<section class="mdl-layout__tab-panel" id="report">
|
||||
<div class="page-content" *ngIf="reportsTabActivie">
|
||||
<section class="mdl-layout__tab-panel" [class.is-active]="activeTab === 'reports'" id="report">
|
||||
<div class="page-content" *ngIf="activeTab === 'reports'">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--4-col task-column mdl-shadow--2dp">
|
||||
<span><h5>Report List</h5></span>
|
||||
|
||||
@@ -19,15 +19,16 @@ import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular
|
||||
import {
|
||||
ActivitiApps,
|
||||
ActivitiFilters,
|
||||
ActivitiTaskDetails,
|
||||
ActivitiTaskList,
|
||||
FilterRepresentationModel
|
||||
FilterRepresentationModel,
|
||||
TaskDetailsEvent
|
||||
} from 'ng2-activiti-tasklist';
|
||||
import {
|
||||
ActivitiProcessFilters,
|
||||
ActivitiProcessInstanceDetails,
|
||||
ActivitiProcessInstanceListComponent,
|
||||
ActivitiStartProcessInstance,
|
||||
FilterProcessRepresentationModel,
|
||||
ProcessInstance
|
||||
} from 'ng2-activiti-processlist';
|
||||
import { AnalyticsReportListComponent } from 'ng2-activiti-analytics';
|
||||
@@ -35,10 +36,11 @@ import { ActivatedRoute } from '@angular/router';
|
||||
import { Subscription } from 'rxjs/Rx';
|
||||
import {
|
||||
ObjectDataTableAdapter,
|
||||
ObjectDataRow,
|
||||
DataSorting
|
||||
} from 'ng2-alfresco-datatable';
|
||||
import { AlfrescoApiService } from 'ng2-alfresco-core';
|
||||
import { FormRenderingService } from 'ng2-activiti-form';
|
||||
import { FormService, FormRenderingService, FormEvent, FormFieldEvent } from 'ng2-activiti-form';
|
||||
import { /*CustomEditorComponent*/ CustomStencil01 } from './custom-editor/custom-editor.component';
|
||||
|
||||
declare var componentHandler;
|
||||
@@ -52,18 +54,12 @@ const currentProcessIdNew = '__NEW__';
|
||||
})
|
||||
export class ActivitiDemoComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild(ActivitiApps)
|
||||
activitiapps: ActivitiApps;
|
||||
|
||||
@ViewChild(ActivitiFilters)
|
||||
activitifilter: ActivitiFilters;
|
||||
|
||||
@ViewChild(ActivitiTaskList)
|
||||
activititasklist: ActivitiTaskList;
|
||||
|
||||
@ViewChild(ActivitiTaskDetails)
|
||||
activitidetails: ActivitiTaskDetails;
|
||||
|
||||
@ViewChild(ActivitiProcessFilters)
|
||||
activitiprocessfilter: ActivitiProcessFilters;
|
||||
|
||||
@@ -80,7 +76,7 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
analyticsreportlist: AnalyticsReportListComponent;
|
||||
|
||||
@Input()
|
||||
appId: number;
|
||||
appId: number = null;
|
||||
|
||||
layoutType: string;
|
||||
currentTaskId: string;
|
||||
@@ -89,13 +85,11 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
taskSchemaColumns: any [] = [];
|
||||
processSchemaColumns: any [] = [];
|
||||
|
||||
processTabActivie: boolean = false;
|
||||
|
||||
reportsTabActivie: boolean = false;
|
||||
activeTab: string = 'tasks'; // tasks|processes|reports
|
||||
|
||||
taskFilter: FilterRepresentationModel;
|
||||
report: any;
|
||||
processFilter: FilterRepresentationModel;
|
||||
processFilter: FilterProcessRepresentationModel;
|
||||
|
||||
sub: Subscription;
|
||||
|
||||
@@ -105,7 +99,8 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
constructor(private elementRef: ElementRef,
|
||||
private route: ActivatedRoute,
|
||||
private apiService: AlfrescoApiService,
|
||||
private formRenderingService: FormRenderingService) {
|
||||
private formRenderingService: FormRenderingService,
|
||||
private formService: FormService) {
|
||||
this.dataTasks = new ObjectDataTableAdapter(
|
||||
[],
|
||||
[
|
||||
@@ -122,12 +117,21 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
{type: 'text', key: 'started', title: 'Started', cssClass: 'hidden', sortable: true}
|
||||
]
|
||||
);
|
||||
this.dataProcesses.setSorting(new DataSorting('started', 'desc'));
|
||||
|
||||
// Uncomment this line to replace all 'text' field editors with custom component
|
||||
// formRenderingService.setComponentTypeResolver('text', () => CustomEditorComponent, true);
|
||||
|
||||
// Uncomment this line to map 'custom_stencil_01' to local editor component
|
||||
formRenderingService.setComponentTypeResolver('custom_stencil_01', () => CustomStencil01, true);
|
||||
|
||||
formService.formLoaded.subscribe((e: FormEvent) => {
|
||||
console.log(`Form loaded: ${e.form.id}`);
|
||||
});
|
||||
|
||||
formService.formFieldValueChanged.subscribe((e: FormFieldEvent) => {
|
||||
console.log(`Field value changed. Form: ${e.form.id}, Field: ${e.field.id}, Value: ${e.field.value}`);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -150,7 +154,9 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
}
|
||||
|
||||
onTaskFilterClick(event: FilterRepresentationModel) {
|
||||
this.taskFilter = event;
|
||||
if(event){
|
||||
this.taskFilter = event;
|
||||
}
|
||||
}
|
||||
|
||||
onReportClick(event: any) {
|
||||
@@ -171,11 +177,12 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
this.currentTaskId = this.activititasklist.getCurrentId();
|
||||
}
|
||||
|
||||
onProcessFilterClick(event: FilterRepresentationModel) {
|
||||
onProcessFilterClick(event: FilterProcessRepresentationModel) {
|
||||
this.currentProcessInstanceId = null;
|
||||
this.processFilter = event;
|
||||
}
|
||||
|
||||
onSuccessProcessFilterList(event: any) {
|
||||
onSuccessProcessFilterList() {
|
||||
this.processFilter = this.activitiprocessfilter.getCurrentFilter();
|
||||
}
|
||||
|
||||
@@ -196,13 +203,15 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
}
|
||||
|
||||
navigateStartProcess() {
|
||||
this.resetProcessFilters();
|
||||
this.reloadProcessFilters();
|
||||
this.currentProcessInstanceId = currentProcessIdNew;
|
||||
}
|
||||
|
||||
onStartProcessInstance(instance: ProcessInstance) {
|
||||
this.currentProcessInstanceId = instance.id;
|
||||
this.activitiStartProcess.reset();
|
||||
this.activitiprocesslist.reload();
|
||||
this.resetProcessFilters();
|
||||
}
|
||||
|
||||
isStartProcessMode() {
|
||||
@@ -218,15 +227,16 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
this.activitiprocesslist.reload();
|
||||
}
|
||||
|
||||
taskFormCompleted(data: any) {
|
||||
this.activitiprocesslist.reload();
|
||||
}
|
||||
|
||||
onFormCompleted(form) {
|
||||
this.activititasklist.reload();
|
||||
this.currentTaskId = null;
|
||||
}
|
||||
|
||||
onTaskCreated(data: any) {
|
||||
this.currentTaskId = data.parentTaskId;
|
||||
this.activititasklist.reload();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
@@ -236,14 +246,6 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
this.loadStencilScriptsInPageFromActiviti();
|
||||
}
|
||||
|
||||
activeProcess() {
|
||||
this.processTabActivie = true;
|
||||
}
|
||||
|
||||
activeReports() {
|
||||
this.reportsTabActivie = true;
|
||||
}
|
||||
|
||||
loadStencilScriptsInPageFromActiviti() {
|
||||
this.apiService.getInstance().activiti.scriptFileApi.getControllers().then(response => {
|
||||
if (response) {
|
||||
@@ -255,4 +257,26 @@ export class ActivitiDemoComponent implements AfterViewInit {
|
||||
});
|
||||
}
|
||||
|
||||
onProcessDetailsTaskClick(event: TaskDetailsEvent) {
|
||||
event.preventDefault();
|
||||
this.activeTab = 'tasks';
|
||||
let processTaskDataRow = new ObjectDataRow({
|
||||
id: event.value.id,
|
||||
name: event.value.name || 'No name',
|
||||
created: event.value.created
|
||||
});
|
||||
this.activitifilter.selectFilter(null);
|
||||
this.dataTasks.setRows([processTaskDataRow]);
|
||||
this.activititasklist.selectTask(event.value.id);
|
||||
this.currentTaskId = event.value.id;
|
||||
}
|
||||
|
||||
private resetProcessFilters() {
|
||||
this.processFilter = null;
|
||||
}
|
||||
|
||||
private reloadProcessFilters() {
|
||||
this.activitiprocessfilter.selectFilter(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<div class="container">
|
||||
<alfresco-upload-drag-area
|
||||
[rootFolderId]="uploadRootFolderId"
|
||||
[currentFolderPath]="uploadFolderPath"
|
||||
[rootFolderId]="documentList.currentFolderId"
|
||||
[versioning] = "versioning"
|
||||
(onSuccess)="documentList.reload()">
|
||||
<alfresco-document-list-breadcrumb
|
||||
[currentFolderPath]="currentPath"
|
||||
(pathChanged)="onBreadcrumbPathChanged($event)" *ngIf="!currentFolderId">
|
||||
[target]="documentList"
|
||||
[folderNode]="documentList.folderNode">
|
||||
</alfresco-document-list-breadcrumb>
|
||||
<div *ngIf="errorMessage" class="error-message">
|
||||
<button (click)="resetError()" class="mdl-button mdl-js-button mdl-button--icon">
|
||||
@@ -16,22 +15,12 @@
|
||||
</div>
|
||||
<alfresco-document-list
|
||||
#documentList
|
||||
[rootFolderId]="rootFolderId"
|
||||
[currentFolderPath]="currentPath"
|
||||
[currentFolderId]="currentFolderId"
|
||||
[contextMenuActions]="true"
|
||||
[contentActions]="true"
|
||||
(error)="onNavigationError($event)"
|
||||
(success)="resetError()"
|
||||
(preview)="showFile($event)"
|
||||
(folderChange)="onFolderChanged($event)">
|
||||
<!--
|
||||
<empty-folder-content>
|
||||
<template>
|
||||
<h1>Sorry, no content here</h1>
|
||||
</template>
|
||||
</empty-folder-content>
|
||||
-->
|
||||
(preview)="showFile($event)">
|
||||
<content-columns>
|
||||
<content-column key="$thumbnail" type="image"></content-column>
|
||||
<content-column
|
||||
@@ -39,13 +28,13 @@
|
||||
key="name"
|
||||
sortable="true"
|
||||
class="full-width ellipsis-cell">
|
||||
<!-- Example of using custom column template -->
|
||||
<!--
|
||||
<template let-entry="$implicit">
|
||||
<span>Hi! {{entry.data.getValue(entry.row, entry.col)}}</span>
|
||||
</template>
|
||||
-->
|
||||
</content-column>
|
||||
<!--
|
||||
<content-column
|
||||
title="Type"
|
||||
source="content.mimeType">
|
||||
</content-column>
|
||||
-->
|
||||
<content-column
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||
key="createdByUser.displayName"
|
||||
@@ -107,43 +96,11 @@
|
||||
</content-action>
|
||||
</content-actions>
|
||||
</alfresco-document-list>
|
||||
<alfresco-pagination
|
||||
[provider]="documentList.data"
|
||||
[supportedPageSizes]="[5, 10, 15, 20]">
|
||||
</alfresco-pagination>
|
||||
</alfresco-upload-drag-area>
|
||||
</div>
|
||||
|
||||
<context-menu-holder></context-menu-holder>
|
||||
|
||||
<div class="p-10">
|
||||
<ul>
|
||||
<li>Current path: {{currentPath}}</li>
|
||||
<li>
|
||||
<button (click)="currentPath = '/'">Go to root</button>
|
||||
</li>
|
||||
<li>
|
||||
<button (click)="currentPath = '/Sites'">Go to Sites</button>
|
||||
</li>
|
||||
<li>
|
||||
<button (click)="currentPath = '/Sites/swsdp';">Go to Web Site Design Project site</button>
|
||||
</li>
|
||||
<li>
|
||||
<button (click)="currentPath = '/Sites/swsdp/documentLibrary';">Go to Document Library</button>
|
||||
</li>
|
||||
<li>
|
||||
<button (click)="currentPath = '/Sites/swsdp/documentLibrary/Agency Files/Contracts'">Go to Agency Contracts</button>
|
||||
</li>
|
||||
<li>
|
||||
<button (click)="currentPath = '!@£$%^&*()'">Go to the wrong path</button>
|
||||
</li>
|
||||
<li>
|
||||
<button (click)="fileDialog.toggleShowDialog()">Show/Hide File Dialog</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<p style="width:250px;margin: 20px;">
|
||||
<label for="switch-multiple-file" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input type="checkbox" id="switch-multiple-file" class="mdl-switch__input" (change)="toggleMultipleFileUpload()" >
|
||||
@@ -183,8 +140,7 @@
|
||||
</div>
|
||||
<div *ngIf="!acceptedFilesTypeShow">
|
||||
<alfresco-upload-button data-automation-id="multiple-file-upload"
|
||||
[rootFolderId]="uploadRootFolderId"
|
||||
[currentFolderPath]="uploadFolderPath"
|
||||
[rootFolderId]="documentList.currentFolderId"
|
||||
[multipleFiles]="multipleFileUpload"
|
||||
[uploadFolders]="folderUpload"
|
||||
[versioning] = "versioning"
|
||||
@@ -194,9 +150,8 @@
|
||||
</div>
|
||||
<div *ngIf="acceptedFilesTypeShow">
|
||||
<alfresco-upload-button data-automation-id="multiple-file-upload"
|
||||
[rootFolderId]="uploadRootFolderId"
|
||||
[currentFolderPath]="uploadFolderPath"
|
||||
acceptedFilesType="{{acceptedFilesType}}"
|
||||
[rootFolderId]="documentList.currentFolderId"
|
||||
[acceptedFilesType]="acceptedFilesType"
|
||||
[multipleFiles]="multipleFileUpload"
|
||||
[uploadFolders]="folderUpload"
|
||||
[versioning] = "versioning"
|
||||
|
||||
@@ -15,16 +15,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, OnInit, Optional, ViewChild } from '@angular/core';
|
||||
import { Component, OnInit, Optional, ViewChild, ChangeDetectorRef } from '@angular/core';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||
import {
|
||||
DocumentActionsService,
|
||||
DocumentList,
|
||||
ContentActionHandler,
|
||||
DocumentActionModel,
|
||||
FolderActionModel
|
||||
} from 'ng2-alfresco-documentlist';
|
||||
import { AlfrescoAuthenticationService, LogService } from 'ng2-alfresco-core';
|
||||
import { DocumentActionsService, DocumentListComponent, ContentActionHandler, DocumentActionModel, FolderActionModel } from 'ng2-alfresco-documentlist';
|
||||
import { FormService } from 'ng2-activiti-form';
|
||||
|
||||
@Component({
|
||||
@@ -33,9 +27,8 @@ import { FormService } from 'ng2-activiti-form';
|
||||
styleUrls: ['./files.component.css']
|
||||
})
|
||||
export class FilesComponent implements OnInit {
|
||||
currentPath: string = '/Sites/swsdp/documentLibrary';
|
||||
rootFolderId: string = '-root-';
|
||||
currentFolderId: string = null;
|
||||
// The identifier of a node. You can also use one of these well-known aliases: -my- | -shared- | -root-
|
||||
currentFolderId: string = '-my-';
|
||||
|
||||
errorMessage: string = null;
|
||||
fileNodeId: any;
|
||||
@@ -44,23 +37,16 @@ export class FilesComponent implements OnInit {
|
||||
folderUpload: boolean = false;
|
||||
acceptedFilesTypeShow: boolean = false;
|
||||
versioning: boolean = false;
|
||||
|
||||
acceptedFilesType: string = '.jpg,.pdf,.js';
|
||||
|
||||
get uploadRootFolderId(): string {
|
||||
return this.currentFolderId || this.rootFolderId;
|
||||
}
|
||||
|
||||
get uploadFolderPath(): string {
|
||||
return this.currentFolderId ? '/' : this.currentPath;
|
||||
}
|
||||
|
||||
@ViewChild(DocumentList)
|
||||
documentList: DocumentList;
|
||||
@ViewChild(DocumentListComponent)
|
||||
documentList: DocumentListComponent;
|
||||
|
||||
constructor(private documentActions: DocumentActionsService,
|
||||
public auth: AlfrescoAuthenticationService,
|
||||
private authService: AlfrescoAuthenticationService,
|
||||
private formService: FormService,
|
||||
private logService: LogService,
|
||||
private changeDetector: ChangeDetectorRef,
|
||||
private router: Router,
|
||||
@Optional() private route: ActivatedRoute) {
|
||||
documentActions.setHandler('my-handler', this.myDocumentActionHandler.bind(this));
|
||||
@@ -87,18 +73,6 @@ export class FilesComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
onFolderChanged(event?: any) {
|
||||
if (event) {
|
||||
this.currentPath = event.path;
|
||||
}
|
||||
}
|
||||
|
||||
onBreadcrumbPathChanged(event?: any) {
|
||||
if (event) {
|
||||
this.currentPath = event.value;
|
||||
}
|
||||
}
|
||||
|
||||
toggleMultipleFileUpload() {
|
||||
this.multipleFileUpload = !this.multipleFileUpload;
|
||||
return this.multipleFileUpload;
|
||||
@@ -123,16 +97,19 @@ export class FilesComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
if (this.route) {
|
||||
this.route.params.forEach((params: Params) => {
|
||||
this.currentFolderId = params.hasOwnProperty('id') ? params['id'] : null;
|
||||
if (params['id']) {
|
||||
this.currentFolderId = params['id'];
|
||||
this.changeDetector.detectChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.auth.isBpmLoggedIn()) {
|
||||
if (this.authService.isBpmLoggedIn()) {
|
||||
this.formService.getProcessDefinitions().subscribe(
|
||||
defs => this.setupBpmActions(defs || []),
|
||||
err => console.log(err)
|
||||
err => this.logService.error(err)
|
||||
);
|
||||
} else {
|
||||
console.log('You are not logged in');
|
||||
this.logService.warn('You are not logged in to BPM');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Demonstrates multiple Alfresco ECM components used together to show the files of you ECM instance :
|
||||
Demonstrates multiple Alfresco ECM components used together to display the files of your ECM instance:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
|
||||
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
|
||||
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -43,11 +43,11 @@
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Demonstrates multiple Alfresco BPM components used together to show your BPM prorcess and tasks:
|
||||
Demonstrates multiple Alfresco BPM components used together to show your BPM process and tasks:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
|
||||
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
|
||||
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -99,7 +99,7 @@
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
|
||||
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
|
||||
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -119,7 +119,7 @@
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
|
||||
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
|
||||
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -139,7 +139,7 @@
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
|
||||
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
|
||||
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -155,11 +155,11 @@
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Shows and create webscripts in your ECM instance:
|
||||
Displays and creates webscripts in your ECM instance:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
<span class="home--feature-list__text">Comunication with the Rest Api and core services</span>
|
||||
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
|
||||
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -175,11 +175,11 @@
|
||||
</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
Shows and add tags to the node of your ECM instance:
|
||||
Displays and adds tags to the node of your ECM instance:
|
||||
<ul class="home--feature-list">
|
||||
<li>
|
||||
<i class="material-icons home--feature-list__icon">brightness_1</i>
|
||||
<span class="home--feature-list__text">Comunication with Rest</span>
|
||||
<span class="home--feature-list__text">Communication with Rest</span>
|
||||
<a href="https://www.npmjs.com/package/ng2-alfresco-core" target="_blank">ng2-alfresco-core</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
import { Component, ViewChild, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Validators } from '@angular/forms';
|
||||
import { StorageService } from 'ng2-alfresco-core';
|
||||
import { StorageService, LogService } from 'ng2-alfresco-core';
|
||||
|
||||
@Component({
|
||||
selector: 'login-demo',
|
||||
@@ -37,17 +37,20 @@ export class LoginDemoComponent implements OnInit {
|
||||
disableCsrf: boolean = false;
|
||||
isECM: boolean = true;
|
||||
isBPM: boolean = false;
|
||||
customMinLenght: number = 2;
|
||||
|
||||
constructor(public router: Router, private storage: StorageService) {
|
||||
constructor(private router: Router,
|
||||
private storage: StorageService,
|
||||
private logService: LogService) {
|
||||
this.customValidation = {
|
||||
username: ['', Validators.compose([Validators.required, Validators.minLength(4)])],
|
||||
username: ['', Validators.compose([Validators.required, Validators.minLength(this.customMinLenght)])],
|
||||
password: ['', Validators.required]
|
||||
};
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.alfrescologin.addCustomValidationError('username', 'required', 'LOGIN.MESSAGES.USERNAME-REQUIRED');
|
||||
this.alfrescologin.addCustomValidationError('username', 'minlength', 'LOGIN.MESSAGES.USERNAME-MIN');
|
||||
this.alfrescologin.addCustomValidationError('username', 'minlength', 'LOGIN.MESSAGES.USERNAME-MIN', {customMinLenght: this.customMinLenght});
|
||||
this.alfrescologin.addCustomValidationError('password', 'required', 'LOGIN.MESSAGES.PASSWORD-REQUIRED');
|
||||
|
||||
if (this.storage.hasItem('providers')) {
|
||||
@@ -75,7 +78,7 @@ export class LoginDemoComponent implements OnInit {
|
||||
}
|
||||
|
||||
onError($event) {
|
||||
console.log($event);
|
||||
this.logService.error($event);
|
||||
}
|
||||
|
||||
toggleECM() {
|
||||
@@ -92,7 +95,7 @@ export class LoginDemoComponent implements OnInit {
|
||||
this.disableCsrf = !this.disableCsrf;
|
||||
}
|
||||
|
||||
updateProvider(){
|
||||
updateProvider() {
|
||||
if (this.isBPM && this.isECM) {
|
||||
this.providers = 'ALL';
|
||||
return this.providers;
|
||||
|
||||
@@ -34,11 +34,11 @@ export class SearchBarComponent {
|
||||
expand = new EventEmitter();
|
||||
|
||||
constructor(public router: Router,
|
||||
public auth: AlfrescoAuthenticationService) {
|
||||
public authService: AlfrescoAuthenticationService) {
|
||||
}
|
||||
|
||||
isLoggedIn(): boolean {
|
||||
return this.auth.isLoggedIn();
|
||||
return this.authService.isLoggedIn();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<div class="search-results-container">
|
||||
<h1>Search results</h1>
|
||||
<alfresco-search (navigate)="onNavigateItem($event)"></alfresco-search>
|
||||
<alfresco-search (preview)="showFile($event)"></alfresco-search>
|
||||
</div>
|
||||
|
||||
<alfresco-viewer *ngIf="fileShowed" [(showViewer)]="fileShowed" [fileNodeId]="fileNodeId" [overlayMode]="true">
|
||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||
</alfresco-viewer>
|
||||
<div *ngIf="fileShowed">
|
||||
<alfresco-viewer [(showViewer)]="fileShowed"
|
||||
[fileNodeId]="fileNodeId"
|
||||
[overlayMode]="true">
|
||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||
</alfresco-viewer>
|
||||
</div>
|
||||
|
||||
@@ -47,18 +47,18 @@ import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||
})
|
||||
export class SearchComponent {
|
||||
|
||||
fileShowed: boolean = false;
|
||||
fileNodeId: string;
|
||||
fileShowed: boolean = false;
|
||||
|
||||
constructor(public router: Router) {
|
||||
}
|
||||
|
||||
onNavigateItem(event: MinimalNodeEntity) {
|
||||
if (event.entry.isFile) {
|
||||
this.fileNodeId = event.entry.id;
|
||||
showFile(event) {
|
||||
if (event.value.entry.isFile) {
|
||||
this.fileNodeId = event.value.entry.id;
|
||||
this.fileShowed = true;
|
||||
} else if (event.entry.isFolder) {
|
||||
this.router.navigate(['/files', event.entry.id]);
|
||||
} else {
|
||||
this.fileShowed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { AlfrescoSettingsService, StorageService } from 'ng2-alfresco-core';
|
||||
import { AlfrescoSettingsService, StorageService, LogService } from 'ng2-alfresco-core';
|
||||
|
||||
@Component({
|
||||
selector: 'alfresco-setting-demo',
|
||||
@@ -28,24 +28,31 @@ export class SettingComponent {
|
||||
ecmHost: string;
|
||||
bpmHost: string;
|
||||
|
||||
constructor(public alfrescoSettingsService: AlfrescoSettingsService,
|
||||
private storage: StorageService) {
|
||||
this.ecmHost = this.alfrescoSettingsService.ecmHost;
|
||||
this.bpmHost = this.alfrescoSettingsService.bpmHost;
|
||||
constructor(private settingsService: AlfrescoSettingsService,
|
||||
private storage: StorageService,
|
||||
private logService: LogService) {
|
||||
this.ecmHost = this.settingsService.ecmHost;
|
||||
this.bpmHost = this.settingsService.bpmHost;
|
||||
}
|
||||
|
||||
public onChangeECMHost(event: KeyboardEvent): void {
|
||||
console.log((<HTMLInputElement>event.target).value);
|
||||
this.ecmHost = (<HTMLInputElement>event.target).value;
|
||||
this.alfrescoSettingsService.ecmHost = this.ecmHost;
|
||||
this.storage.setItem(`ecmHost`, this.ecmHost);
|
||||
let value = (<HTMLInputElement>event.target).value.trim();
|
||||
if (value) {
|
||||
this.logService.info(`ECM host: ${value}`);
|
||||
this.ecmHost = value;
|
||||
this.settingsService.ecmHost = value;
|
||||
this.storage.setItem(`ecmHost`, value);
|
||||
}
|
||||
}
|
||||
|
||||
public onChangeBPMHost(event: KeyboardEvent): void {
|
||||
console.log((<HTMLInputElement>event.target).value);
|
||||
this.bpmHost = (<HTMLInputElement>event.target).value;
|
||||
this.alfrescoSettingsService.bpmHost = this.bpmHost;
|
||||
this.storage.setItem(`bpmHost`, this.bpmHost);
|
||||
let value = (<HTMLInputElement>event.target).value.trim();
|
||||
if (value) {
|
||||
this.logService.info(`BPM host: ${value}`);
|
||||
this.bpmHost = value;
|
||||
this.settingsService.bpmHost = value;
|
||||
this.storage.setItem(`bpmHost`, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,42 +16,41 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
|
||||
@Component({
|
||||
selector: 'alfresco-webscript-demo',
|
||||
template: `
|
||||
|
||||
<label for="script-path"><b>Insert a scriptPath</b></label><br>
|
||||
<input id="script-path" type="text" size="48" [(ngModel)]="scriptPath"><br>
|
||||
<label for="context-root"><b>Insert a contextRoot</b></label><br>
|
||||
<input id="context-root" type="text" size="48" [(ngModel)]="contextRoot"><br>
|
||||
<label for="service-path"><b>Insert a servicePath</b></label><br>
|
||||
<input id="service-path" type="text" size="48" [(ngModel)]="servicePath"><br>
|
||||
<alfresco-webscript-get [scriptPath]="scriptPath"
|
||||
[scriptArgs]="scriptArgs"
|
||||
[contextRoot]="contextRoot"
|
||||
[servicePath]="servicePath"
|
||||
[contentType]="'HTML'"
|
||||
(onSuccess)= "logData($event)"></alfresco-webscript-get>
|
||||
<label for="script-path"><b>Insert a scriptPath</b></label><br>
|
||||
<input id="script-path" type="text" size="48" [(ngModel)]="scriptPath"><br>
|
||||
<label for="context-root"><b>Insert a contextRoot</b></label><br>
|
||||
<input id="context-root" type="text" size="48" [(ngModel)]="contextRoot"><br>
|
||||
<label for="service-path"><b>Insert a servicePath</b></label><br>
|
||||
<input id="service-path" type="text" size="48" [(ngModel)]="servicePath"><br>
|
||||
<alfresco-webscript-get
|
||||
[scriptPath]="scriptPath"
|
||||
[scriptArgs]="scriptArgs"
|
||||
[contextRoot]="contextRoot"
|
||||
[servicePath]="servicePath"
|
||||
[contentType]="'HTML'"
|
||||
(onSuccess)= "logData($event)">
|
||||
</alfresco-webscript-get>
|
||||
`
|
||||
})
|
||||
export class WebscriptComponent {
|
||||
|
||||
currentPath: string = '/';
|
||||
|
||||
authenticated: boolean;
|
||||
|
||||
host: string = 'http://127.0.0.1:8080';
|
||||
|
||||
scriptPath: string = 'sample/folder/Company%20Home';
|
||||
|
||||
contextRoot: string = 'alfresco';
|
||||
|
||||
servicePath: string = 'service';
|
||||
|
||||
scriptArgs: string = '';
|
||||
|
||||
constructor(private logService: LogService) {
|
||||
}
|
||||
|
||||
logData(data) {
|
||||
console.log(data);
|
||||
this.logService.log(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,13 @@ import 'dialog-polyfill/dialog-polyfill.css';
|
||||
|
||||
// Flags
|
||||
import 'flag-icon-css/css/flag-icon.min.css';
|
||||
|
||||
import '../public/css/app.css';
|
||||
import '../public/css/muli-font.css';
|
||||
|
||||
// Load the Angular Material 2 stylesheet
|
||||
import '@angular/material/core/theming/prebuilt/deeppurple-amber.css'
|
||||
|
||||
import 'ng2-activiti-form/stencils/runtime.ng1';
|
||||
import 'ng2-activiti-form/stencils/runtime.adf';
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ module.exports = webpackMerge(commonConfig, {
|
||||
|
||||
output: {
|
||||
path: helpers.root('dist'),
|
||||
publicPath: 'http://localhost:3000/',
|
||||
filename: '[name].js',
|
||||
chunkFilename: '[id].chunk.js'
|
||||
},
|
||||
@@ -60,6 +59,9 @@ module.exports = webpackMerge(commonConfig, {
|
||||
],
|
||||
|
||||
devServer: {
|
||||
host: '0.0.0.0',
|
||||
port: 3000,
|
||||
inline: true,
|
||||
historyApiFallback: true,
|
||||
stats: 'minimal'
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
var helpers = require('./helpers');
|
||||
var fs = require('fs');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
var glob = require('glob');
|
||||
|
||||
const rootPath = helpers.root('node_modules');
|
||||
@@ -34,12 +33,21 @@ module.exports = {
|
||||
},
|
||||
|
||||
module: {
|
||||
preLoaders: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: [
|
||||
...alfrescoLibs
|
||||
],
|
||||
loader: 'source-map-loader'
|
||||
}
|
||||
],
|
||||
loaders: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
|
||||
},
|
||||
{
|
||||
test: /\.ts$/,
|
||||
loaders: ['awesome-typescript-loader', 'angular2-template-loader', 'systemjs-loader'],
|
||||
exclude: ['node_modules','public']
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: [
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
{
|
||||
"LOGIN": {
|
||||
"LOGO": "Alfresco",
|
||||
"LABEL": {
|
||||
"LOGIN": "Login",
|
||||
"USERNAME": "Username",
|
||||
"PASSWORD": "Password",
|
||||
"REMEMBER": "Remember"
|
||||
},
|
||||
"MESSAGES": {
|
||||
"USERNAME-REQUIRED": "Required",
|
||||
"USERNAME-MIN": "Your username needs to be at least 4 characters.",
|
||||
"PASSWORD-REQUIRED": "Enter your password to sign in",
|
||||
"LOGIN-ERROR-CREDENTIALS": "You have entered an invalid username or password",
|
||||
"LOGIN-ERROR-PROVIDERS": "Providers cannot be undefined",
|
||||
"LOGIN-SUCCESS": "Login successful"
|
||||
},
|
||||
"BUTTON": {
|
||||
"LOGIN": "SIGN IN"
|
||||
},
|
||||
"ACTION": {
|
||||
"HELP": "NEED HELP?",
|
||||
"REGISTER": "REGISTER"
|
||||
"LOGIN": {
|
||||
"LOGO": "Alfresco",
|
||||
"LABEL": {
|
||||
"LOGIN": "Login",
|
||||
"USERNAME": "Username",
|
||||
"PASSWORD": "Password",
|
||||
"REMEMBER": "Remember"
|
||||
},
|
||||
"MESSAGES": {
|
||||
"USERNAME-REQUIRED": "Required",
|
||||
"USERNAME-MIN": "Your username needs to be at least {{customMinLenght}} characters.",
|
||||
"PASSWORD-REQUIRED": "Enter your password to sign in",
|
||||
"LOGIN-ERROR-CREDENTIALS": "You have entered an invalid username or password",
|
||||
"LOGIN-ERROR-PROVIDERS": "Providers cannot be undefined",
|
||||
"LOGIN-SUCCESS": "Login successful",
|
||||
"LOGIN-ERROR-CORS": "CORS exception, check your server configuration",
|
||||
"LOGIN-ERROR-CSRF": "CSRF exception, set [disableCsrf]=\"true\" in alfresco-login component",
|
||||
"LOGIN-ECM-LICENSE": "The ECM is in read-only mode"
|
||||
},
|
||||
"BUTTON": {
|
||||
"LOGIN": "SIGN IN"
|
||||
},
|
||||
"ACTION": {
|
||||
"HELP": "NEED HELP?",
|
||||
"REGISTER": "REGISTER"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
{
|
||||
"LOGIN": {
|
||||
"LABEL": {
|
||||
"LOGIN": "Autenticazione",
|
||||
"USERNAME": "Nome utente",
|
||||
"PASSWORD": "Password",
|
||||
"REMEMBER": "Ricordami"
|
||||
},
|
||||
"MESSAGES": {
|
||||
"USERNAME-REQUIRED": "Campo obbligatorio",
|
||||
"USERNAME-MIN": "Inserire un nome utente di minimo 4 caratteri.",
|
||||
"PASSWORD-REQUIRED": "Campo obbligatorio",
|
||||
"LOGIN-ERROR-CREDENTIALS": "Nome utente o password non validi",
|
||||
"LOGIN-ERROR-PROVIDERS": "Providers non può essere nullo",
|
||||
"LOGIN-SUCCESS": "Login effettuata con successo"
|
||||
},
|
||||
"BUTTON": {
|
||||
"LOGIN": "Accedi"
|
||||
},
|
||||
"ACTION": {
|
||||
"HELP": "BISOGNO DI AIUTO?",
|
||||
"REGISTER": "REGISTRATI"
|
||||
"LOGIN": {
|
||||
"LABEL": {
|
||||
"LOGIN": "Autenticazione",
|
||||
"USERNAME": "Nome utente",
|
||||
"PASSWORD": "Password",
|
||||
"REMEMBER": "Ricordami"
|
||||
},
|
||||
"MESSAGES": {
|
||||
"USERNAME-REQUIRED": "Campo obbligatorio",
|
||||
"USERNAME-MIN": "Inserire un nome utente di minimo 4 caratteri.",
|
||||
"PASSWORD-REQUIRED": "Campo obbligatorio",
|
||||
"LOGIN-ERROR-CREDENTIALS": "Nome utente o password non validi",
|
||||
"LOGIN-ERROR-PROVIDERS": "Providers non può essere nullo",
|
||||
"LOGIN-SUCCESS": "Login effettuata con successo",
|
||||
"LOGIN-ERROR-CORS": "CORS exception, controlla le configurazioni del tuo server",
|
||||
"LOGIN-ERROR-CSRF": "CSRF exception, set [disableCsrf]=\"true\" in alfresco-login component",
|
||||
"LOGIN-ECM-LICENSE": "l'ECM e' in read-only mode"
|
||||
},
|
||||
"BUTTON": {
|
||||
"LOGIN": "Accedi"
|
||||
},
|
||||
"ACTION": {
|
||||
"HELP": "BISOGNO DI AIUTO?",
|
||||
"REGISTER": "REGISTRATI"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
<!-- Polyfill(s) for Safari (pre-10.x) -->
|
||||
<script src=js/Intl.min.js></script>
|
||||
|
||||
<!-- IE/FF -->
|
||||
<script src=js/element.scrollintoviewifneeded-polyfill.js></script>
|
||||
|
||||
<!--[if IE]>
|
||||
<script src=js/shim.min.js></script>
|
||||
<script src=//cdnjs.cloudflare.com/ajax/libs/dom4/1.8.3/dom4.js></script>
|
||||
<script src=js/element.scrollintoviewifneeded-polyfill.js></script>
|
||||
<script src=js/classlist-polyfill.js></script>
|
||||
<script src=js/web-animations.min.js></script>
|
||||
<script src=js/typedarray.js></script>
|
||||
@@ -31,14 +33,31 @@
|
||||
<script src="js/material.min.js"></script>
|
||||
<link href="css/iconfont/material-icons.css" rel="stylesheet">
|
||||
|
||||
|
||||
<style>
|
||||
.main_header_adf .mdl-layout__drawer-button {
|
||||
right: 0 !important;
|
||||
left: initial !important;
|
||||
left: auto;
|
||||
|
||||
.loader-container {
|
||||
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||
display: -webkit-flex; /* NEW - Chrome */
|
||||
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
-webkit-box-flex-direction: row;
|
||||
-moz-box-flex-direction: row;
|
||||
-webkit-flex-direction: row;
|
||||
flex-direction: row;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.loader-item {
|
||||
margin: auto;
|
||||
max-height:100px;
|
||||
max-width:300px;
|
||||
}
|
||||
|
||||
.loader-text{
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<!-- 3. Display the application -->
|
||||
@@ -46,9 +65,14 @@
|
||||
<alfresco-app>
|
||||
<div id="loader-container" class="loader-container">
|
||||
<div class="loader-item">
|
||||
<div id="loader-spin" class="mdl-progress mdl-js-progress mdl-progress__indeterminate"></div>
|
||||
<div id="loader-spin" class="mdl-progress mdl-js-progress mdl-progress__indeterminate is-upgraded"
|
||||
data-upgraded=",MaterialProgress">
|
||||
<div class="progressbar bar bar1" style="width: 0%;"></div>
|
||||
<div class="bufferbar bar bar2" style="width: 100%;"></div>
|
||||
<div class="auxbar bar bar3" style="width: 0%;"></div>
|
||||
</div>
|
||||
<div id="loader-text" class="loader-text">Loading Demo Shell..</div>
|
||||
</div >
|
||||
</div>
|
||||
</div>
|
||||
</alfresco-app>
|
||||
</body>
|
||||
|
||||
+19
-18
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "Alfresco-Angular2-Demo",
|
||||
"description": "Demo shell for Alfresco Angular2 components",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings dist",
|
||||
"start": "npm run server-versions && webpack-dev-server --inline --progress --port 3000 --max_old_space_size=4096 --max_new_space_size=4096",
|
||||
"start": "npm run server-versions && webpack-dev-server --progress --max_old_space_size=4096 --max_new_space_size=4096",
|
||||
"start:dist": "wsrv -s dist/ -p 3000 -a 0.0.0.0",
|
||||
"clean-build": "rimraf 'app/{,**/}**.js' 'app/{,**/}**.js.map' 'app/{,**/}**.d.ts'",
|
||||
"test": "karma start",
|
||||
@@ -62,6 +62,7 @@
|
||||
"@angular/platform-browser-dynamic": "2.2.2",
|
||||
"@angular/router": "3.2.2",
|
||||
"@angular/upgrade": "2.2.2",
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"systemjs": "0.19.27",
|
||||
"core-js": "^2.4.1",
|
||||
"reflect-metadata": "^0.1.8",
|
||||
@@ -73,25 +74,25 @@
|
||||
"pdfjs-dist": "1.5.404",
|
||||
"flag-icon-css": "2.3.0",
|
||||
"moment": "2.15.1",
|
||||
"chart.js": "^2.1.4",
|
||||
"chart.js": "2.3.0",
|
||||
"ng2-charts": "1.1.0",
|
||||
"raphael": "^2.2.6",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"alfresco-js-api": "^1.0.0",
|
||||
"ng2-activiti-analytics": "1.0.0",
|
||||
"ng2-alfresco-core": "1.0.0",
|
||||
"ng2-alfresco-datatable": "1.0.0",
|
||||
"ng2-alfresco-documentlist": "1.0.0",
|
||||
"ng2-alfresco-login": "1.0.0",
|
||||
"ng2-alfresco-search": "1.0.0",
|
||||
"ng2-alfresco-upload": "1.0.0",
|
||||
"ng2-alfresco-viewer": "1.0.0",
|
||||
"ng2-activiti-form": "1.0.0",
|
||||
"ng2-activiti-tasklist": "1.0.0",
|
||||
"ng2-alfresco-userinfo": "1.0.0",
|
||||
"ng2-activiti-processlist": "1.0.0",
|
||||
"ng2-alfresco-webscript": "1.0.0",
|
||||
"ng2-alfresco-tag": "1.0.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-activiti-analytics": "1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-alfresco-datatable": "1.1.0",
|
||||
"ng2-alfresco-documentlist": "1.1.0",
|
||||
"ng2-alfresco-login": "1.1.0",
|
||||
"ng2-alfresco-search": "1.1.0",
|
||||
"ng2-alfresco-upload": "1.1.0",
|
||||
"ng2-alfresco-viewer": "1.1.0",
|
||||
"ng2-activiti-form": "1.1.0",
|
||||
"ng2-activiti-tasklist": "1.1.0",
|
||||
"ng2-alfresco-userinfo": "1.1.0",
|
||||
"ng2-activiti-processlist": "1.1.0",
|
||||
"ng2-alfresco-webscript": "1.1.0",
|
||||
"ng2-alfresco-tag": "1.1.0",
|
||||
"dialog-polyfill": "^0.4.3",
|
||||
"element.scrollintoviewifneeded-polyfill": "^1.0.1"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,6 @@ body, html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.p-10 {
|
||||
padding: 10px;
|
||||
}
|
||||
@@ -13,24 +12,24 @@ body, html {
|
||||
}
|
||||
|
||||
.loader-container {
|
||||
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||
display: -webkit-flex; /* NEW - Chrome */
|
||||
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||
display: -webkit-flex; /* NEW - Chrome */
|
||||
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
-webkit-box-flex-direction: row;
|
||||
-moz-box-flex-direction: row;
|
||||
-webkit-flex-direction: row;
|
||||
flex-direction: row;
|
||||
height:100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.loader-item {
|
||||
margin: auto;
|
||||
max-height:100px;
|
||||
max-width:300px;
|
||||
max-height: 100px;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.loader-text{
|
||||
.loader-text {
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
@@ -39,3 +38,27 @@ body, html {
|
||||
._dialog_overlay {
|
||||
position: static !important;
|
||||
}
|
||||
|
||||
.main_header_adf .mdl-layout__drawer-button {
|
||||
right: 0 !important;
|
||||
left: initial !important;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.mdl-layout__header {
|
||||
color: rgb(255, 255, 255);
|
||||
background-color: rgb(31, 188, 210);
|
||||
}
|
||||
|
||||
.mdl-layout__header .material-icons {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.mdl-layout__header-row .mdl-navigation__link {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.md-simple-snackbar-action {
|
||||
border: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
+2
-2
File diff suppressed because one or more lines are too long
@@ -69,6 +69,9 @@ Follow the 3 steps below:
|
||||
<script src="node_modules/material-design-lite/material.min.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
||||
|
||||
<!-- Load the Angular Material 2 stylesheet -->
|
||||
<link href="node_modules/@angular/material/core/theming/prebuilt/deeppurple-amber.css" rel="stylesheet">
|
||||
|
||||
<!-- Polyfill(s) for Safari (pre-10.x) -->
|
||||
<script src="node_modules/intl/dist/Intl.min.js"></script>
|
||||
<script src="node_modules/intl/locale-data/jsonp/en.js"></script>
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"@angular/http": "2.2.2",
|
||||
"@angular/platform-browser": "2.2.2",
|
||||
"@angular/platform-browser-dynamic": "2.2.2",
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"@angular/router": "3.2.2",
|
||||
"@angular/upgrade": "2.2.2",
|
||||
"core-js": "^2.4.1",
|
||||
@@ -57,10 +58,10 @@
|
||||
"moment": "2.15.1",
|
||||
"raphael": "^2.2.6",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "^1.0.0",
|
||||
"ng2-alfresco-core": "1.0.0",
|
||||
"ng2-activiti-diagrams": "1.0.0",
|
||||
"ng2-activiti-analytics": "^1.0.0"
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-activiti-diagrams": "1.1.0",
|
||||
"ng2-activiti-analytics": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
|
||||
@@ -18,51 +18,49 @@
|
||||
import { NgModule, Component, OnInit } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService, StorageService } from 'ng2-alfresco-core';
|
||||
import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService, StorageService, LogService } from 'ng2-alfresco-core';
|
||||
import { AnalyticsModule } from 'ng2-activiti-analytics';
|
||||
|
||||
@Component({
|
||||
selector: 'alfresco-app-demo',
|
||||
template: `
|
||||
<label for="ticket"><b>Insert a valid ticket:</b></label><br>
|
||||
<input id="ticket" type="text" size="48" (change)="updateTicket()" [(ngModel)]="ticket"><br>
|
||||
<label for="host"><b>Insert the ip of your Activiti instance:</b></label><br>
|
||||
<input id="host" type="text" size="48" (change)="updateHost()" [(ngModel)]="host"><br><br>
|
||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid ticket to perform
|
||||
operations.
|
||||
</div>
|
||||
<hr>
|
||||
<label for="ticket"><b>Insert a valid ticket:</b></label><br>
|
||||
<input id="ticket" type="text" size="48" (change)="updateTicket()" [(ngModel)]="ticket"><br>
|
||||
<label for="host"><b>Insert the ip of your Activiti instance:</b></label><br>
|
||||
<input id="host" type="text" size="48" (change)="updateHost()" [(ngModel)]="host"><br><br>
|
||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid ticket to perform
|
||||
operations.
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<div class="page-content">
|
||||
<label for="appId"><b>Insert the appId:</b></label><br>
|
||||
<input id="appId" size="10" type="text" [(ngModel)]="appId">
|
||||
<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 [appId]="appId" *ngIf="report" [reportId]="report.id"></activiti-analytics>
|
||||
<div class="page-content">
|
||||
<label for="appId"><b>Insert the appId:</b></label><br>
|
||||
<input id="appId" size="10" type="text" [(ngModel)]="appId">
|
||||
<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 [appId]="appId" *ngIf="report" [reportId]="report.id"></activiti-analytics>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
`
|
||||
})
|
||||
|
||||
export class AnalyticsDemoComponent implements OnInit {
|
||||
|
||||
appId: number;
|
||||
|
||||
report: any;
|
||||
|
||||
authenticated: boolean;
|
||||
|
||||
host: string = 'http://localhost:9999';
|
||||
|
||||
ticket: string;
|
||||
|
||||
constructor(private authService: AlfrescoAuthenticationService,
|
||||
private settingsService: AlfrescoSettingsService,
|
||||
private storage: StorageService) {
|
||||
private storage: StorageService,
|
||||
private logService: LogService) {
|
||||
settingsService.bpmHost = this.host;
|
||||
settingsService.setProviders('BPM');
|
||||
|
||||
@@ -91,12 +89,12 @@ export class AnalyticsDemoComponent implements OnInit {
|
||||
login() {
|
||||
this.authService.login('admin', 'admin').subscribe(
|
||||
ticket => {
|
||||
console.log(ticket);
|
||||
this.logService.log(ticket);
|
||||
this.ticket = this.authService.getTicketBpm();
|
||||
this.authenticated = true;
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
this.logService.error(error);
|
||||
this.authenticated = false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import { DiagramsModule } from 'ng2-activiti-diagrams';
|
||||
import { AnalyticsReportListComponent } from './src/components/analytics-report-list.component';
|
||||
import { AnalyticsReportParametersComponent } from './src/components/analytics-report-parameters.component';
|
||||
import { AnalyticsComponent } from './src/components/analytics.component';
|
||||
import { AnalyticsGeneratorComponent } from './src/components/analytics-generator.component';
|
||||
import { AnalyticsReportHeatMapComponent } from './src/components/analytics-report-heat-map.component';
|
||||
import { AnalyticsService } from './src/services/analytics.service';
|
||||
import { CHART_DIRECTIVES } from 'ng2-charts/ng2-charts';
|
||||
@@ -29,6 +30,7 @@ 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-generator.component';
|
||||
export * from './src/components/analytics-report-list.component';
|
||||
export * from './src/components/analytics-report-parameters.component';
|
||||
export * from './src/services/analytics.service';
|
||||
@@ -38,6 +40,7 @@ export const ANALYTICS_DIRECTIVES: any[] = [
|
||||
AnalyticsComponent,
|
||||
AnalyticsReportListComponent,
|
||||
AnalyticsReportParametersComponent,
|
||||
AnalyticsGeneratorComponent,
|
||||
AnalyticsReportHeatMapComponent,
|
||||
WIDGET_DIRECTIVES
|
||||
];
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
// Tun on full stack traces in errors to help debugging
|
||||
Error.stackTraceLimit = Infinity;
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
|
||||
|
||||
window.componentHandler = {
|
||||
upgradeAllRegistered: function () {
|
||||
},
|
||||
upgradeElement: function () {
|
||||
}
|
||||
};
|
||||
|
||||
__karma__.loaded = function() {};
|
||||
|
||||
@@ -39,6 +46,8 @@ var map = {
|
||||
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
|
||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||
'@angular/material': 'npm:@angular/material/bundles/material.umd.js',
|
||||
|
||||
// testing
|
||||
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
|
||||
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "ng2-activiti-analytics",
|
||||
"description": "Activiti Angular2 Analytics Component",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
"clean-build": "rimraf index.js index.js.map index.d.ts'src/{,**/}**.js' 'src/{,**/}**.js.map' 'src/{,**/}**.d.ts' bundles",
|
||||
"build": "npm run clean-build && npm run tslint && rimraf dist && tsc && license-check && npm run build.umd",
|
||||
"build:w": "npm run clean-build && npm run tslint && rimraf dist && tsc:w && license-check npm run build.umd",
|
||||
"build:w": "npm run clean-build && npm run tslint && rimraf dist && npm run tsc:w && license-check && npm run build.umd",
|
||||
"tslint": "tslint -c tslint.json 'src/{,**/}**.ts' 'index.ts' -e '{,**/}**.d.ts' -e './gulpfile.ts'",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
@@ -16,7 +16,7 @@
|
||||
"test-browser": "npm run build && concurrently \"karma start karma.conf.js --reporters kjhtml\" \"npm run watch-task\"",
|
||||
"posttest": "remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html && remap-istanbul -i coverage/report/coverage-final.json -o coverage/report/coverage-final.json",
|
||||
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
||||
"prepublish": "npm run build",
|
||||
"prepublish": "npm run test",
|
||||
"travis": "npm link ng2-alfresco-core ng2-activiti-diagrams",
|
||||
"gulp": "gulp",
|
||||
"build.umd": "gulp build.prod --color --env-config prod --build-type prod",
|
||||
@@ -51,24 +51,26 @@
|
||||
"@angular/http": "2.0.0",
|
||||
"@angular/platform-browser": "2.0.0",
|
||||
"@angular/platform-browser-dynamic": "2.0.0",
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"core-js": "^2.4.1",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
"rxjs": "5.0.0-beta.12",
|
||||
"systemjs": "0.19.27",
|
||||
"zone.js": "^0.6.23",
|
||||
"chart.js": "^2.1.4",
|
||||
"chart.js": "2.3.0",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-charts": "1.1.0",
|
||||
"moment": "2.15.1",
|
||||
"raphael": "^2.2.6",
|
||||
"alfresco-js-api": "^1.0.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"ng2-alfresco-core": "1.0.0",
|
||||
"ng2-activiti-diagrams": "1.0.0"
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-activiti-diagrams": "1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "1.3.1",
|
||||
"cssnano": "^3.8.1",
|
||||
@@ -87,6 +89,7 @@
|
||||
"gulp-template": "^4.0.0",
|
||||
"gulp-typescript": "^3.1.3",
|
||||
"gulp-uglify": "^2.0.0",
|
||||
"gulp-util": "^3.0.7",
|
||||
"intl": "^1.2.5",
|
||||
"jasmine-core": "2.4.1",
|
||||
"karma": "0.13.22",
|
||||
@@ -97,6 +100,7 @@
|
||||
"karma-jasmine-html-reporter": "0.2.0",
|
||||
"karma-mocha-reporter": "2.0.3",
|
||||
"license-check": "1.1.5",
|
||||
"merge-stream": "^1.0.1",
|
||||
"remap-istanbul": "0.6.3",
|
||||
"rimraf": "2.5.2",
|
||||
"run-sequence": "^1.2.2",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.chart {display: block; width: 100%;}
|
||||
|
||||
.analytics-row__entry {
|
||||
cursor: pointer;
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
<div *ngIf="reports">
|
||||
<div *ngFor="let report of reports">
|
||||
<h4>{{report.title}}</h4>
|
||||
<div [ngSwitch]="report.type">
|
||||
<div *ngSwitchCase="'pie'">
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="!report.hasData()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div *ngIf="report.hasData()">
|
||||
<div *ngIf="report.hasZeroValues()">{{'ANALYTICS.MESSAGES.ZERO-DATA-FOUND' | translate}}</div>
|
||||
<base-chart *ngIf="!report.hasZeroValues()" class="chart"
|
||||
[data]="report.data"
|
||||
[labels]="report.labels"
|
||||
[chartType]="report.type"></base-chart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'table'">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div [attr.id]="'chart-table-' + report.id" *ngIf="report.hasDatasets()">
|
||||
<table class="table table-responsive table-condensed" 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>
|
||||
<div *ngSwitchCase="'masterDetailTable'">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div [attr.id]="'chart-master-detail-table-' + report.id" *ngIf="report.hasDatasets()">
|
||||
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||
<tr>
|
||||
<th *ngFor="let label of report.labels">{{label | translate}}</th>
|
||||
</tr>
|
||||
<tr *ngFor="let rows of report.datasets" class="analytics-row__entry" style="text-align: center;">
|
||||
<td *ngFor="let row of rows" (click)="toggleDetailsTable()">{{row | translate }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div [attr.id]="'chart-master-detail-' + report.id" *ngIf="isShowDetails()">
|
||||
<table class="table table-responsive table-condensed" style="width: 100%">
|
||||
<tr>
|
||||
<th *ngFor="let label of report.detailsTable.labels">{{label | translate}}</th>
|
||||
</tr>
|
||||
<tr *ngFor="let rows of report.detailsTable.datasets" style="text-align: center;">
|
||||
<td *ngFor="let row of rows">{{row | translate }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'bar'">
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<base-chart *ngIf="report.hasDatasets()" class="chart"
|
||||
[datasets]="report.datasets"
|
||||
[labels]="report.labels"
|
||||
[options]="report.options"
|
||||
[chartType]="report.type"></base-chart>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'multiBar'">
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div *ngIf="report.hasDatasets()">
|
||||
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" [attr.for]="'stacked-id'">
|
||||
<input type="checkbox" [attr.id]="'stacked-id'" class="mdl-checkbox__input"
|
||||
[checked]="report.options.scales.xAxes[0].stacked"
|
||||
[(ngModel)]="report.options.scales.xAxes[0].stacked"
|
||||
(change)="refresh(report)">
|
||||
<span class="mdl-checkbox__label">Stacked</span>
|
||||
</label>
|
||||
<base-chart class="chart"
|
||||
[datasets]="report.datasets"
|
||||
[labels]="report.labels"
|
||||
[options]="report.options"
|
||||
[chartType]="'bar'"></base-chart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'HeatMap'">
|
||||
<analytics-report-heat-map [report]="report"></analytics-report-heat-map>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{report.type}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br><br><br>
|
||||
<div *ngIf="!reports">{{'ANALYTICS.MESSAGES.FILL-PARAMETER' | translate}}</div>
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
/*!
|
||||
* @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 { DebugElement } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { CHART_DIRECTIVES } from 'ng2-charts/ng2-charts';
|
||||
import { CoreModule, AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
import { DiagramsModule } from 'ng2-activiti-diagrams';
|
||||
|
||||
import { AnalyticsReportListComponent } from '../components/analytics-report-list.component';
|
||||
import { AnalyticsGeneratorComponent } from '../components/analytics-generator.component';
|
||||
import { AnalyticsReportParametersComponent } from '../components/analytics-report-parameters.component';
|
||||
import { AnalyticsReportHeatMapComponent } from '../components/analytics-report-heat-map.component';
|
||||
import { WIDGET_DIRECTIVES } from '../components/widgets/index';
|
||||
import { Chart } from '../models/chart.model';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { ReportQuery } from '../models/report.model';
|
||||
import * as analyticMock from '../assets/analyticsComponent.mock';
|
||||
|
||||
export const ANALYTICS_DIRECTIVES: any[] = [
|
||||
AnalyticsGeneratorComponent,
|
||||
AnalyticsReportParametersComponent,
|
||||
AnalyticsReportListComponent,
|
||||
AnalyticsReportHeatMapComponent,
|
||||
WIDGET_DIRECTIVES
|
||||
];
|
||||
export const ANALYTICS_PROVIDERS: any[] = [
|
||||
AnalyticsService
|
||||
];
|
||||
|
||||
declare let jasmine: any;
|
||||
declare let mdDateTimePicker: any;
|
||||
|
||||
describe('AnalyticsGeneratorComponent', () => {
|
||||
|
||||
let component: any;
|
||||
let fixture: ComponentFixture<AnalyticsGeneratorComponent>;
|
||||
let debug: DebugElement;
|
||||
let element: HTMLElement;
|
||||
|
||||
let componentHandler: any;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule.forRoot(),
|
||||
DiagramsModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
...ANALYTICS_DIRECTIVES,
|
||||
...CHART_DIRECTIVES
|
||||
],
|
||||
providers: [
|
||||
...ANALYTICS_PROVIDERS
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AnalyticsGeneratorComponent);
|
||||
component = fixture.componentInstance;
|
||||
debug = fixture.debugElement;
|
||||
element = fixture.nativeElement;
|
||||
fixture.detectChanges();
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
});
|
||||
|
||||
describe('Rendering tests', () => {
|
||||
beforeEach(() => {
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('Should render the Process definition overview report ', (done) => {
|
||||
component.onSuccess.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(3);
|
||||
|
||||
expect(res[0]).toBeDefined();
|
||||
expect(res[0].type).toEqual('table');
|
||||
expect(res[0].datasets).toBeDefined();
|
||||
expect(res[0].datasets.length).toEqual(4);
|
||||
expect(res[0].datasets[0][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS');
|
||||
expect(res[0].datasets[0][1]).toEqual('9');
|
||||
expect(res[0].datasets[1][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[1][1]).toEqual('41');
|
||||
expect(res[0].datasets[2][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[2][1]).toEqual('3');
|
||||
expect(res[0].datasets[3][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[3][1]).toEqual('38');
|
||||
|
||||
expect(res[1]).toBeDefined();
|
||||
expect(res[1].type).toEqual('pie');
|
||||
|
||||
expect(res[2]).toBeDefined();
|
||||
expect(res[2].type).toEqual('table');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
let reportId = 1001;
|
||||
let reportParamQuery = new ReportQuery({status: 'All'});
|
||||
|
||||
component.generateReport(reportId, reportParamQuery);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticMock.chartProcessDefOverview
|
||||
});
|
||||
});
|
||||
|
||||
it('Should render the Task overview report ', (done) => {
|
||||
component.onSuccess.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(3);
|
||||
|
||||
expect(res[0]).toBeDefined();
|
||||
expect(res[0].type).toEqual('bar');
|
||||
expect(res[0].labels).toBeDefined();
|
||||
expect(res[0].labels.length).toEqual(2);
|
||||
expect(res[0].labels[0]).toEqual('2016-09-30T00:00:00.000+0000');
|
||||
expect(res[0].labels[1]).toEqual('2016-10-04T00:00:00.000+0000');
|
||||
expect(res[0].datasets[0].label).toEqual('series1');
|
||||
expect(res[0].datasets[0].data[0]).toEqual(3);
|
||||
expect(res[0].datasets[0].data[1]).toEqual(1);
|
||||
|
||||
expect(res[1]).toBeDefined();
|
||||
expect(res[1].type).toEqual('masterDetailTable');
|
||||
expect(res[1].datasets).toBeDefined();
|
||||
expect(res[1].datasets.length).toEqual(2);
|
||||
expect(res[1].datasets[0][0]).toEqual('fake 1 user task');
|
||||
expect(res[1].datasets[0][1]).toEqual('1');
|
||||
expect(res[1].datasets[0][2]).toEqual('2.0');
|
||||
expect(res[1].datasets[0][3]).toEqual('3.0');
|
||||
expect(res[1].datasets[0][4]).toEqual('4.0');
|
||||
expect(res[1].datasets[0][5]).toEqual('5.0');
|
||||
expect(res[1].datasets[0][6]).toEqual('6.0');
|
||||
expect(res[1].datasets[1][0]).toEqual('fake 2 user task');
|
||||
expect(res[1].datasets[1][1]).toEqual('1');
|
||||
expect(res[1].datasets[1][2]).toEqual('2.0');
|
||||
expect(res[1].datasets[1][3]).toEqual('3.0');
|
||||
expect(res[1].datasets[1][4]).toEqual('4.0');
|
||||
expect(res[1].datasets[1][5]).toEqual('5.0');
|
||||
expect(res[1].datasets[1][6]).toEqual('6.0');
|
||||
|
||||
expect(res[2]).toBeDefined();
|
||||
expect(res[2].type).toEqual('multiBar');
|
||||
expect(res[2].labels).toBeDefined();
|
||||
expect(res[2].labels.length).toEqual(3);
|
||||
expect(res[2].labels[0]).toEqual(1);
|
||||
expect(res[2].labels[1]).toEqual(2);
|
||||
expect(res[2].labels[2]).toEqual(3);
|
||||
expect(res[2].datasets[0].label).toEqual('averages');
|
||||
expect(res[2].datasets[0].data[0]).toEqual(0);
|
||||
expect(res[2].datasets[0].data[1]).toEqual(5);
|
||||
expect(res[2].datasets[0].data[2]).toEqual(2);
|
||||
expect(res[2].datasets[1].label).toEqual('minima');
|
||||
expect(res[2].datasets[1].data[0]).toEqual(0);
|
||||
expect(res[2].datasets[1].data[1]).toEqual(0);
|
||||
expect(res[2].datasets[1].data[2]).toEqual(0);
|
||||
expect(res[2].datasets[2].label).toEqual('maxima');
|
||||
expect(res[2].datasets[2].data[0]).toEqual(0);
|
||||
expect(res[2].datasets[2].data[1]).toEqual(29);
|
||||
expect(res[2].datasets[2].data[2]).toEqual(29);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
let reportParamQuery = new ReportQuery({status: 'All'});
|
||||
component.reportId = 1;
|
||||
component.generateReport(reportParamQuery);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticMock.chartTaskOverview
|
||||
});
|
||||
});
|
||||
|
||||
it('Should reset the reports when the onChanged is call', () => {
|
||||
component.reports = [ new Chart({id: 'fake', type: 'fake-type'})];
|
||||
component.reportId = 1;
|
||||
component.ngOnChanges();
|
||||
expect(component.reports).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should emit onError event with a 404 response ', (done) => {
|
||||
component.onError.subscribe((err) => {
|
||||
expect(err).toBeDefined();
|
||||
done();
|
||||
});
|
||||
|
||||
let reportParamQuery = new ReportQuery({status: 'All'});
|
||||
component.reportId = 1;
|
||||
component.generateReport(reportParamQuery);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 404,
|
||||
contentType: 'json',
|
||||
responseText: []
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, OnChanges, Input, Output, SimpleChanges } from '@angular/core';
|
||||
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { ReportQuery } from '../models/report.model';
|
||||
import { Chart } from '../models/chart.model';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'activiti-analytics-generator',
|
||||
templateUrl: './analytics-generator.component.html',
|
||||
styleUrls: ['./analytics-generator.component.css']
|
||||
})
|
||||
export class AnalyticsGeneratorComponent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
reportId: number;
|
||||
|
||||
@Input()
|
||||
reportParamQuery: ReportQuery = undefined;
|
||||
|
||||
@Output()
|
||||
onSuccess = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
onError = new EventEmitter();
|
||||
|
||||
reports: Chart[];
|
||||
|
||||
showDetails: boolean = false;
|
||||
|
||||
public barChartOptions: any = {
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
stepSize: 1
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
},
|
||||
stacked: true
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
constructor(private translateService: AlfrescoTranslationService,
|
||||
private analyticsService: AnalyticsService,
|
||||
private logService: LogService) {
|
||||
logService.info('AnalyticsGeneratorComponent');
|
||||
if (translateService) {
|
||||
translateService.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (this.reportId && this.reportParamQuery) {
|
||||
this.generateReport(this.reportId, this.reportParamQuery);
|
||||
} else {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public generateReport(reportId, reportParamQuery) {
|
||||
this.analyticsService.getReportsByParams(reportId, reportParamQuery).subscribe(
|
||||
(res: Chart[]) => {
|
||||
this.reports = res;
|
||||
this.onSuccess.emit(res);
|
||||
},
|
||||
(err: any) => {
|
||||
this.onError.emit(err);
|
||||
this.logService.error(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public reset() {
|
||||
if (this.reports) {
|
||||
this.reports = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public refresh(report): void {
|
||||
/**
|
||||
* (My guess), for Angular to recognize the change in the dataset
|
||||
* it has to change the dataset variable directly,
|
||||
* so one way around it, is to clone the data, change it and then
|
||||
* assign it;
|
||||
*/
|
||||
let clone = JSON.parse(JSON.stringify(report));
|
||||
report.datasets = clone.datasets;
|
||||
}
|
||||
|
||||
toggleDetailsTable() {
|
||||
this.showDetails = !this.showDetails;
|
||||
}
|
||||
|
||||
isShowDetails(): boolean {
|
||||
return this.showDetails;
|
||||
}
|
||||
}
|
||||
+11
-5
@@ -15,17 +15,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { CoreModule, AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
import { DiagramsModule } from 'ng2-activiti-diagrams';
|
||||
import { AnalyticsReportHeatMapComponent } from '../components/analytics-report-heat-map.component';
|
||||
import { WIDGET_DIRECTIVES } from '../components/widgets/index';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('Test ng2-activiti-analytics-report-heat-map', () => {
|
||||
describe('AnalyticsReportHeatMapComponent', () => {
|
||||
|
||||
let componentHandler: any;
|
||||
let component: any;
|
||||
@@ -44,8 +45,8 @@ describe('Test ng2-activiti-analytics-report-heat-map', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule,
|
||||
DiagramsModule
|
||||
CoreModule.forRoot(),
|
||||
DiagramsModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
AnalyticsReportHeatMapComponent,
|
||||
@@ -55,6 +56,11 @@ describe('Test ng2-activiti-analytics-report-heat-map', () => {
|
||||
AnalyticsService
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
+3
-3
@@ -43,11 +43,11 @@ export class AnalyticsReportHeatMapComponent implements OnInit {
|
||||
currentMetricColors: string;
|
||||
metricType: string;
|
||||
|
||||
constructor(private translate: AlfrescoTranslationService,
|
||||
constructor(private translateService: AlfrescoTranslationService,
|
||||
private analyticsService: AnalyticsService,
|
||||
private formBuilder: FormBuilder) {
|
||||
if (translate) {
|
||||
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
|
||||
if (translateService) {
|
||||
translateService.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-5
@@ -15,15 +15,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { CoreModule, AlfrescoTranslationService } 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', () => {
|
||||
describe('AnalyticsReportListComponent', () => {
|
||||
|
||||
let reportList = [
|
||||
{'id': 2002, 'name': 'Fake Test Process definition heat map'},
|
||||
@@ -35,7 +36,7 @@ describe('Test ng2-activiti-analytics Report list', () => {
|
||||
|
||||
let reportSelected = {'id': 2003, 'name': 'Fake Test Process definition overview'};
|
||||
|
||||
let component: any;
|
||||
let component: AnalyticsReportListComponent;
|
||||
let fixture: ComponentFixture<AnalyticsReportListComponent>;
|
||||
let debug: DebugElement;
|
||||
let element: HTMLElement;
|
||||
@@ -43,7 +44,7 @@ describe('Test ng2-activiti-analytics Report list', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
AnalyticsReportListComponent
|
||||
@@ -52,6 +53,10 @@ describe('Test ng2-activiti-analytics Report list', () => {
|
||||
AnalyticsService
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
+5
-7
@@ -16,11 +16,10 @@
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||
import { Observer, Observable } from 'rxjs/Rx';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { ReportParametersModel } from '../models/report.model';
|
||||
import { Observer } from 'rxjs/Observer';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
@@ -46,9 +45,8 @@ export class AnalyticsReportListComponent implements OnInit {
|
||||
|
||||
reports: ReportParametersModel[] = [];
|
||||
|
||||
constructor(private auth: AlfrescoAuthenticationService,
|
||||
private analyticsService: AnalyticsService) {
|
||||
|
||||
constructor(private analyticsService: AnalyticsService,
|
||||
private logService: LogService) {
|
||||
this.report$ = new Observable<ReportParametersModel>(observer => this.reportObserver = observer).share();
|
||||
}
|
||||
|
||||
@@ -85,7 +83,7 @@ export class AnalyticsReportListComponent implements OnInit {
|
||||
},
|
||||
(err: any) => {
|
||||
this.onError.emit(err);
|
||||
console.log(err);
|
||||
this.logService.error(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
+15
@@ -48,3 +48,18 @@
|
||||
.icon-small:hover .material-icons {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.is-hide {
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
transition: height 0.5s;
|
||||
}
|
||||
|
||||
.report-container {
|
||||
border: solid 1px rgb(212, 212, 212);
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
.report-container-setting {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
+78
-70
@@ -1,75 +1,83 @@
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="reportParameters">
|
||||
<form [formGroup]="reportForm" novalidate>
|
||||
<div *ngIf="isEditable">
|
||||
<input
|
||||
type="text"
|
||||
class="mdl-textfield__input large"
|
||||
id="reportName"
|
||||
autofocus
|
||||
data-automation-id="reportName"
|
||||
[value]="reportParameters.name"
|
||||
(input)="reportParameters.name=$event.target.value"
|
||||
(blur)="editTitle($event)"
|
||||
/>
|
||||
</div>
|
||||
<div *ngIf="!isEditable">
|
||||
<span class="icon-small">
|
||||
<i class="material-icons">mode_edit</i>
|
||||
<h4 (click)="editEnable()">{{reportParameters.name}}</h4>
|
||||
</span>
|
||||
</div><hr>
|
||||
<div *ngFor="let field of reportParameters.definition.parameters">
|
||||
<div [ngSwitch]="field.type">
|
||||
<div *ngSwitchCase="'integer'">
|
||||
<br>
|
||||
<number-widget [field]="field" [group]="reportForm.controls.processInstanceGroup" [controllerName]="'slowProcessInstanceInteger'"
|
||||
[required]="true"></number-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'duration'">
|
||||
<br>
|
||||
<duration-widget [field]="field" [group]="reportForm.controls.durationGroup"
|
||||
[controllerName]="'duration'"></duration-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'boolean'">
|
||||
<br>
|
||||
<checkbox-widget [field]="field" [group]="reportForm.controls.typeFilteringGroup"
|
||||
[controllerName]="'typeFiltering'"></checkbox-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'status'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.statusGroup" [controllerName]="'status'"
|
||||
[required]="true"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'processDefinition'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.processDefGroup" [controllerName]="'processDefinitionId'"
|
||||
[required]="true" (fieldChanged)="onProcessDefinitionChanges(field)"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'task'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.taskGroup" [controllerName]="'taskName'"
|
||||
[required]="true"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dateRange'">
|
||||
<br>
|
||||
<date-range-widget [field]="field" [group]="reportForm.controls.dateRange"></date-range-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dateInterval'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.dateIntervalGroup" [controllerName]="'dateRangeInterval'"
|
||||
[required]="true" [showDefaultOption]="false"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{field.type}}</span>
|
||||
<div class="report-container">
|
||||
<a class="mdl-navigation__link setting-button" data-automation-id="settings">
|
||||
<button (click)="toggleParameters()" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
|
||||
<i class="material-icons">settings</i>
|
||||
</button>
|
||||
<span class="report-container-setting">{{'ANALYTICS.MESSAGES.SETTING-TITLE' | translate}}</span>
|
||||
</a>
|
||||
<div class="col-md-6" [class.is-hide]="isParametersHide()" >
|
||||
<div *ngIf="reportParameters">
|
||||
<form [formGroup]="reportForm" novalidate>
|
||||
<div *ngIf="isEditable">
|
||||
<input
|
||||
type="text"
|
||||
class="mdl-textfield__input large"
|
||||
id="reportName"
|
||||
autofocus
|
||||
data-automation-id="reportName"
|
||||
[value]="reportParameters.name"
|
||||
(input)="reportParameters.name=$event.target.value"
|
||||
(blur)="editTitle($event)"
|
||||
/>
|
||||
</div>
|
||||
<div *ngIf="!isEditable">
|
||||
<span class="icon-small">
|
||||
<i class="material-icons">mode_edit</i>
|
||||
<h4 (click)="editEnable()">{{reportParameters.name}}</h4>
|
||||
</span>
|
||||
</div><hr>
|
||||
<div *ngFor="let field of reportParameters.definition.parameters">
|
||||
<div [ngSwitch]="field.type">
|
||||
<div *ngSwitchCase="'integer'">
|
||||
<br>
|
||||
<number-widget [field]="field" [group]="reportForm.controls.processInstanceGroup" [controllerName]="'slowProcessInstanceInteger'"
|
||||
[required]="true"></number-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'duration'">
|
||||
<br>
|
||||
<duration-widget [field]="field" [group]="reportForm.controls.durationGroup"
|
||||
[controllerName]="'duration'"></duration-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'boolean'">
|
||||
<br>
|
||||
<checkbox-widget [field]="field" [group]="reportForm.controls.typeFilteringGroup"
|
||||
[controllerName]="'typeFiltering'"></checkbox-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'status'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.statusGroup" [controllerName]="'status'"
|
||||
[required]="true"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'processDefinition'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.processDefGroup" [controllerName]="'processDefinitionId'"
|
||||
[required]="true" (fieldChanged)="onProcessDefinitionChanges(field)"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'task'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.taskGroup" [controllerName]="'taskName'"
|
||||
[required]="true"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dateRange'">
|
||||
<br>
|
||||
<date-range-widget [field]="field" [group]="reportForm.controls.dateRange"></date-range-widget>
|
||||
</div>
|
||||
<div *ngSwitchCase="'dateInterval'">
|
||||
<br>
|
||||
<dropdown-widget [field]="field" [group]="reportForm.controls.dateIntervalGroup" [controllerName]="'dateRangeInterval'"
|
||||
[required]="true" [showDefaultOption]="false"></dropdown-widget>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{field.type}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="debug">
|
||||
<p>ReportForm valid : {{ reportForm.valid }}</p>
|
||||
<p>ReportForm status : {{ reportForm.errors | json }}</p>
|
||||
<p>ReportForm FormGroup valid : {{reportForm && reportForm.controls.dateRange.valid | json }}</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngIf="debug">
|
||||
<p>ReportForm valid : {{ reportForm.valid }}</p>
|
||||
<p>ReportForm status : {{ reportForm.errors | json }}</p>
|
||||
<p>ReportForm FormGroup valid : {{reportForm && reportForm.controls.dateRange.valid | json }}</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+23
-20
@@ -16,25 +16,23 @@
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import {
|
||||
CoreModule
|
||||
} from 'ng2-alfresco-core';
|
||||
import { DebugElement, SimpleChange } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import * as moment from 'moment';
|
||||
import { CoreModule, AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
|
||||
import { AnalyticsReportParametersComponent } from '../components/analytics-report-parameters.component';
|
||||
import { WIDGET_DIRECTIVES } from '../components/widgets/index';
|
||||
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { ReportParametersModel } from '../models/report.model';
|
||||
import * as moment from 'moment';
|
||||
import { DebugElement, SimpleChange } from '@angular/core';
|
||||
import * as analyticParamsMock from '../assets/analyticsParamsReportComponent.mock';
|
||||
|
||||
declare let jasmine: any;
|
||||
declare let mdDateTimePicker: any;
|
||||
|
||||
describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
|
||||
describe('AnalyticsReportParametersComponent', () => {
|
||||
|
||||
let component: any;
|
||||
let component: AnalyticsReportParametersComponent;
|
||||
let fixture: ComponentFixture<AnalyticsReportParametersComponent>;
|
||||
let debug: DebugElement;
|
||||
let element: HTMLElement;
|
||||
@@ -44,7 +42,7 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
AnalyticsReportParametersComponent,
|
||||
@@ -54,6 +52,15 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
|
||||
AnalyticsService
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -62,10 +69,6 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
|
||||
debug = fixture.debugElement;
|
||||
element = fixture.nativeElement;
|
||||
fixture.detectChanges();
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
});
|
||||
|
||||
describe('Rendering tests', () => {
|
||||
@@ -323,9 +326,9 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
|
||||
responseText: analyticParamsMock.reportDefParamProcessDefOptionsApp
|
||||
});
|
||||
|
||||
let appId = 1;
|
||||
let appId = '1';
|
||||
component.appId = appId;
|
||||
component.reportId = 1;
|
||||
component.reportId = '1';
|
||||
let change = new SimpleChange(null, appId);
|
||||
component.ngOnChanges({ 'appId': change });
|
||||
|
||||
@@ -341,7 +344,7 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
|
||||
expect(res[1].name).toEqual('Fake task name 2');
|
||||
});
|
||||
|
||||
component.reportId = 100;
|
||||
component.reportId = '100';
|
||||
component.reportParameters = new ReportParametersModel(analyticParamsMock.reportDefParamTask);
|
||||
component.onProcessDefinitionChanges(analyticParamsMock.fieldProcessDef);
|
||||
|
||||
@@ -392,10 +395,10 @@ describe('Test ng2-analytics-report-parameters Report Parameters ', () => {
|
||||
responseText: []
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should convert a string in number', () => {
|
||||
let numberConvert = component.convertNumber('2');
|
||||
expect(numberConvert).toEqual(2);
|
||||
it('Should convert a string in number', () => {
|
||||
let numberConvert = component.convertNumber('2');
|
||||
expect(numberConvert).toEqual(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+46
-12
@@ -15,12 +15,29 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, OnInit, OnChanges, Input, Output, SimpleChanges } from '@angular/core';
|
||||
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { ReportParametersModel, ReportQuery, ParameterValueModel, ReportParameterDetailsModel } from '../models/report.model';
|
||||
import {
|
||||
Component,
|
||||
EventEmitter,
|
||||
OnInit,
|
||||
OnChanges,
|
||||
Input,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
OnDestroy,
|
||||
AfterViewChecked
|
||||
} from '@angular/core';
|
||||
import { FormGroup, FormBuilder, FormControl } from '@angular/forms';
|
||||
import * as moment from 'moment';
|
||||
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import {
|
||||
ReportParametersModel,
|
||||
ReportQuery,
|
||||
ParameterValueModel,
|
||||
ReportParameterDetailsModel
|
||||
} from '../models/report.model';
|
||||
|
||||
declare var componentHandler;
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
@@ -28,7 +45,7 @@ import * as moment from 'moment';
|
||||
templateUrl: './analytics-report-parameters.component.html',
|
||||
styleUrls: ['./analytics-report-parameters.component.css']
|
||||
})
|
||||
export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
|
||||
export class AnalyticsReportParametersComponent implements OnInit, OnChanges, OnDestroy, AfterViewChecked {
|
||||
|
||||
public static FORMAT_DATE_ACTIVITI: string = 'YYYY-MM-DD';
|
||||
|
||||
@@ -67,12 +84,14 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
|
||||
private reportParamsSub;
|
||||
private paramOpts;
|
||||
private isEditable: boolean = false;
|
||||
private hideParameters: boolean = true;
|
||||
|
||||
constructor(private translate: AlfrescoTranslationService,
|
||||
constructor(private translateService: AlfrescoTranslationService,
|
||||
private analyticsService: AnalyticsService,
|
||||
private formBuilder: FormBuilder ) {
|
||||
if (translate) {
|
||||
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
|
||||
private formBuilder: FormBuilder,
|
||||
private logService: LogService) {
|
||||
if (translateService) {
|
||||
translateService.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +165,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
|
||||
}
|
||||
},
|
||||
(err: any) => {
|
||||
console.log(err);
|
||||
this.logService.error(err);
|
||||
this.onError.emit(err);
|
||||
}
|
||||
);
|
||||
@@ -160,7 +179,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
|
||||
this.onSuccessParamOpt.emit(opts);
|
||||
},
|
||||
(err: any) => {
|
||||
console.log(err);
|
||||
this.logService.error(err);
|
||||
this.onError.emit(err);
|
||||
}
|
||||
);
|
||||
@@ -231,9 +250,24 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges {
|
||||
this.onEdit.emit(this.reportParameters.name);
|
||||
},
|
||||
(err: any) => {
|
||||
console.log(err);
|
||||
this.logService.error(err);
|
||||
this.onError.emit(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ngAfterViewChecked() {
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (componentHandler) {
|
||||
componentHandler.upgradeAllRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
toggleParameters() {
|
||||
this.hideParameters = !this.hideParameters;
|
||||
}
|
||||
|
||||
isParametersHide() {
|
||||
return this.hideParameters;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1 @@
|
||||
.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;
|
||||
}
|
||||
|
||||
@@ -5,83 +5,8 @@
|
||||
(onEdit)="onEditReport($event)">
|
||||
</analytics-report-parameters>
|
||||
|
||||
<div *ngIf="reports">
|
||||
<div *ngFor="let report of reports">
|
||||
<h4>{{report.title}}</h4>
|
||||
<div [ngSwitch]="report.type">
|
||||
<div *ngSwitchCase="'pie'">
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="!report.hasData()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<base-chart *ngIf="report.hasData()" class="chart"
|
||||
[data]="report.data"
|
||||
[labels]="report.labels"
|
||||
[chartType]="report.type"></base-chart>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'table'">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div [attr.id]="'chart-table-' + report.id" *ngIf="report.hasDatasets()">
|
||||
<table class="table table-responsive table-condensed" 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>
|
||||
<div *ngSwitchCase="'masterDetailTable'">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div [attr.id]="'chart-master-detail-table-' + report.id" *ngIf="report.hasDatasets()">
|
||||
<table class="table table-responsive table-condensed" 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>
|
||||
<div *ngSwitchCase="'bar'">
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<base-chart *ngIf="report.hasDatasets()" class="chart"
|
||||
[datasets]="report.datasets"
|
||||
[labels]="report.labels"
|
||||
[options]="report.options"
|
||||
[chartType]="report.type"></base-chart>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'multiBar'">
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="!report.hasDatasets()">{{'ANALYTICS.MESSAGES.NO-DATA-FOUND' | translate}}</div>
|
||||
<div *ngIf="report.hasDatasets()">
|
||||
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" [attr.for]="'stacked-id'">
|
||||
<input type="checkbox" [attr.id]="'stacked-id'" class="mdl-checkbox__input"
|
||||
[checked]="report.options.scales.xAxes[0].stacked"
|
||||
[(ngModel)]="report.options.scales.xAxes[0].stacked"
|
||||
(change)="refresh(report)">
|
||||
<span class="mdl-checkbox__label">Stacked</span>
|
||||
</label>
|
||||
<base-chart class="chart"
|
||||
[datasets]="report.datasets"
|
||||
[labels]="report.labels"
|
||||
[options]="report.options"
|
||||
[chartType]="'bar'"></base-chart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'HeatMap'">
|
||||
<analytics-report-heat-map [report]="report"></analytics-report-heat-map>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
<span>{{'ANALYTICS.MESSAGES.UNKNOWN-WIDGET-TYPE' | translate}}: {{report.type}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br><br><br>
|
||||
<div *ngIf="!reports">{{'ANALYTICS.MESSAGES.FILL-PARAMETER' | translate}}</div>
|
||||
</div>
|
||||
<activiti-analytics-generator [reportId]="reportId"
|
||||
[reportParamQuery]="reportParamQuery"
|
||||
#analyticsgenerator>
|
||||
</activiti-analytics-generator>
|
||||
</div>
|
||||
|
||||
@@ -16,25 +16,23 @@
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import {
|
||||
CoreModule
|
||||
} from 'ng2-alfresco-core';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { CHART_DIRECTIVES } from 'ng2-charts/ng2-charts';
|
||||
import { CoreModule, AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
import { DiagramsModule } from 'ng2-activiti-diagrams';
|
||||
|
||||
import { AnalyticsReportListComponent } from '../components/analytics-report-list.component';
|
||||
import { AnalyticsComponent } from '../components/analytics.component';
|
||||
import { AnalyticsGeneratorComponent } from '../components/analytics-generator.component';
|
||||
import { AnalyticsReportParametersComponent } from '../components/analytics-report-parameters.component';
|
||||
import { AnalyticsReportHeatMapComponent } from '../components/analytics-report-heat-map.component';
|
||||
import { WIDGET_DIRECTIVES } from '../components/widgets/index';
|
||||
import { CHART_DIRECTIVES } from 'ng2-charts/ng2-charts';
|
||||
import { Chart } from '../models/chart.model';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { ReportQuery } from '../models/report.model';
|
||||
import { DebugElement, SimpleChange } from '@angular/core';
|
||||
import * as analyticMock from '../assets/analyticsComponent.mock';
|
||||
|
||||
export const ANALYTICS_DIRECTIVES: any[] = [
|
||||
AnalyticsComponent,
|
||||
AnalyticsGeneratorComponent,
|
||||
AnalyticsReportParametersComponent,
|
||||
AnalyticsReportListComponent,
|
||||
AnalyticsReportHeatMapComponent,
|
||||
@@ -47,7 +45,7 @@ export const ANALYTICS_PROVIDERS: any[] = [
|
||||
declare let jasmine: any;
|
||||
declare let mdDateTimePicker: any;
|
||||
|
||||
describe('Test ng2-activiti-analytics Report ', () => {
|
||||
describe('AnalyticsComponent', () => {
|
||||
|
||||
let component: any;
|
||||
let fixture: ComponentFixture<AnalyticsComponent>;
|
||||
@@ -59,8 +57,8 @@ describe('Test ng2-activiti-analytics Report ', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule,
|
||||
DiagramsModule
|
||||
CoreModule.forRoot(),
|
||||
DiagramsModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
...ANALYTICS_DIRECTIVES,
|
||||
@@ -70,6 +68,10 @@ describe('Test ng2-activiti-analytics Report ', () => {
|
||||
...ANALYTICS_PROVIDERS
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
let translateService = TestBed.get(AlfrescoTranslationService);
|
||||
spyOn(translateService, 'addTranslationFolder').and.stub();
|
||||
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -93,136 +95,5 @@ describe('Test ng2-activiti-analytics Report ', () => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('Should render the Process definition overview report ', (done) => {
|
||||
component.onSuccess.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(3);
|
||||
|
||||
expect(res[0]).toBeDefined();
|
||||
expect(res[0].type).toEqual('table');
|
||||
expect(res[0].datasets).toBeDefined();
|
||||
expect(res[0].datasets.length).toEqual(4);
|
||||
expect(res[0].datasets[0][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS');
|
||||
expect(res[0].datasets[0][1]).toEqual('9');
|
||||
expect(res[0].datasets[1][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-TOTAL-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[1][1]).toEqual('41');
|
||||
expect(res[0].datasets[2][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[2][1]).toEqual('3');
|
||||
expect(res[0].datasets[3][0]).toEqual('__KEY_REPORTING.DEFAULT-REPORTS.PROCESS-DEFINITION-OVERVIEW.GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES');
|
||||
expect(res[0].datasets[3][1]).toEqual('38');
|
||||
|
||||
expect(res[1]).toBeDefined();
|
||||
expect(res[1].type).toEqual('pie');
|
||||
|
||||
expect(res[2]).toBeDefined();
|
||||
expect(res[2].type).toEqual('table');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
let reportParamQuery = new ReportQuery({status: 'All'});
|
||||
component.appId = 1;
|
||||
component.reportId = 1001;
|
||||
component.showReport(reportParamQuery);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticMock.chartProcessDefOverview
|
||||
});
|
||||
});
|
||||
|
||||
it('Should render the Task overview report ', (done) => {
|
||||
component.onSuccess.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(3);
|
||||
|
||||
expect(res[0]).toBeDefined();
|
||||
expect(res[0].type).toEqual('bar');
|
||||
expect(res[0].labels).toBeDefined();
|
||||
expect(res[0].labels.length).toEqual(2);
|
||||
expect(res[0].labels[0]).toEqual('2016-09-30T00:00:00.000+0000');
|
||||
expect(res[0].labels[1]).toEqual('2016-10-04T00:00:00.000+0000');
|
||||
expect(res[0].datasets[0].label).toEqual('series1');
|
||||
expect(res[0].datasets[0].data[0]).toEqual(3);
|
||||
expect(res[0].datasets[0].data[1]).toEqual(1);
|
||||
|
||||
expect(res[1]).toBeDefined();
|
||||
expect(res[1].type).toEqual('table');
|
||||
expect(res[1].datasets).toBeDefined();
|
||||
expect(res[1].datasets.length).toEqual(2);
|
||||
expect(res[1].datasets[0][0]).toEqual('fake 1 user task');
|
||||
expect(res[1].datasets[0][1]).toEqual('1');
|
||||
expect(res[1].datasets[0][2]).toEqual('2.0');
|
||||
expect(res[1].datasets[0][3]).toEqual('3.0');
|
||||
expect(res[1].datasets[0][4]).toEqual('4.0');
|
||||
expect(res[1].datasets[0][5]).toEqual('5.0');
|
||||
expect(res[1].datasets[0][6]).toEqual('6.0');
|
||||
expect(res[1].datasets[1][0]).toEqual('fake 2 user task');
|
||||
expect(res[1].datasets[1][1]).toEqual('1');
|
||||
expect(res[1].datasets[1][2]).toEqual('2.0');
|
||||
expect(res[1].datasets[1][3]).toEqual('3.0');
|
||||
expect(res[1].datasets[1][4]).toEqual('4.0');
|
||||
expect(res[1].datasets[1][5]).toEqual('5.0');
|
||||
expect(res[1].datasets[1][6]).toEqual('6.0');
|
||||
|
||||
expect(res[2]).toBeDefined();
|
||||
expect(res[2].type).toEqual('multiBar');
|
||||
expect(res[2].labels).toBeDefined();
|
||||
expect(res[2].labels.length).toEqual(3);
|
||||
expect(res[2].labels[0]).toEqual(1);
|
||||
expect(res[2].labels[1]).toEqual(2);
|
||||
expect(res[2].labels[2]).toEqual(3);
|
||||
expect(res[2].datasets[0].label).toEqual('averages');
|
||||
expect(res[2].datasets[0].data[0]).toEqual(0);
|
||||
expect(res[2].datasets[0].data[1]).toEqual(5);
|
||||
expect(res[2].datasets[0].data[2]).toEqual(2);
|
||||
expect(res[2].datasets[1].label).toEqual('minima');
|
||||
expect(res[2].datasets[1].data[0]).toEqual(0);
|
||||
expect(res[2].datasets[1].data[1]).toEqual(0);
|
||||
expect(res[2].datasets[1].data[2]).toEqual(0);
|
||||
expect(res[2].datasets[2].label).toEqual('maxima');
|
||||
expect(res[2].datasets[2].data[0]).toEqual(0);
|
||||
expect(res[2].datasets[2].data[1]).toEqual(29);
|
||||
expect(res[2].datasets[2].data[2]).toEqual(29);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
let reportParamQuery = new ReportQuery({status: 'All'});
|
||||
component.reportId = 1;
|
||||
component.showReport(reportParamQuery);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: analyticMock.chartTaskOverview
|
||||
});
|
||||
});
|
||||
|
||||
it('Should reset the reports when the onChanged is call', () => {
|
||||
let reportId = 1;
|
||||
component.reports = [ new Chart({id: 'fake', type: 'fake-type'})];
|
||||
let change = new SimpleChange(null, reportId);
|
||||
component.ngOnChanges({ 'reportId': change });
|
||||
expect(component.reports).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should emit onError event with a 404 response ', (done) => {
|
||||
component.onError.subscribe((err) => {
|
||||
expect(err).toBeDefined();
|
||||
done();
|
||||
});
|
||||
|
||||
let reportParamQuery = new ReportQuery({status: 'All'});
|
||||
component.reportId = 1;
|
||||
component.showReport(reportParamQuery);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 404,
|
||||
contentType: 'json',
|
||||
responseText: []
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, OnChanges, Input, Output, SimpleChanges } from '@angular/core';
|
||||
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
import { Component, EventEmitter, OnChanges, Input, Output, SimpleChanges, ViewChild } from '@angular/core';
|
||||
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
|
||||
import { AnalyticsService } from '../services/analytics.service';
|
||||
import { ReportQuery } from '../models/report.model';
|
||||
import { Chart } from '../models/chart.model';
|
||||
import { AnalyticsGeneratorComponent } from './analytics-generator.component';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
@@ -30,7 +30,7 @@ import { Chart } from '../models/chart.model';
|
||||
export class AnalyticsComponent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
appId: string;
|
||||
appId: number;
|
||||
|
||||
@Input()
|
||||
reportId: number;
|
||||
@@ -38,80 +38,37 @@ export class AnalyticsComponent implements OnChanges {
|
||||
@Input()
|
||||
debug: boolean = false;
|
||||
|
||||
@Output()
|
||||
onSuccess = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
editReport = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
onError = new EventEmitter();
|
||||
@ViewChild('analyticsgenerator')
|
||||
analyticsgenerator: AnalyticsGeneratorComponent;
|
||||
|
||||
reportParamQuery = new ReportQuery();
|
||||
reportParamQuery: ReportQuery;
|
||||
|
||||
reports: Chart[];
|
||||
|
||||
public barChartOptions: any = {
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
stepSize: 1
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
},
|
||||
stacked: true
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
constructor(private translate: AlfrescoTranslationService,
|
||||
private analyticsService: AnalyticsService) {
|
||||
console.log('AnalyticsComponent');
|
||||
if (translate) {
|
||||
translate.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
|
||||
constructor(private translateService: AlfrescoTranslationService,
|
||||
private analyticsService: AnalyticsService,
|
||||
private logService: LogService) {
|
||||
logService.info('AnalyticsComponent');
|
||||
if (translateService) {
|
||||
translateService.addTranslationFolder('ng2-activiti-analytics', 'node_modules/ng2-activiti-analytics/src');
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
this.reset();
|
||||
this.analyticsgenerator.reset();
|
||||
}
|
||||
|
||||
public showReport($event) {
|
||||
this.reportParamQuery = $event;
|
||||
this.analyticsService.getReportsByParams(this.reportId, this.reportParamQuery).subscribe(
|
||||
(res: Chart[]) => {
|
||||
this.reports = res;
|
||||
this.onSuccess.emit(res);
|
||||
},
|
||||
(err: any) => {
|
||||
this.onError.emit(err);
|
||||
console.log(err);
|
||||
}
|
||||
);
|
||||
this.analyticsgenerator.generateReport(this.reportId, $event);
|
||||
}
|
||||
|
||||
public reset() {
|
||||
if (this.reports) {
|
||||
this.reports = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public refresh(report): void {
|
||||
/**
|
||||
* (My guess), for Angular to recognize the change in the dataset
|
||||
* it has to change the dataset variable directly,
|
||||
* so one way around it, is to clone the data, change it and then
|
||||
* assign it;
|
||||
*/
|
||||
let clone = JSON.parse(JSON.stringify(report));
|
||||
report.datasets = clone.datasets;
|
||||
this.analyticsgenerator.reset();
|
||||
}
|
||||
|
||||
public onEditReport(name: string) {
|
||||
this.editReport.emit(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<label class="dropdown-widget__label" [attr.for]="field.id">{{field.nameKey | translate}}</label>
|
||||
<select [formControlName]="controllerName" [attr.id]="'select-' + field.id" class="dropdown-widget__select"
|
||||
[(ngModel)]="field.value" (ngModelChange)="changeValue($event)">
|
||||
<option *ngIf="showDefaultOption" value="">{{defaultOptionText}}</option>
|
||||
<option *ngIf="showDefaultOption" value="null">{{defaultOptionText}}</option>
|
||||
<option *ngFor="let opt of field.options" [value]="opt.id">{{opt.label}}</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -4,7 +4,9 @@
|
||||
"MESSAGES": {
|
||||
"UNKNOWN-WIDGET-TYPE": "UNKNOWN WIDGET TYPE",
|
||||
"FILL-PARAMETER": "Fill in the parameters to generate your report",
|
||||
"NO-DATA-FOUND": "No data found"
|
||||
"NO-DATA-FOUND": "No data found",
|
||||
"ZERO-DATA-FOUND": "There are only zero values",
|
||||
"SETTING-TITLE": "Change report setting"
|
||||
}
|
||||
},
|
||||
"__KEY_REPORTING": {
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
{
|
||||
"ANALYTICS": {
|
||||
"TTILE": "ANALYTICS"
|
||||
"TTILE": "ANALYTICS",
|
||||
"MESSAGES": {
|
||||
"UNKNOWN-WIDGET-TYPE": "TIPO WIDGET SCONOSCIUTO",
|
||||
"FILL-PARAMETER": "Riempi tutti i campi per generare il report",
|
||||
"NO-DATA-FOUND": "Nessun valore trovato",
|
||||
"ZERO-DATA-FOUND": "Ci sono solo valori che valgono zero",
|
||||
"SETTING-TITLE": "Modifica i parametri del report"
|
||||
}
|
||||
},
|
||||
"__KEY_REPORTING": {
|
||||
"DEFAULT-REPORTS": {
|
||||
"PROCESS-DEFINITION-OVERVIEW": {
|
||||
"GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS": "Numero totale di process definitions",
|
||||
"GENERAL-TABLE-TOTAL-PROCESS-INSTANCES": "Numero totale di process instances",
|
||||
"GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES": "Numero totale di process instances attivi",
|
||||
"GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES": "Numero totale di process instances completi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"REPORTING": {
|
||||
"DEFAULT-REPORTS": {
|
||||
"PROCESS-HEAT-MAP": {
|
||||
"TYPE-FILTERING": "Include tutti gli steps (Deselezionandolo, rimuoverai gli step come start events, gateways, etc.)?"
|
||||
},
|
||||
"PROCESS-INSTANCES-OVERVIEW": {
|
||||
"PROCESS-DEFINITION": "Definizione del processo",
|
||||
"DATE-RANGE": "Intervallo di Date",
|
||||
"SLOW-PROC-INST-NUMBER": "Quanti process instances lenti vuoi mostrare?"
|
||||
},
|
||||
"TASK-OVERVIEW": {
|
||||
"PROCESS-DEFINITION": "Definizione del processo",
|
||||
"DATE-RANGE": "Intervallo di Date",
|
||||
"DATE-RANGE-INTERVAL": "Aggrega date per"
|
||||
},
|
||||
"TASK-SLA": {
|
||||
"TASK": "Task",
|
||||
"PROCESS-DEFINITION": "Definizione del processo",
|
||||
"DATE-RANGE": "Intervallo di Date",
|
||||
"SLA-DURATION": "Qual' é il tempo che questo task necessita per essere completato per rimanere nella SLA?"
|
||||
}
|
||||
},
|
||||
"PROCESS-STATUS": "Stato del processo",
|
||||
"TASK-STATUS": "Stato del task"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ export class Chart {
|
||||
case 'processDefinitionHeatMap':
|
||||
chartType = 'HeatMap';
|
||||
break;
|
||||
case 'masterDetailTable':
|
||||
chartType = 'masterDetailTable';
|
||||
break;
|
||||
default:
|
||||
chartType = 'table';
|
||||
break;
|
||||
@@ -191,6 +194,22 @@ export class TableChart extends Chart {
|
||||
}
|
||||
}
|
||||
|
||||
export class DetailsTableChart extends TableChart {
|
||||
detailsTable: any;
|
||||
showDetails: boolean = false;
|
||||
|
||||
constructor(obj?: any) {
|
||||
super(obj);
|
||||
if (obj.detailTables) {
|
||||
this.detailsTable = new TableChart(obj.detailTables[0]);
|
||||
}
|
||||
}
|
||||
|
||||
hasDetailsTable() {
|
||||
return this.detailsTable ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
export class HeatMapChart extends Chart {
|
||||
avgTimePercentages: string;
|
||||
avgTimeValues: string;
|
||||
@@ -236,7 +255,20 @@ export class PieChart extends Chart {
|
||||
this.data.push(data);
|
||||
}
|
||||
|
||||
hasData() {
|
||||
hasData(): boolean {
|
||||
return this.data && this.data.length > 0 ? true : false;
|
||||
}
|
||||
|
||||
hasZeroValues(): boolean {
|
||||
let isZeroValues: boolean = false;
|
||||
if (this.hasData()) {
|
||||
isZeroValues = true;
|
||||
this.data.forEach((value) => {
|
||||
if (value.toString() !== '0') {
|
||||
isZeroValues = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
return isZeroValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,18 +16,17 @@
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AlfrescoAuthenticationService, AlfrescoSettingsService, AlfrescoApiService } from 'ng2-alfresco-core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { Response } from '@angular/http';
|
||||
import { AlfrescoApiService, LogService } from 'ng2-alfresco-core';
|
||||
import { ReportParametersModel, ParameterValueModel } from '../models/report.model';
|
||||
import { Chart, PieChart, TableChart, BarChart, HeatMapChart, MultiBarChart } from '../models/chart.model';
|
||||
import { Chart, PieChart, TableChart, BarChart, HeatMapChart, MultiBarChart, DetailsTableChart } from '../models/chart.model';
|
||||
|
||||
@Injectable()
|
||||
export class AnalyticsService {
|
||||
|
||||
constructor(private authService: AlfrescoAuthenticationService,
|
||||
public apiService: AlfrescoApiService,
|
||||
private alfrescoSettingsService: AlfrescoSettingsService) {
|
||||
constructor(private apiService: AlfrescoApiService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,14 +42,14 @@ export class AnalyticsService {
|
||||
reports.push(reportModel);
|
||||
});
|
||||
return reports;
|
||||
}).catch(this.handleError);
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getReportParams(reportId: string): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.getReportParams(reportId))
|
||||
.map((res: any) => {
|
||||
return new ReportParametersModel(res);
|
||||
}).catch(this.handleError);
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getParamValuesByType(type: string, appId: string, reportId?: string, processDefinitionId?: string) {
|
||||
@@ -123,7 +122,7 @@ export class AnalyticsService {
|
||||
paramOptions.push(new ParameterValueModel(opt));
|
||||
});
|
||||
return paramOptions;
|
||||
}).catch(this.handleError);
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getProcessDefinitionsValues(appId: string): Observable<any> {
|
||||
@@ -134,7 +133,7 @@ export class AnalyticsService {
|
||||
paramOptions.push(new ParameterValueModel(opt));
|
||||
});
|
||||
return paramOptions;
|
||||
}).catch(this.handleError);
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getTasksByProcessDefinitionId(reportId: string, processDefinitionId: string): Observable<any> {
|
||||
@@ -145,7 +144,7 @@ export class AnalyticsService {
|
||||
paramOptions.push(new ParameterValueModel({ id: opt, name: opt }));
|
||||
});
|
||||
return paramOptions;
|
||||
}).catch(this.handleError);
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getReportsByParams(reportId: number, paramsQuery: any): Observable<any> {
|
||||
@@ -160,7 +159,7 @@ export class AnalyticsService {
|
||||
} else if (chartData.type === 'processDefinitionHeatMap') {
|
||||
elements.push(new HeatMapChart(chartData));
|
||||
} else if (chartData.type === 'masterDetailTable') {
|
||||
elements.push(new TableChart(chartData));
|
||||
elements.push(new DetailsTableChart(chartData));
|
||||
} else if (chartData.type === 'barChart') {
|
||||
elements.push(new BarChart(chartData));
|
||||
} else if (chartData.type === 'multiBarChart') {
|
||||
@@ -169,24 +168,24 @@ export class AnalyticsService {
|
||||
});
|
||||
|
||||
return elements;
|
||||
}).catch(this.handleError);
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
public createDefaultReports(): Observable<any> {
|
||||
createDefaultReports(): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.createDefaultReports())
|
||||
.map(this.toJson)
|
||||
.catch(this.handleError);
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
public updateReport(reportId: number, name: string): Observable<any> {
|
||||
updateReport(reportId: number, name: string): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.reportApi.updateReport(reportId, name))
|
||||
.map((res: any) => {
|
||||
console.log('upload');
|
||||
}).catch(this.handleError);
|
||||
this.logService.info('upload');
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
private handleError(error: Response) {
|
||||
console.error(error);
|
||||
this.logService.error(error);
|
||||
return Observable.throw(error.json().error || 'Server error');
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ Follow the 3 steps below:
|
||||
<script src="node_modules/material-design-lite/material.min.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
||||
|
||||
<!-- Load the Angular Material 2 stylesheet -->
|
||||
<link href="node_modules/@angular/material/core/theming/prebuilt/deeppurple-amber.css" rel="stylesheet">
|
||||
|
||||
<!-- Polyfill(s) for Safari (pre-10.x) -->
|
||||
<script src="node_modules/intl/dist/Intl.min.js"></script>
|
||||
<script src="node_modules/intl/locale-data/jsonp/en.js"></script>
|
||||
|
||||
@@ -39,17 +39,18 @@
|
||||
"@angular/http": "2.2.2",
|
||||
"@angular/platform-browser": "2.2.2",
|
||||
"@angular/platform-browser-dynamic": "2.2.2",
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"@angular/router": "3.2.2",
|
||||
"@angular/upgrade": "2.2.2",
|
||||
"alfresco-js-api": "^1.0.0",
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"core-js": "^2.4.1",
|
||||
"dialog-polyfill": "^0.4.3",
|
||||
"element.scrollintoviewifneeded-polyfill": "^1.0.1",
|
||||
"intl": "1.2.4",
|
||||
"material-design-icons": "2.2.3",
|
||||
"material-design-lite": "1.2.1",
|
||||
"ng2-activiti-diagrams": "^1.0.0",
|
||||
"ng2-alfresco-core": "1.0.0",
|
||||
"ng2-activiti-diagrams": "^1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"raphael": "^2.2.6",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
|
||||
@@ -19,40 +19,39 @@ import { NgModule, Component } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService, StorageService } from 'ng2-alfresco-core';
|
||||
import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService, StorageService, LogService } from 'ng2-alfresco-core';
|
||||
import { DiagramsModule } from 'ng2-activiti-diagrams';
|
||||
|
||||
@Component({
|
||||
selector: 'alfresco-app-demo',
|
||||
template: `
|
||||
<label for="ticket"><b>Insert a valid ticket:</b></label><br>
|
||||
<input id="ticket" type="text" size="48" (change)="updateTicket()" [(ngModel)]="ticket"><br>
|
||||
<label for="host"><b>Insert the ip of your Activiti instance:</b></label><br>
|
||||
<input id="host" type="text" size="48" (change)="updateHost()" [(ngModel)]="host"><br><br>
|
||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid ticket to perform
|
||||
operations.
|
||||
</div>
|
||||
<hr>
|
||||
<label for="ticket"><b>Insert a valid ticket:</b></label><br>
|
||||
<input id="ticket" type="text" size="48" (change)="updateTicket()" [(ngModel)]="ticket"><br>
|
||||
<label for="host"><b>Insert the ip of your Activiti instance:</b></label><br>
|
||||
<input id="host" type="text" size="48" (change)="updateHost()" [(ngModel)]="host"><br><br>
|
||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid ticket to perform
|
||||
operations.
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<label for="processDefinitionId"><b>Insert the ProcessDefinitionId:</b></label><br>
|
||||
<input id="processDefinitionId" size="70" type="text" [(ngModel)]="processDefinitionId">
|
||||
<activiti-diagram [processDefinitionId]="processDefinitionId"></activiti-diagram>`
|
||||
<label for="processDefinitionId"><b>Insert the ProcessDefinitionId:</b></label><br>
|
||||
<input id="processDefinitionId" size="70" type="text" [(ngModel)]="processDefinitionId">
|
||||
<activiti-diagram [processDefinitionId]="processDefinitionId"></activiti-diagram>
|
||||
`
|
||||
})
|
||||
|
||||
export class DiagramDemoComponent {
|
||||
|
||||
processDefinitionId: string = 'ThirdProcess:1:15053';
|
||||
|
||||
authenticated: boolean;
|
||||
|
||||
host: string = 'http://localhost:9999';
|
||||
|
||||
ticket: string;
|
||||
|
||||
constructor(private authService: AlfrescoAuthenticationService,
|
||||
private settingsService: AlfrescoSettingsService,
|
||||
private storage: StorageService) {
|
||||
private storage: StorageService,
|
||||
private logService: LogService) {
|
||||
settingsService.bpmHost = this.host;
|
||||
settingsService.setProviders('BPM');
|
||||
|
||||
@@ -77,12 +76,12 @@ export class DiagramDemoComponent {
|
||||
login() {
|
||||
this.authService.login('admin', 'admin').subscribe(
|
||||
ticket => {
|
||||
console.log(ticket);
|
||||
this.logService.info(`Logged in with ticket ${ticket}`);
|
||||
this.ticket = this.authService.getTicketBpm();
|
||||
this.authenticated = true;
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
this.logService.error(error);
|
||||
this.authenticated = false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
// Tun on full stack traces in errors to help debugging
|
||||
Error.stackTraceLimit = Infinity;
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
|
||||
|
||||
window.componentHandler = {
|
||||
upgradeAllRegistered: function () {
|
||||
},
|
||||
upgradeElement: function () {
|
||||
}
|
||||
};
|
||||
|
||||
__karma__.loaded = function() {};
|
||||
|
||||
@@ -39,6 +46,8 @@ var map = {
|
||||
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
|
||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||
'@angular/material': 'npm:@angular/material/bundles/material.umd.js',
|
||||
|
||||
// testing
|
||||
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
|
||||
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "ng2-activiti-diagrams",
|
||||
"description": "Activiti Angular2 Diagrams Component",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
"clean-build": "rimraf index.js index.js.map index.d.ts'src/{,**/}**.js' 'src/{,**/}**.js.map' 'src/{,**/}**.d.ts' bundles",
|
||||
"build": "npm run clean-build && npm run tslint && rimraf dist && tsc && license-check && npm run build.umd",
|
||||
"build:w": "npm run clean-build && npm run tslint && rimraf dist && tsc:w && license-check npm run build.umd",
|
||||
"build:w": "npm run clean-build && npm run tslint && rimraf dist && npm run tsc:w && license-check && npm run build.umd",
|
||||
"tslint": "tslint -c tslint.json 'src/{,**/}**.ts' 'index.ts' -e '{,**/}**.d.ts' -e './gulpfile.ts'",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
@@ -16,7 +16,7 @@
|
||||
"test-browser": "npm run build && concurrently \"karma start karma.conf.js --reporters kjhtml\" \"npm run watch-task\"",
|
||||
"posttest": "remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html && remap-istanbul -i coverage/report/coverage-final.json -o coverage/report/coverage-final.json",
|
||||
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
||||
"prepublish": "npm run build",
|
||||
"prepublish": "npm run test",
|
||||
"travis": "npm link ng2-alfresco-core",
|
||||
"gulp": "gulp",
|
||||
"build.umd": "gulp build.prod --color --env-config prod --build-type prod",
|
||||
@@ -47,21 +47,21 @@
|
||||
"@angular/http": "2.0.0",
|
||||
"@angular/platform-browser": "2.0.0",
|
||||
"@angular/platform-browser-dynamic": "2.0.0",
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"core-js": "^2.4.1",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
"rxjs": "5.0.0-beta.12",
|
||||
"systemjs": "0.19.27",
|
||||
"zone.js": "^0.6.23",
|
||||
"raphael": "^2.2.6",
|
||||
"chart.js": "^2.1.4",
|
||||
"ng2-charts": "1.1.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "^1.0.0",
|
||||
"ng2-alfresco-core": "1.0.0"
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "1.3.1",
|
||||
"cssnano": "^3.8.1",
|
||||
@@ -80,6 +80,7 @@
|
||||
"gulp-template": "^4.0.0",
|
||||
"gulp-typescript": "^3.1.3",
|
||||
"gulp-uglify": "^2.0.0",
|
||||
"gulp-util": "^3.0.7",
|
||||
"intl": "^1.2.5",
|
||||
"jasmine-core": "2.4.1",
|
||||
"karma": "0.13.22",
|
||||
@@ -90,6 +91,7 @@
|
||||
"karma-jasmine-html-reporter": "0.2.0",
|
||||
"karma-mocha-reporter": "2.0.3",
|
||||
"license-check": "1.1.5",
|
||||
"merge-stream": "^1.0.1",
|
||||
"remap-istanbul": "0.6.3",
|
||||
"rimraf": "2.5.2",
|
||||
"run-sequence": "^1.2.2",
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import {
|
||||
CoreModule,
|
||||
AlfrescoTranslationService
|
||||
} from 'ng2-alfresco-core';
|
||||
import { CoreModule, AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
|
||||
import { DIAGRAM_DIRECTIVES, DIAGRAM_PROVIDERS } from './index';
|
||||
import { RAPHAEL_DIRECTIVES, RAPHAEL_PROVIDERS } from './raphael/index';
|
||||
@@ -50,7 +47,7 @@ describe('Test ng2-activiti-diagrams ', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreModule
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
...DIAGRAM_DIRECTIVES,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, ElementRef, Input, Output, EventEmitter, SimpleChanges } from '@angular/core';
|
||||
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
|
||||
import { DiagramsService } from '../services/diagrams.service';
|
||||
import { DiagramColorService } from '../services/diagram-color.service';
|
||||
import { RaphaelService } from './raphael/raphael.service';
|
||||
@@ -57,17 +57,16 @@ export class DiagramComponent {
|
||||
PADDING_HEIGHT: number = 60;
|
||||
|
||||
private diagram: DiagramModel;
|
||||
private elementRef: ElementRef;
|
||||
|
||||
constructor(elementRef: ElementRef,
|
||||
private translate: AlfrescoTranslationService,
|
||||
constructor(private elementRef: ElementRef,
|
||||
private translateService: AlfrescoTranslationService,
|
||||
private diagramColorService: DiagramColorService,
|
||||
private raphaelService: RaphaelService,
|
||||
private diagramsService: DiagramsService) {
|
||||
if (translate) {
|
||||
translate.addTranslationFolder('ng2-activiti-diagrams', 'node_modules/ng2-activiti-diagrams/src');
|
||||
private diagramsService: DiagramsService,
|
||||
private logService: LogService) {
|
||||
if (translateService) {
|
||||
translateService.addTranslationFolder('ng2-activiti-diagrams', 'node_modules/ng2-activiti-diagrams/src');
|
||||
}
|
||||
this.elementRef = elementRef;
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
@@ -86,7 +85,7 @@ export class DiagramComponent {
|
||||
},
|
||||
(err: any) => {
|
||||
this.onError.emit(err);
|
||||
console.log(err);
|
||||
this.logService.error(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
+5
-3
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Directive, OnInit, ElementRef, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { Point } from './models/point';
|
||||
import { RaphaelBase } from './raphael-base';
|
||||
import { RaphaelService } from './raphael.service';
|
||||
@@ -43,19 +44,20 @@ export class RaphaelMultilineTextDirective extends RaphaelBase implements OnInit
|
||||
TEXT_PADDING = 3;
|
||||
|
||||
constructor(public elementRef: ElementRef,
|
||||
raphaelService: RaphaelService) {
|
||||
raphaelService: RaphaelService,
|
||||
private logService: LogService) {
|
||||
super(elementRef, raphaelService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
console.log(this.elementRef);
|
||||
this.logService.log(this.elementRef);
|
||||
if (this.text === null || this.text === undefined) {
|
||||
this.text = '';
|
||||
}
|
||||
this.draw(this.position, this.text);
|
||||
}
|
||||
|
||||
public draw(position: Point, text: string) {
|
||||
draw(position: Point, text: string) {
|
||||
let textPaper = this.paper.text(position.x + this.TEXT_PADDING, position.y + this.TEXT_PADDING, text).attr({
|
||||
'text-anchor': 'middle',
|
||||
'font-family': 'Arial',
|
||||
|
||||
@@ -16,27 +16,28 @@
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { Response, Http, Headers, RequestOptions } from '@angular/http';
|
||||
import { AlfrescoAuthenticationService, AlfrescoSettingsService, LogService } from 'ng2-alfresco-core';
|
||||
|
||||
@Injectable()
|
||||
export class DiagramsService {
|
||||
|
||||
constructor(private authService: AlfrescoAuthenticationService,
|
||||
private http: Http,
|
||||
private alfrescoSettingsService: AlfrescoSettingsService) {
|
||||
private settingsService: AlfrescoSettingsService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
getProcessDefinitionModel(processDefinitionId: string): Observable<any> {
|
||||
let url = `${this.alfrescoSettingsService.getBPMApiBaseUrl()}/app/rest/process-definitions/${processDefinitionId}/model-json`;
|
||||
let url = `${this.settingsService.getBPMApiBaseUrl()}/app/rest/process-definitions/${processDefinitionId}/model-json`;
|
||||
let options = this.getRequestOptions();
|
||||
return this.http
|
||||
.get(url, options)
|
||||
.map((res: any) => {
|
||||
let body = res.json();
|
||||
return body;
|
||||
}).catch(this.handleError);
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
public getHeaders(): Headers {
|
||||
@@ -53,7 +54,7 @@ export class DiagramsService {
|
||||
}
|
||||
|
||||
private handleError(error: Response) {
|
||||
console.error(error);
|
||||
this.logService.error(error);
|
||||
return Observable.throw(error.json().error || 'Server error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,22 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Library Contents
|
||||
|
||||
### Components
|
||||
|
||||
- [ActivitiForm](#activitiform-component)
|
||||
- ActivitiStartForm
|
||||
|
||||
### Services
|
||||
|
||||
- [FormService](#formservice)
|
||||
- ActivitiAlfrescoContentService
|
||||
- EcmModelService
|
||||
- FormRenderingService
|
||||
- NodeService
|
||||
- WidgetVisibilityService
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you start using this development framework, make sure you have installed all required software and done all the
|
||||
@@ -65,6 +81,9 @@ Follow the 3 steps below:
|
||||
<script src="node_modules/material-design-lite/material.min.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
||||
|
||||
<!-- Load the Angular Material 2 stylesheet -->
|
||||
<link href="node_modules/@angular/material/core/theming/prebuilt/deeppurple-amber.css" rel="stylesheet">
|
||||
|
||||
<!-- Polyfill(s) for Safari (pre-10.x) -->
|
||||
<script src="node_modules/intl/dist/Intl.min.js"></script>
|
||||
<script src="node_modules/intl/locale-data/jsonp/en.js"></script>
|
||||
@@ -98,7 +117,9 @@ Follow the 3 steps below:
|
||||
Please refer to the following example file: [systemjs.config.js](demo/systemjs
|
||||
.config.js) .
|
||||
|
||||
## Basic usage examples
|
||||
## ActivitiForm Component
|
||||
|
||||
### Basic usage
|
||||
|
||||
The component shows a Form from Activiti
|
||||
|
||||
@@ -109,6 +130,7 @@ The component shows a Form from Activiti
|
||||
Usage example of this component :
|
||||
|
||||
**main.ts**
|
||||
|
||||
```ts
|
||||
import { NgModule, Component } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
@@ -220,9 +242,9 @@ and store the form field as metadata. The param nameNode is optional.
|
||||
</activiti-form>
|
||||
```
|
||||
|
||||
## Configuration
|
||||
### Configuration
|
||||
|
||||
### Properties
|
||||
#### Properties
|
||||
|
||||
The recommended set of properties can be found in the following table:
|
||||
|
||||
@@ -238,11 +260,12 @@ The recommended set of properties can be found in the following table:
|
||||
| `showDebugButton` | boolean | false | Toggle debug options. |
|
||||
| `readOnly` | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
|
||||
| `showRefreshButton` | boolean | true | Toggle rendering of the `Refresh` button. |
|
||||
| `showValidationIcon` | boolean | true | Toggle rendering of the validation icon next form title. |
|
||||
| `saveMetadata` | boolean | false | Store the value of the form as metadata. |
|
||||
| `path` | string | | Path of the folder where to store the metadata. |
|
||||
| `nameNode` (optional) | string | true | Name to assign to the new node where the metadata are stored. |
|
||||
|
||||
#### Advanced properties
|
||||
##### Advanced properties
|
||||
|
||||
The following properties are for complex customisation purposes:
|
||||
|
||||
@@ -251,7 +274,7 @@ The recommended set of properties can be found in the following table:
|
||||
| `form` | FormModel | | Underlying form model instance. |
|
||||
| `debugMode` | boolean | false | Toggle debug mode, allows displaying additional data for development and debugging purposes. |
|
||||
|
||||
### Events
|
||||
#### Events
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
@@ -328,6 +351,70 @@ There are two additional functions that can be of a great value when controlling
|
||||
**Please note that if `event.preventDefault()` is not called then default outcome behaviour
|
||||
will also be executed after your custom code.**
|
||||
|
||||
## FormService
|
||||
|
||||
```ts
|
||||
import { Component } from '@angular/core';
|
||||
import { FormService, FormEvent, FormFieldEvent } from 'ng2-activiti-form';
|
||||
|
||||
@Component(...)
|
||||
class MyComponent {
|
||||
|
||||
constructor(private formService: FormService) {
|
||||
|
||||
formService.formLoaded.subscribe((e: FormEvent) => {
|
||||
console.log(`Form loaded: ${e.form.id}`);
|
||||
});
|
||||
|
||||
formService.formFieldValueChanged.subscribe((e: FormFieldEvent) => {
|
||||
console.log(`Field value changed. Form: ${e.form.id}, Field: ${e.field.id}, Value: ${e.field.value}`);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Args Type | Description |
|
||||
| --- | --- | --- |
|
||||
| formLoaded | FormEvent | Raised when form has been loaded or reloaded |
|
||||
| formFieldValueChanged | FormFieldEvent | Raised when input values change |
|
||||
| taskCompleted | FormEvent | Raised when a task is completed successfully |
|
||||
| taskCompletedError | FormErrorEvent | Raised when a task is completed unsuccessfully |
|
||||
| taskSaved | FormEvent | Raised when a task is saved successfully |
|
||||
| taskSavedError | FormErrorEvent | Raised when a task is saved unsuccessfully |
|
||||
|
||||
### Methods
|
||||
|
||||
| Name | Params | Returns | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| createFormFromANode | (formName: string) | Observable\<any\> | Create a Form with a fields for each metadata properties |
|
||||
| createForm | (formName: string) | Observable\<any\> | Create a Form |
|
||||
| addFieldsToAForm | (formId: string, formModel: FormDefinitionModel) | Observable\<any\> | Add Fileds to A form |
|
||||
| searchFrom | (name: string) | Observable\<any\> | Search For A Form by name |
|
||||
| getForms | n/a | Observable\<any\> | Get All the forms |
|
||||
| getProcessDefinitions | n/a | Observable\<any\> | Get Process Definitions |
|
||||
| getTasks | n/a | Observable\<any\> | Get All the Tasks |
|
||||
| getTask | (taskId: string) | Observable\<any\> | Get Task |
|
||||
| saveTaskForm | (taskId: string, formValues: FormValues) | Observable\<any\> | Save Task Form |
|
||||
| completeTaskForm | (taskId: string, formValues: FormValues, outcome?: string) | Observable\<any\> | Complete Task Form |
|
||||
| getTaskForm | (taskId: string) | Observable\<any\> | Get Form related to a taskId |
|
||||
| getFormDefinitionById | (formId: string) | Observable\<any\> | Get Form Definition |
|
||||
| getFormDefinitionByName | (name: string) | Observable\<any\> | Returns form definition by a given name. |
|
||||
| getStartFormInstance | (processId: string) | Observable\<any\> | Get start form instance for a given processId |
|
||||
| getStartFormDefinition | (processId: string) | Observable\<any\> | Get start form definition for a given process |
|
||||
| createTemporaryRawRelatedContent | (file: any) | Observable\<any\> | Save File |
|
||||
| getRestFieldValues | (taskId: string, field: string) | Observable\<any\> | |
|
||||
| getRestFieldValuesByProcessId | (processDefinitionId: string, field: string) | Observable\<any\> | |
|
||||
| getRestFieldValuesColumnByProcessId | (processDefinitionId: string, field: string, column?: string) | Observable\<any\> | |
|
||||
| getRestFieldValuesColumn | (taskId: string, field: string, column?: string) | Observable\<any\> | |
|
||||
| getWorkflowGroups\* | (filter: string, groupId?: string) | Observable\<GroupModel[]\> | |
|
||||
| getWorkflowUsers\* | (filter: string, groupId?: string) | Observable\<GroupUserModel[]\> | |
|
||||
|
||||
\* _Uses private Activiti WebApp api_
|
||||
|
||||
## See also
|
||||
|
||||
- [Form Stencils with Angular 2](docs/stencils.md)
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"@angular/http": "2.2.2",
|
||||
"@angular/platform-browser": "2.2.2",
|
||||
"@angular/platform-browser-dynamic": "2.2.2",
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"@angular/router": "3.2.2",
|
||||
"@angular/upgrade": "2.2.2",
|
||||
"core-js": "^2.4.1",
|
||||
@@ -54,9 +55,9 @@
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "^1.0.0",
|
||||
"ng2-alfresco-core": "1.0.0",
|
||||
"ng2-activiti-form": "^1.0.0"
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0",
|
||||
"ng2-activiti-form": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
|
||||
@@ -18,40 +18,39 @@
|
||||
import { NgModule, Component, OnInit } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService, StorageService } from 'ng2-alfresco-core';
|
||||
import { CoreModule, AlfrescoSettingsService, AlfrescoAuthenticationService, StorageService, LogService } from 'ng2-alfresco-core';
|
||||
import { ActivitiFormModule } from 'ng2-activiti-form';
|
||||
|
||||
@Component({
|
||||
selector: 'alfresco-app-demo',
|
||||
template: `
|
||||
<label for="ticket"><b>Insert a valid ticket:</b></label><br>
|
||||
<input id="ticket" type="text" size="48" (change)="updateTicket()" [(ngModel)]="ticket"><br>
|
||||
<label for="host"><b>Insert the ip of your Activiti instance:</b></label><br>
|
||||
<input id="host" type="text" size="48" (change)="updateHost()" [(ngModel)]="host"><br><br>
|
||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid ticket to perform
|
||||
operations.
|
||||
</div>
|
||||
<hr>
|
||||
<label for="ticket"><b>Insert a valid ticket:</b></label><br>
|
||||
<input id="ticket" type="text" size="48" (change)="updateTicket()" [(ngModel)]="ticket"><br>
|
||||
<label for="host"><b>Insert the ip of your Activiti instance:</b></label><br>
|
||||
<input id="host" type="text" size="48" (change)="updateHost()" [(ngModel)]="host"><br><br>
|
||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid ticket to perform
|
||||
operations.
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<label for="taskId"><b>Insert the taskId:</b></label><br>
|
||||
<input id="taskId" size="10" type="text" [(ngModel)]="taskId">
|
||||
<activiti-form [taskId]="taskId"></activiti-form>`
|
||||
<label for="taskId"><b>Insert the taskId:</b></label><br>
|
||||
<input id="taskId" size="10" type="text" [(ngModel)]="taskId">
|
||||
<activiti-form [taskId]="taskId"></activiti-form>
|
||||
`
|
||||
})
|
||||
|
||||
export class FormDemoComponent implements OnInit {
|
||||
|
||||
taskId: number;
|
||||
|
||||
authenticated: boolean;
|
||||
|
||||
host: string = 'http://localhost:9999';
|
||||
|
||||
ticket: string;
|
||||
|
||||
constructor(private authService: AlfrescoAuthenticationService,
|
||||
private settingsService: AlfrescoSettingsService,
|
||||
private storage: StorageService) {
|
||||
private storage: StorageService,
|
||||
private logService: LogService) {
|
||||
settingsService.bpmHost = this.host;
|
||||
settingsService.setProviders('BPM');
|
||||
|
||||
@@ -76,12 +75,12 @@ export class FormDemoComponent implements OnInit {
|
||||
login() {
|
||||
this.authService.login('admin', 'admin').subscribe(
|
||||
ticket => {
|
||||
console.log(ticket);
|
||||
this.logService.info(`Logged in with ticket ${ticket}`);
|
||||
this.ticket = this.authService.getTicketBpm();
|
||||
this.authenticated = true;
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
this.logService.error(error);
|
||||
this.authenticated = false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ export * from './src/components/widgets/index';
|
||||
export * from './src/services/ecm-model.service';
|
||||
export * from './src/services/node.service';
|
||||
export * from './src/services/form-rendering.service';
|
||||
export * from './src/events/index';
|
||||
|
||||
export const ACTIVITI_FORM_DIRECTIVES: any[] = [
|
||||
ActivitiForm,
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
// Tun on full stack traces in errors to help debugging
|
||||
Error.stackTraceLimit = Infinity;
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
|
||||
|
||||
window.componentHandler = {
|
||||
upgradeAllRegistered: function () {
|
||||
},
|
||||
upgradeElement: function () {
|
||||
}
|
||||
};
|
||||
|
||||
__karma__.loaded = function() {};
|
||||
|
||||
@@ -39,6 +46,8 @@ var map = {
|
||||
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
|
||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||
'@angular/material': 'npm:@angular/material/bundles/material.umd.js',
|
||||
|
||||
// testing
|
||||
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
|
||||
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "ng2-activiti-form",
|
||||
"description": "Alfresco Activiti Form Component for Angular 2",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
|
||||
"clean-build": "rimraf index.js index.js.map index.d.ts'src/{,**/}**.js' 'src/{,**/}**.js.map' 'src/{,**/}**.d.ts' bundles",
|
||||
"build": "npm run clean-build && npm run tslint && rimraf dist && tsc && license-check && npm run build.umd",
|
||||
"build:w": "npm run clean-build && npm run tslint && rimraf dist && tsc:w && license-check npm run build.umd",
|
||||
"build:w": "npm run clean-build && npm run tslint && rimraf dist && npm run tsc:w && license-check && npm run build.umd",
|
||||
"tslint": "tslint -c tslint.json 'src/{,**/}**.ts' 'index.ts' -e '{,**/}**.d.ts' -e './gulpfile.ts'",
|
||||
"tsc": "tsc",
|
||||
"tsc:w": "tsc -w",
|
||||
@@ -16,7 +16,7 @@
|
||||
"test-browser": "npm run build && concurrently \"karma start karma.conf.js --reporters kjhtml\" \"npm run watch-task\"",
|
||||
"posttest": "remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html && remap-istanbul -i coverage/report/coverage-final.json -o coverage/report/coverage-final.json",
|
||||
"coverage": "npm run test && wsrv -o -p 9875 ./coverage/report",
|
||||
"prepublish": "npm run build",
|
||||
"prepublish": "npm run test",
|
||||
"travis": "npm link ng2-alfresco-core",
|
||||
"gulp": "gulp",
|
||||
"build.umd": "gulp build.prod --color --env-config prod --build-type prod",
|
||||
@@ -54,6 +54,7 @@
|
||||
"@angular/http": "2.0.0",
|
||||
"@angular/platform-browser": "2.0.0",
|
||||
"@angular/platform-browser-dynamic": "2.0.0",
|
||||
"@angular/material": "2.0.0-beta.1",
|
||||
"core-js": "^2.4.1",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
"rxjs": "5.0.0-beta.12",
|
||||
@@ -62,13 +63,13 @@
|
||||
"moment": "2.15.1",
|
||||
"md-date-time-picker": "^2.2.0",
|
||||
"ng2-translate": "2.5.0",
|
||||
"alfresco-js-api": "^1.0.0",
|
||||
"ng2-alfresco-core": "1.0.0"
|
||||
"alfresco-js-api": "~1.1.0",
|
||||
"ng2-alfresco-core": "1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^2.2.33",
|
||||
"@types/node": "^6.0.42",
|
||||
"autoprefixer": "^6.5.1",
|
||||
"autoprefixer": "^6.5.4",
|
||||
"concurrently": "^2.2.0",
|
||||
"cpx": "^1.3.1",
|
||||
"cssnano": "^3.8.1",
|
||||
@@ -87,6 +88,7 @@
|
||||
"gulp-template": "^4.0.0",
|
||||
"gulp-typescript": "^3.1.3",
|
||||
"gulp-uglify": "^2.0.0",
|
||||
"gulp-util": "^3.0.7",
|
||||
"intl": "^1.2.5",
|
||||
"jasmine-ajax": "^3.2.0",
|
||||
"jasmine-core": "2.4.1",
|
||||
@@ -98,6 +100,7 @@
|
||||
"karma-jasmine-html-reporter": "^0.2.0",
|
||||
"karma-mocha-reporter": "^2.0.3",
|
||||
"license-check": "^1.0.4",
|
||||
"merge-stream": "^1.0.1",
|
||||
"remap-istanbul": "^0.6.3",
|
||||
"rimraf": "2.5.2",
|
||||
"run-sequence": "^1.2.2",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div *ngIf="hasForm()">
|
||||
<div class="mdl-card mdl-shadow--2dp activiti-form-container">
|
||||
<div class="mdl-card__title">
|
||||
<i class="material-icons">{{ form.isValid ? 'event_available' : 'event_busy' }}</i>
|
||||
<i *ngIf="showValidationIcon" class="material-icons">{{ form.isValid ? 'event_available' : 'event_busy' }}</i>
|
||||
<h2 *ngIf="isTitleEnabled()" class="mdl-card__title-text">{{form.taskName}}</h2>
|
||||
</div>
|
||||
<div class="mdl-card__media">
|
||||
@@ -24,7 +24,7 @@
|
||||
alfresco-mdl-button
|
||||
[disabled]="!isOutcomeButtonEnabled(outcome)"
|
||||
[class.mdl-button--colored]="!outcome.isSystem"
|
||||
[class.activiti-form-hide-button]="!isOutcomeButtonVisible(outcome)"
|
||||
[class.activiti-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
|
||||
(click)="onOutcomeClicked(outcome, $event)">
|
||||
{{outcome.name}}
|
||||
</button>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { SimpleChange } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { ActivitiForm } from './activiti-form.component';
|
||||
import { FormModel, FormOutcomeModel, FormFieldModel, FormOutcomeEvent, FormFieldTypes } from './widgets/index';
|
||||
import { FormService } from './../services/form.service';
|
||||
@@ -30,6 +31,7 @@ describe('ActivitiForm', () => {
|
||||
let formComponent: ActivitiForm;
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
let nodeService: NodeService;
|
||||
let logService: LogService;
|
||||
|
||||
beforeEach(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
@@ -37,11 +39,12 @@ describe('ActivitiForm', () => {
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
|
||||
visibilityService = new WidgetVisibilityService(null);
|
||||
logService = new LogService();
|
||||
visibilityService = new WidgetVisibilityService(null, logService);
|
||||
spyOn(visibilityService, 'refreshVisibility').and.stub();
|
||||
formService = new FormService(null, null);
|
||||
nodeService = new NodeService(null, null);
|
||||
formComponent = new ActivitiForm(formService, visibilityService, null, nodeService);
|
||||
formService = new FormService(null, null, logService);
|
||||
nodeService = new NodeService(null);
|
||||
formComponent = new ActivitiForm(formService, visibilityService, null, nodeService, logService);
|
||||
});
|
||||
|
||||
it('should upgrade MDL content on view checked', () => {
|
||||
@@ -98,35 +101,73 @@ describe('ActivitiForm', () => {
|
||||
});
|
||||
|
||||
it('should not enable outcome button when model missing', () => {
|
||||
expect(formComponent.isOutcomeButtonVisible(null)).toBeFalsy();
|
||||
expect(formComponent.isOutcomeButtonVisible(null, false)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should enable custom outcome buttons', () => {
|
||||
let formModel = new FormModel();
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: 'action1', name: 'Action 1'});
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy();
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should allow controlling [complete] button visibility', () => {
|
||||
let formModel = new FormModel();
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$save', name: FormOutcomeModel.SAVE_ACTION});
|
||||
|
||||
formComponent.showSaveButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy();
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
|
||||
formComponent.showSaveButton = false;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome)).toBeFalsy();
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show only [complete] button with readOnly form ', () => {
|
||||
let formModel = new FormModel();
|
||||
formModel.readOnly = true;
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$complete', name: FormOutcomeModel.COMPLETE_ACTION});
|
||||
|
||||
formComponent.showCompleteButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not show [save] button with readOnly form ', () => {
|
||||
let formModel = new FormModel();
|
||||
formModel.readOnly = true;
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$save', name: FormOutcomeModel.SAVE_ACTION});
|
||||
|
||||
formComponent.showSaveButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show [custom-outcome] button with readOnly form and selected custom-outcome', () => {
|
||||
let formModel = new FormModel({selectedOutcome: 'custom-outcome'});
|
||||
formModel.readOnly = true;
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$customoutome', name: 'custom-outcome'});
|
||||
|
||||
formComponent.showCompleteButton = true;
|
||||
formComponent.showSaveButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
|
||||
outcome = new FormOutcomeModel(formModel, {id: '$customoutome2', name: 'custom-outcome2'});
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should allow controlling [save] button visibility', () => {
|
||||
let formModel = new FormModel();
|
||||
formModel.readOnly = false;
|
||||
formComponent.form = formModel;
|
||||
let outcome = new FormOutcomeModel(formModel, {id: '$save', name: FormOutcomeModel.COMPLETE_ACTION});
|
||||
|
||||
formComponent.showCompleteButton = true;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy();
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
|
||||
|
||||
formComponent.showCompleteButton = false;
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome)).toBeFalsy();
|
||||
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should load form on refresh', () => {
|
||||
@@ -560,13 +601,6 @@ describe('ActivitiForm', () => {
|
||||
expect(formService.completeTaskForm).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should log error to console by default', () => {
|
||||
const error = 'Error';
|
||||
spyOn(console, 'log').and.stub();
|
||||
formComponent.handleError(error);
|
||||
expect(console.log).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('should complete form form and raise corresponding event', () => {
|
||||
spyOn(formService, 'completeTaskForm').and.callFake(() => {
|
||||
return Observable.create(observer => {
|
||||
|
||||
@@ -15,18 +15,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
OnInit, AfterViewChecked, OnChanges,
|
||||
SimpleChanges,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter
|
||||
} from '@angular/core';
|
||||
import { Component, OnInit, AfterViewChecked, OnChanges, SimpleChanges, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { EcmModelService } from './../services/ecm-model.service';
|
||||
import { FormService } from './../services/form.service';
|
||||
import { NodeService } from './../services/node.service';
|
||||
import { FormModel, FormOutcomeModel, FormValues, FormFieldModel, FormOutcomeEvent } from './widgets/core/index';
|
||||
import { FormEvent, FormErrorEvent } from './../events/index';
|
||||
|
||||
import { WidgetVisibilityService } from './../services/widget-visibility.service';
|
||||
|
||||
@@ -85,6 +80,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
|
||||
static SAVE_OUTCOME_ID: string = '$save';
|
||||
static COMPLETE_OUTCOME_ID: string = '$complete';
|
||||
static START_PROCESS_OUTCOME_ID: string = '$startProcess';
|
||||
static CUSTOM_OUTCOME_ID: string = '$custom';
|
||||
|
||||
@Input()
|
||||
@@ -129,6 +125,9 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
@Input()
|
||||
showRefreshButton: boolean = true;
|
||||
|
||||
@Input()
|
||||
showValidationIcon: boolean = true;
|
||||
|
||||
@Output()
|
||||
formSaved: EventEmitter<FormModel> = new EventEmitter<FormModel>();
|
||||
|
||||
@@ -149,9 +148,10 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
debugMode: boolean = false;
|
||||
|
||||
constructor(protected formService: FormService,
|
||||
public visibilityService: WidgetVisibilityService,
|
||||
protected visibilityService: WidgetVisibilityService,
|
||||
private ecmModelService: EcmModelService,
|
||||
private nodeService: NodeService) {
|
||||
private nodeService: NodeService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
hasForm(): boolean {
|
||||
@@ -182,14 +182,20 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
return false;
|
||||
}
|
||||
|
||||
isOutcomeButtonVisible(outcome: FormOutcomeModel): boolean {
|
||||
isOutcomeButtonVisible(outcome: FormOutcomeModel, isFormReadOnly: boolean): boolean {
|
||||
if (outcome && outcome.name) {
|
||||
if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) {
|
||||
return this.showCompleteButton;
|
||||
}
|
||||
if (isFormReadOnly) {
|
||||
return outcome.isSelected ;
|
||||
}
|
||||
if (outcome.name === FormOutcomeModel.SAVE_ACTION) {
|
||||
return this.showSaveButton;
|
||||
}
|
||||
if (outcome.name === FormOutcomeModel.START_PROCESS_ACTION) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -252,15 +258,20 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (outcome.id === ActivitiForm.START_PROCESS_OUTCOME_ID) {
|
||||
this.completeTaskForm();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (outcome.id === ActivitiForm.CUSTOM_OUTCOME_ID) {
|
||||
this.formSaved.emit(this.form);
|
||||
this.onTaskSaved(this.form);
|
||||
this.storeFormAsMetadata();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Note: Activiti is using NAME field rather than ID for outcomes
|
||||
if (outcome.name) {
|
||||
this.formSaved.emit(this.form);
|
||||
this.onTaskSaved(this.form);
|
||||
this.completeTaskForm(outcome.name);
|
||||
return true;
|
||||
}
|
||||
@@ -326,8 +337,8 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
.getTaskForm(taskId)
|
||||
.subscribe(
|
||||
form => {
|
||||
this.form = new FormModel(form, data, this.readOnly);
|
||||
this.formLoaded.emit(this.form);
|
||||
this.form = new FormModel(form, data, this.readOnly, this.formService);
|
||||
this.onFormLoaded(this.form);
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
@@ -342,7 +353,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
form => {
|
||||
this.formName = form.name;
|
||||
this.form = this.parseForm(form);
|
||||
this.formLoaded.emit(this.form);
|
||||
this.onFormLoaded(this.form);
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
@@ -357,9 +368,8 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
id => {
|
||||
this.formService.getFormDefinitionById(id).subscribe(
|
||||
form => {
|
||||
// console.log('Get Form By Form definition Name', form);
|
||||
this.form = this.parseForm(form);
|
||||
this.formLoaded.emit(this.form);
|
||||
this.onFormLoaded(this.form);
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
@@ -378,12 +388,10 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
.saveTaskForm(this.form.taskId, this.form.values)
|
||||
.subscribe(
|
||||
() => {
|
||||
this.formSaved.emit(this.form);
|
||||
this.onTaskSaved(this.form);
|
||||
this.storeFormAsMetadata();
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
}
|
||||
error => this.onTaskSavedError(this.form, error)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -394,24 +402,22 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
.completeTaskForm(this.form.taskId, this.form.values, outcome)
|
||||
.subscribe(
|
||||
() => {
|
||||
this.formCompleted.emit(this.form);
|
||||
this.onTaskCompleted(this.form);
|
||||
this.storeFormAsMetadata();
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
}
|
||||
error => this.onTaskCompletedError(this.form, error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
handleError(err: any): any {
|
||||
console.log(err);
|
||||
this.logService.error(err);
|
||||
this.onError.emit(err);
|
||||
}
|
||||
|
||||
parseForm(json: any): FormModel {
|
||||
if (json) {
|
||||
let form = new FormModel(json, this.data, this.readOnly);
|
||||
let form = new FormModel(json, this.data, this.readOnly, this.formService);
|
||||
if (!json.fields) {
|
||||
form.outcomes = this.getFormDefinitionOutcomes(form);
|
||||
}
|
||||
@@ -427,7 +433,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
*/
|
||||
getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] {
|
||||
return [
|
||||
new FormOutcomeModel(form, {id: '$custom', name: FormOutcomeModel.SAVE_ACTION, isSystem: true})
|
||||
new FormOutcomeModel(form, { id: '$custom', name: FormOutcomeModel.SAVE_ACTION, isSystem: true })
|
||||
];
|
||||
}
|
||||
|
||||
@@ -478,4 +484,29 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected onFormLoaded(form: FormModel) {
|
||||
this.formLoaded.emit(form);
|
||||
this.formService.formLoaded.next(new FormEvent(form));
|
||||
}
|
||||
|
||||
protected onTaskSaved(form: FormModel) {
|
||||
this.formSaved.emit(form);
|
||||
this.formService.taskSaved.next(new FormEvent(form));
|
||||
}
|
||||
|
||||
protected onTaskSavedError(form: FormModel, error: any) {
|
||||
this.handleError(error);
|
||||
this.formService.taskSavedError.next(new FormErrorEvent(form, error));
|
||||
}
|
||||
|
||||
protected onTaskCompleted(form: FormModel) {
|
||||
this.formCompleted.emit(form);
|
||||
this.formService.taskCompleted.next(new FormEvent(form));
|
||||
}
|
||||
|
||||
protected onTaskCompletedError(form: FormModel, error: any) {
|
||||
this.handleError(error);
|
||||
this.formService.taskCompletedError.next(new FormErrorEvent(form, error));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
alfresco-mdl-button
|
||||
[disabled]="!isOutcomeButtonEnabled(outcome)"
|
||||
[class.mdl-button--colored]="!outcome.isSystem"
|
||||
[class.activiti-form-hide-button]="!isOutcomeButtonVisible(outcome)"
|
||||
[class.activiti-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
|
||||
(click)="onOutcomeClicked(outcome, $event)">
|
||||
{{outcome.name}}
|
||||
</button>
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ describe('ActivitiStartForm', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreModule],
|
||||
imports: [CoreModule.forRoot()],
|
||||
declarations: [
|
||||
ActivitiStartForm,
|
||||
FormFieldComponent,
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
|
||||
import {
|
||||
Component,
|
||||
AfterViewChecked, OnChanges,
|
||||
AfterViewChecked,
|
||||
OnChanges,
|
||||
SimpleChanges,
|
||||
Input,
|
||||
ViewChild,
|
||||
@@ -25,10 +26,11 @@ import {
|
||||
Output,
|
||||
EventEmitter
|
||||
} from '@angular/core';
|
||||
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
|
||||
import { ActivitiForm } from './activiti-form.component';
|
||||
import { FormService } from './../services/form.service';
|
||||
import { WidgetVisibilityService } from './../services/widget-visibility.service';
|
||||
import { FormOutcomeModel } from './widgets/core/index';
|
||||
|
||||
/**
|
||||
* Displays the start form for a named process definition, which can be used to retrieve values to start a new process.
|
||||
@@ -67,6 +69,9 @@ export class ActivitiStartForm extends ActivitiForm implements AfterViewChecked,
|
||||
@Input()
|
||||
showRefreshButton: boolean = true;
|
||||
|
||||
@Input()
|
||||
readOnlyForm: boolean = false;
|
||||
|
||||
@Output()
|
||||
outcomeClick: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
@@ -75,12 +80,15 @@ export class ActivitiStartForm extends ActivitiForm implements AfterViewChecked,
|
||||
|
||||
constructor(private translate: AlfrescoTranslationService,
|
||||
formService: FormService,
|
||||
visibilityService: WidgetVisibilityService) {
|
||||
super(formService, visibilityService, null, null);
|
||||
visibilityService: WidgetVisibilityService,
|
||||
logService: LogService) {
|
||||
super(formService, visibilityService, null, null, logService);
|
||||
|
||||
if (this.translate) {
|
||||
this.translate.addTranslationFolder('ng2-activiti-form', 'node_modules/ng2-activiti-form/src');
|
||||
}
|
||||
|
||||
this.showTitle = false;
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
@@ -107,12 +115,11 @@ export class ActivitiStartForm extends ActivitiForm implements AfterViewChecked,
|
||||
this.formName = form.name;
|
||||
form.processDefinitionId = this.processDefinitionId;
|
||||
this.form = this.parseForm(form);
|
||||
this.form.readOnly = this.readOnlyForm;
|
||||
// this.form.processDefinitionId = this.processDefinitionId;
|
||||
this.formLoaded.emit(this.form);
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
}
|
||||
error => this.handleError(error)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -123,15 +130,38 @@ export class ActivitiStartForm extends ActivitiForm implements AfterViewChecked,
|
||||
form => {
|
||||
this.formName = form.processDefinitionName;
|
||||
this.form = this.parseForm(form);
|
||||
this.form.readOnly = this.readOnlyForm;
|
||||
this.formLoaded.emit(this.form);
|
||||
},
|
||||
(error) => {
|
||||
this.handleError(error);
|
||||
}
|
||||
error => this.handleError(error)
|
||||
);
|
||||
}
|
||||
|
||||
/** @override */
|
||||
isOutcomeButtonVisible(outcome: FormOutcomeModel, isFormReadOnly: boolean): boolean {
|
||||
if (outcome && outcome.isSystem && ( outcome.name === FormOutcomeModel.SAVE_ACTION ||
|
||||
outcome.name === FormOutcomeModel.COMPLETE_ACTION )) {
|
||||
return false;
|
||||
} else if (outcome && outcome.name === FormOutcomeModel.START_PROCESS_ACTION) {
|
||||
return true;
|
||||
}
|
||||
return super.isOutcomeButtonVisible(outcome, isFormReadOnly);
|
||||
}
|
||||
|
||||
/** @override */
|
||||
saveTaskForm() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** @override */
|
||||
onRefreshClicked() {
|
||||
if (this.processDefinitionId) {
|
||||
this.visibilityService.cleanProcessVariable();
|
||||
this.getStartFormDefinition(this.processDefinitionId);
|
||||
} else if (this.processId) {
|
||||
this.visibilityService.cleanProcessVariable();
|
||||
this.loadStartForm(this.processId);
|
||||
}
|
||||
}
|
||||
|
||||
completeTaskForm(outcome?: string) {
|
||||
|
||||
+7
-4
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { LogServiceMock } from 'ng2-alfresco-core';
|
||||
import { AttachWidget } from './attach.widget';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
@@ -28,10 +29,12 @@ describe('AttachWidget', () => {
|
||||
let widget: AttachWidget;
|
||||
let contentService: ActivitiAlfrescoContentService;
|
||||
let dialogPolyfill: any;
|
||||
let logService: LogServiceMock;
|
||||
|
||||
beforeEach(() => {
|
||||
contentService = new ActivitiAlfrescoContentService(null, null);
|
||||
widget = new AttachWidget(contentService);
|
||||
logService = new LogServiceMock();
|
||||
contentService = new ActivitiAlfrescoContentService(null, logService);
|
||||
widget = new AttachWidget(contentService, logService);
|
||||
|
||||
dialogPolyfill = {
|
||||
registerDialog(obj: any) {
|
||||
@@ -268,9 +271,9 @@ describe('AttachWidget', () => {
|
||||
Observable.throw(error)
|
||||
);
|
||||
|
||||
spyOn(console, 'log').and.stub();
|
||||
spyOn(logService, 'error').and.stub();
|
||||
widget.getExternalContentNodes();
|
||||
expect(console.log).toHaveBeenCalledWith(error);
|
||||
expect(logService.error).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('should register dialog via polyfill', () => {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, Input, Output, EventEmitter, ViewChild } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
import { ExternalContent } from '../core/external-content';
|
||||
@@ -49,7 +50,8 @@ export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
@ViewChild('dialog')
|
||||
dialog: any;
|
||||
|
||||
constructor(private contentService: ActivitiAlfrescoContentService) {
|
||||
constructor(private contentService: ActivitiAlfrescoContentService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -97,7 +99,7 @@ export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
this.contentService.getAlfrescoNodes(this.selectedFolderAccountId, this.selectedFolderPathId)
|
||||
.subscribe(
|
||||
nodes => this.selectedFolderNodes = nodes,
|
||||
error => this.handleError(error)
|
||||
error => this.logService.error(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,3 +18,7 @@
|
||||
.container-widget__header-text.collapsible {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.container-widget__mdl-grid {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,9 +11,9 @@
|
||||
<span (click)="onExpanderClicked()" id="container-header-label">{{content.name}}</span>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="mdl-grid" [ngClass]="{'hidden':!(content?.isVisible && content?.isExpanded)}">
|
||||
<div class="mdl-grid container-widget__mdl-grid" [ngClass]="{'hidden':!(content?.isVisible && content?.isExpanded)}">
|
||||
<div *ngFor="let col of content.columns" class="mdl-cell mdl-cell--{{col.size}}-col">
|
||||
<div class="mdl-grid" *ngIf="col.hasFields()">
|
||||
<div class="mdl-grid container-widget__mdl-grid" *ngIf="col.hasFields()">
|
||||
<div *ngFor="let field of col.fields" class="mdl-cell mdl-cell--12-col">
|
||||
<form-field [field]="field"></form-field>
|
||||
</div>
|
||||
|
||||
@@ -22,14 +22,17 @@ export class FormOutcomeModel extends FormWidgetModel {
|
||||
|
||||
static SAVE_ACTION: string = 'Save'; // Activiti 'Save' action name
|
||||
static COMPLETE_ACTION: string = 'Complete'; // Activiti 'Complete' action name
|
||||
static START_PROCESS_ACTION: string = 'Start Process'; // Activiti 'Start Process' action name
|
||||
|
||||
isSystem: boolean = false;
|
||||
isSelected: boolean = false;
|
||||
|
||||
constructor(form: FormModel, json?: any) {
|
||||
super(form, json);
|
||||
|
||||
if (json) {
|
||||
this.isSystem = json.isSystem ? true : false;
|
||||
this.isSelected = form && json.name === form.selectedOutcome ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,13 +270,16 @@ describe('FormModel', () => {
|
||||
};
|
||||
|
||||
let form = new FormModel(json);
|
||||
expect(form.outcomes.length).toBe(2);
|
||||
expect(form.outcomes.length).toBe(3);
|
||||
|
||||
expect(form.outcomes[0].id).toBe(FormModel.SAVE_OUTCOME);
|
||||
expect(form.outcomes[0].isSystem).toBeTruthy();
|
||||
|
||||
expect(form.outcomes[1].id).toBe(FormModel.COMPLETE_OUTCOME);
|
||||
expect(form.outcomes[1].isSystem).toBeTruthy();
|
||||
|
||||
expect(form.outcomes[2].id).toBe(FormModel.START_PROCESS_OUTCOME);
|
||||
expect(form.outcomes[2].isSystem).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should create outcomes only when fields available', () => {
|
||||
|
||||
@@ -23,12 +23,15 @@ import { FormOutcomeModel } from './form-outcome.model';
|
||||
import { FormFieldModel } from './form-field.model';
|
||||
import { FormFieldTypes } from './form-field-types';
|
||||
import { FormFieldTemplates } from './form-field-templates';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { FormFieldEvent } from './../../../events/index';
|
||||
|
||||
export class FormModel {
|
||||
|
||||
static UNSET_TASK_NAME: string = 'Nameless task';
|
||||
static SAVE_OUTCOME: string = '$save';
|
||||
static COMPLETE_OUTCOME: string = '$complete';
|
||||
static START_PROCESS_OUTCOME: string = '$startProcess';
|
||||
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
@@ -47,6 +50,7 @@ export class FormModel {
|
||||
fields: FormWidgetModel[] = [];
|
||||
outcomes: FormOutcomeModel[] = [];
|
||||
customFieldTemplates: FormFieldTemplates = {};
|
||||
readonly selectedOutcome: string;
|
||||
|
||||
values: FormValues = {};
|
||||
|
||||
@@ -64,7 +68,7 @@ export class FormModel {
|
||||
return this.outcomes && this.outcomes.length > 0;
|
||||
}
|
||||
|
||||
constructor(json?: any, data?: FormValues, readOnly: boolean = false) {
|
||||
constructor(json?: any, data?: FormValues, readOnly: boolean = false, protected formService?: FormService) {
|
||||
this.readOnly = readOnly;
|
||||
|
||||
if (json) {
|
||||
@@ -76,6 +80,7 @@ export class FormModel {
|
||||
this.taskName = json.taskName || json.name || FormModel.UNSET_TASK_NAME;
|
||||
this.processDefinitionId = json.processDefinitionId;
|
||||
this.customFieldTemplates = json.customFieldTemplates || {};
|
||||
this.selectedOutcome = json.selectedOutcome || {};
|
||||
|
||||
let tabCache: FormWidgetModelCache<TabModel> = {};
|
||||
|
||||
@@ -103,11 +108,12 @@ export class FormModel {
|
||||
if (json.fields) {
|
||||
let saveOutcome = new FormOutcomeModel(this, { id: FormModel.SAVE_OUTCOME, name: 'Save', isSystem: true });
|
||||
let completeOutcome = new FormOutcomeModel(this, {id: FormModel.COMPLETE_OUTCOME, name: 'Complete', isSystem: true });
|
||||
let startProcessOutcome = new FormOutcomeModel(this, { id: FormModel.START_PROCESS_OUTCOME, name: 'Start Process', isSystem: true });
|
||||
|
||||
let customOutcomes = (json.outcomes || []).map(obj => new FormOutcomeModel(this, obj));
|
||||
|
||||
this.outcomes = [saveOutcome].concat(
|
||||
customOutcomes.length > 0 ? customOutcomes : [completeOutcome]
|
||||
customOutcomes.length > 0 ? customOutcomes : [completeOutcome, startProcessOutcome]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -116,6 +122,9 @@ export class FormModel {
|
||||
|
||||
onFormFieldChanged(field: FormFieldModel) {
|
||||
this.validateField(field);
|
||||
if (this.formService) {
|
||||
this.formService.formFieldValueChanged.next(new FormFieldEvent(this, field));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: consider evaluating and caching once the form is loaded
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
.date-widget {
|
||||
width: 100%;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.date-widget--button {
|
||||
margin-top: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.mdl-date__input{
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.mdl-grid__date-widget{
|
||||
align-items:center;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.date-widget__invalid .mdl-textfield__input {
|
||||
@@ -21,3 +33,8 @@
|
||||
.date-widget__invalid .mdl-textfield__error {
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
.date-widget-button__cell{
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<div class="mdl-grid" *ngIf="field?.isVisible" id="data-widget">
|
||||
<div class="mdl-grid mdl-grid__date-widget" *ngIf="field?.isVisible" id="data-widget">
|
||||
<div class="mdl-cell mdl-cell--11-col">
|
||||
<div class="mdl-textfield mdl-js-textfield date-widget"
|
||||
[class.date-widget__invalid]="!field.isValid">
|
||||
<label [attr.for]="field.id">{{field.name}}</label>
|
||||
<input class="mdl-textfield__input"
|
||||
<input class="mdl-textfield__input mdl-date__input"
|
||||
type="text"
|
||||
[attr.id]="field.id"
|
||||
[attr.required]="isRequired()"
|
||||
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--1-col">
|
||||
<button
|
||||
class="mdl-button mdl-js-button mdl-button--icon date-widget--button"
|
||||
class="mdl-button mdl-js-button mdl-button--icon"
|
||||
(click)="datePicker.toggle()">
|
||||
<i class="material-icons">date_range</i>
|
||||
</button>
|
||||
|
||||
+8
-9
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { CoreModule, LogServiceMock } from 'ng2-alfresco-core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { DisplayValueWidget } from './display-value.widget';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
@@ -26,20 +26,19 @@ import { FormFieldTypes } from '../core/form-field-types';
|
||||
import { FormModel } from '../core/form.model';
|
||||
import { DynamicTableColumn, DynamicTableRow } from './../dynamic-table/dynamic-table.widget.model';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
import { AlfrescoSettingsService } from 'ng2-alfresco-core';
|
||||
|
||||
describe('DisplayValueWidget', () => {
|
||||
|
||||
let widget: DisplayValueWidget;
|
||||
let formService: FormService;
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
let settingsService: AlfrescoSettingsService;
|
||||
let logService: LogServiceMock;
|
||||
|
||||
beforeEach(() => {
|
||||
settingsService = new AlfrescoSettingsService();
|
||||
formService = new FormService(null, null);
|
||||
visibilityService = new WidgetVisibilityService(null);
|
||||
widget = new DisplayValueWidget(formService, visibilityService, settingsService);
|
||||
logService = new LogServiceMock();
|
||||
formService = new FormService(null, null, logService);
|
||||
visibilityService = new WidgetVisibilityService(null, logService);
|
||||
widget = new DisplayValueWidget(formService, visibilityService, logService);
|
||||
});
|
||||
|
||||
it('should require field to setup default value', () => {
|
||||
@@ -393,7 +392,7 @@ describe('DisplayValueWidget', () => {
|
||||
Observable.throw(error)
|
||||
);
|
||||
|
||||
spyOn(console, 'log').and.stub();
|
||||
spyOn(logService, 'error').and.stub();
|
||||
|
||||
let form = new FormModel({taskId: '<id>'});
|
||||
|
||||
@@ -409,7 +408,7 @@ describe('DisplayValueWidget', () => {
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||
expect(console.log).toHaveBeenCalledWith(error);
|
||||
expect(logService.error).toHaveBeenCalledWith(error);
|
||||
expect(widget.value).toBe('100');
|
||||
});
|
||||
|
||||
|
||||
+7
-5
@@ -16,14 +16,14 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import * as moment from 'moment';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
import { DynamicTableColumn, DynamicTableRow } from './../dynamic-table/dynamic-table.widget.model';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
import { AlfrescoSettingsService } from 'ng2-alfresco-core';
|
||||
import * as moment from 'moment';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
@@ -51,7 +51,7 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
constructor(private formService: FormService,
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private settingsService: AlfrescoSettingsService) {
|
||||
private logService: LogService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -181,9 +181,10 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
} else {
|
||||
this.value = this.field.value;
|
||||
}
|
||||
this.visibilityService.refreshVisibility(this.field.form);
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
this.logService.error(error);
|
||||
this.value = this.field.value;
|
||||
}
|
||||
);
|
||||
@@ -202,9 +203,10 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
} else {
|
||||
this.value = this.field.value;
|
||||
}
|
||||
this.visibilityService.refreshVisibility(this.field.form);
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
this.logService.error(error);
|
||||
this.value = this.field.value;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
.dropdown-widget {
|
||||
width: 100%;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.dropdown-widget__select {
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.dropdown-widget__invalid .dropdown-widget__select {
|
||||
|
||||
+5
-11
@@ -15,14 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { DropdownWidget } from './dropdown.widget';
|
||||
import { FormModel } from './../core/form.model';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { EcmModelService } from '../../../services/ecm-model.service';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
|
||||
@@ -33,9 +33,9 @@ describe('DropdownWidget', () => {
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
|
||||
beforeEach(() => {
|
||||
formService = new FormService(null, null);
|
||||
visibilityService = new WidgetVisibilityService(null);
|
||||
widget = new DropdownWidget(formService, visibilityService);
|
||||
formService = new FormService(null, null, null);
|
||||
visibilityService = new WidgetVisibilityService(null, null);
|
||||
widget = new DropdownWidget(formService, visibilityService, null);
|
||||
widget.field = new FormFieldModel(new FormModel());
|
||||
});
|
||||
|
||||
@@ -74,12 +74,6 @@ describe('DropdownWidget', () => {
|
||||
expect(formService.getRestFieldValues).toHaveBeenCalledWith(taskId, fieldId);
|
||||
});
|
||||
|
||||
it('should log error to console by default', () => {
|
||||
spyOn(console, 'error').and.stub();
|
||||
widget.handleError('Err');
|
||||
expect(console.error).toHaveBeenCalledWith('Err');
|
||||
});
|
||||
|
||||
it('should preserve empty option when loading fields', () => {
|
||||
let restFieldValue: FormFieldOption = <FormFieldOption> { id: '1', name: 'Option1' };
|
||||
spyOn(formService, 'getRestFieldValues').and.returnValue(
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
@@ -30,7 +31,8 @@ import { WidgetVisibilityService } from '../../../services/widget-visibility.ser
|
||||
export class DropdownWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
constructor(private formService: FormService,
|
||||
private visibilityService: WidgetVisibilityService) {
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -59,7 +61,7 @@ export class DropdownWidget extends WidgetComponent implements OnInit {
|
||||
this.field.options = options.concat((result || []));
|
||||
this.field.updateForm();
|
||||
},
|
||||
this.handleError
|
||||
err => this.handleError(err)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -78,7 +80,7 @@ export class DropdownWidget extends WidgetComponent implements OnInit {
|
||||
this.field.options = options.concat((result || []));
|
||||
this.field.updateForm();
|
||||
},
|
||||
this.handleError
|
||||
err => this.handleError(err)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,7 +99,7 @@ export class DropdownWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
|
||||
handleError(error: any) {
|
||||
console.error(error);
|
||||
this.logService.error(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-4
@@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { LogServiceMock } from 'ng2-alfresco-core';
|
||||
import { DynamicTableWidget } from './dynamic-table.widget';
|
||||
import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './dynamic-table.widget.model';
|
||||
import { FormModel, FormFieldTypes } from './../core/index';
|
||||
@@ -25,11 +26,13 @@ describe('DynamicTableWidget', () => {
|
||||
let widget: DynamicTableWidget;
|
||||
let table: DynamicTableModel;
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
let logService: LogServiceMock;
|
||||
|
||||
beforeEach(() => {
|
||||
logService = new LogServiceMock();
|
||||
table = new DynamicTableModel(null);
|
||||
visibilityService = new WidgetVisibilityService(null);
|
||||
widget = new DynamicTableWidget(null, visibilityService);
|
||||
visibilityService = new WidgetVisibilityService(null, logService);
|
||||
widget = new DynamicTableWidget(null, visibilityService, logService);
|
||||
widget.content = table;
|
||||
});
|
||||
|
||||
@@ -192,13 +195,13 @@ describe('DynamicTableWidget', () => {
|
||||
});
|
||||
|
||||
it('should require table to save changes', () => {
|
||||
spyOn(console, 'log').and.stub();
|
||||
spyOn(logService, 'error').and.stub();
|
||||
widget.editMode = true;
|
||||
widget.content = null;
|
||||
widget.onSaveChanges();
|
||||
|
||||
expect(widget.editMode).toBeFalsy();
|
||||
expect(console.log).toHaveBeenCalledWith(widget.ERROR_MODEL_NOT_FOUND);
|
||||
expect(logService.error).toHaveBeenCalledWith(widget.ERROR_MODEL_NOT_FOUND);
|
||||
});
|
||||
|
||||
it('should cancel changes', () => {
|
||||
|
||||
+4
-2
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, ElementRef, OnInit } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './dynamic-table.widget.model';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
@@ -36,7 +37,8 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit {
|
||||
editRow: DynamicTableRow = null;
|
||||
|
||||
constructor(private elementRef: ElementRef,
|
||||
private visibilityService: WidgetVisibilityService) {
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -136,7 +138,7 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
this.content.flushValue();
|
||||
} else {
|
||||
this.handleError(this.ERROR_MODEL_NOT_FOUND);
|
||||
this.logService.error(this.ERROR_MODEL_NOT_FOUND);
|
||||
}
|
||||
this.editMode = false;
|
||||
}
|
||||
|
||||
+2
-2
@@ -39,7 +39,7 @@ describe('DropdownEditorComponent', () => {
|
||||
let row: DynamicTableRow;
|
||||
|
||||
beforeEach(() => {
|
||||
formService = new FormService(null, null);
|
||||
formService = new FormService(null, null, null);
|
||||
|
||||
row = <DynamicTableRow> { value: { dropdown: 'one' } };
|
||||
column = <DynamicTableColumn> {
|
||||
@@ -56,7 +56,7 @@ describe('DropdownEditorComponent', () => {
|
||||
table.rows.push(row);
|
||||
table.columns.push(column);
|
||||
|
||||
component = new DropdownEditorComponent(formService);
|
||||
component = new DropdownEditorComponent(formService, null);
|
||||
component.table = table;
|
||||
component.row = row;
|
||||
component.column = column;
|
||||
|
||||
+5
-2
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { DynamicTableModel, DynamicTableRow, DynamicTableColumn, DynamicTableColumnOption } from './../../dynamic-table.widget.model';
|
||||
import { FormService } from './../../../../../services/form.service';
|
||||
|
||||
@@ -39,7 +40,9 @@ export class DropdownEditorComponent implements OnInit {
|
||||
@Input()
|
||||
column: DynamicTableColumn;
|
||||
|
||||
constructor(private formService: FormService) {}
|
||||
constructor(private formService: FormService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
let field = this.table.field;
|
||||
@@ -98,6 +101,6 @@ export class DropdownEditorComponent implements OnInit {
|
||||
}
|
||||
|
||||
handleError(error: any) {
|
||||
console.error(error);
|
||||
this.logService.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ describe('FunctionalGroupWidget', () => {
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
|
||||
formService = new FormService(null, null);
|
||||
formService = new FormService(null, null, null);
|
||||
elementRef = new ElementRef(null);
|
||||
widget = new FunctionalGroupWidget(formService, elementRef);
|
||||
widget.field = new FormFieldModel(new FormModel());
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ describe('PeopleWidget', () => {
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
|
||||
formService = new FormService(null, null);
|
||||
formService = new FormService(null, null, null);
|
||||
elementRef = new ElementRef(null);
|
||||
widget = new PeopleWidget(formService, elementRef);
|
||||
widget.field = new FormFieldModel(new FormModel());
|
||||
|
||||
+11
-8
@@ -15,13 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { CoreModule, LogServiceMock } from 'ng2-alfresco-core';
|
||||
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { RadioButtonsWidget } from './radio-buttons.widget';
|
||||
import { FormModel } from './../core/form.model';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { CoreModule } from 'ng2-alfresco-core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { EcmModelService } from '../../../services/ecm-model.service';
|
||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
@@ -33,11 +34,13 @@ describe('RadioButtonsWidget', () => {
|
||||
let formService: FormService;
|
||||
let widget: RadioButtonsWidget;
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
let logService: LogServiceMock;
|
||||
|
||||
beforeEach(() => {
|
||||
formService = new FormService(null, null);
|
||||
visibilityService = new WidgetVisibilityService(null);
|
||||
widget = new RadioButtonsWidget(formService, visibilityService);
|
||||
logService = new LogServiceMock();
|
||||
formService = new FormService(null, null, logService);
|
||||
visibilityService = new WidgetVisibilityService(null, logService);
|
||||
widget = new RadioButtonsWidget(formService, visibilityService, logService);
|
||||
widget.field = new FormFieldModel(new FormModel(), { restUrl: '<url>' });
|
||||
});
|
||||
|
||||
@@ -118,12 +121,12 @@ describe('RadioButtonsWidget', () => {
|
||||
});
|
||||
|
||||
it('should log error to console by default', () => {
|
||||
spyOn(console, 'error').and.stub();
|
||||
spyOn(logService, 'error').and.stub();
|
||||
widget.handleError('Err');
|
||||
expect(console.error).toHaveBeenCalledWith('Err');
|
||||
expect(logService.error).toHaveBeenCalledWith('Err');
|
||||
});
|
||||
|
||||
it('should update the field value when an option is selected', () => {
|
||||
xit('should update the field value when an option is selected', () => {
|
||||
spyOn(widget, 'checkVisibility').and.stub();
|
||||
widget.onOptionClick('fake-opt');
|
||||
|
||||
|
||||
+6
-4
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { LogService } from 'ng2-alfresco-core';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
@@ -30,7 +31,8 @@ import { WidgetVisibilityService } from '../../../services/widget-visibility.ser
|
||||
export class RadioButtonsWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
constructor(private formService: FormService,
|
||||
private visibilityService: WidgetVisibilityService) {
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private logService: LogService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -55,7 +57,7 @@ export class RadioButtonsWidget extends WidgetComponent implements OnInit {
|
||||
this.field.options = result || [];
|
||||
this.field.updateForm();
|
||||
},
|
||||
this.handleError
|
||||
err => this.handleError(err)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,7 +72,7 @@ export class RadioButtonsWidget extends WidgetComponent implements OnInit {
|
||||
this.field.options = result || [];
|
||||
this.field.updateForm();
|
||||
},
|
||||
this.handleError
|
||||
err => this.handleError(err)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -84,7 +86,7 @@ export class RadioButtonsWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
|
||||
handleError(error: any) {
|
||||
console.error(error);
|
||||
this.logService.error(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user